Skip to content

Commit 46b27ee

Browse files
authored
Merge pull request #37630: Improve RateLimiter Config in terraform example
2 parents bab2374 + 9ac321a commit 46b27ee

4 files changed

Lines changed: 113 additions & 54 deletions

File tree

examples/terraform/envoy-ratelimiter/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ Apache Beam pipelines often process data at massive scale, which can easily over
2525

2626
This Terraform module deploys a **centralized Rate Limit Service (RLS)** using Envoy. Beam workers can query this service to coordinate global quotas across thousands of distributed workers, ensuring you stay within safe API limits without hitting `429 Too Many Requests` errors.
2727

28-
Example Beam Pipelines using it:
28+
Example Beam Python Pipelines using it:
2929
* [Simple DoFn RateLimiter](https://github.com/apache/beam/blob/master/sdks/python/apache_beam/examples/rate_limiter_simple.py)
3030
* [Vertex AI RateLimiter](https://github.com/apache/beam/blob/master/sdks/python/apache_beam/examples/inference/rate_limiter_vertex_ai.py)
3131

32+
Example Beam Java Pipelines using it:
33+
* [Simple DoFn RateLimiter](https://github.com/apache/beam/blob/master/examples/java/src/main/java/org/apache/beam/examples/RateLimiterSimple.java)
34+
3235
## Architectures:
3336
- **GKE Autopilot**: Fully managed, serverless Kubernetes environment.
3437
- **Private Cluster**: Nodes have internal IPs only.
@@ -78,6 +81,8 @@ region = "us-central1" # GCP Region for deployment
7881
cluster_name = "ratelimit-cluster" # Name of the GKE cluster
7982
deletion_protection = true # Prevent accidental cluster deletion (set "true" for prod)
8083
control_plane_cidr = "172.16.0.0/28" # CIDR for GKE control plane (must not overlap with subnet)
84+
namespace = "envoy-ratelimiter" # Kubernetes namespace for deployment
85+
enable_metrics = false # Deploy statsd-exporter sidecar
8186
ratelimit_replicas = 1 # Initial number of Rate Limit pods
8287
min_replicas = 1 # Minimum HPA replicas
8388
max_replicas = 5 # Maximum HPA replicas
@@ -163,6 +168,8 @@ terraform destroy
163168
|region |GCP Region for deployment |us-central1 |
164169
|control_plane_cidr |CIDR block for GKE control plane |172.16.0.0/28 |
165170
|cluster_name |Name of the GKE cluster |ratelimit-cluster |
171+
|namespace |Kubernetes namespace to deploy resources into |envoy-ratelimiter |
172+
|enable_metrics |Deploy statsd-exporter sidecar |false |
166173
|deletion_protection |Prevent accidental cluster deletion |false |
167174
|ratelimit_replicas |Initial number of Rate Limit pods |1 |
168175
|min_replicas |Minimum HPA replicas |1 |

examples/terraform/envoy-ratelimiter/gke.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ resource "google_container_cluster" "primary" {
3131

3232
# Private Cluster Configuration
3333
private_cluster_config {
34-
enable_private_nodes = true # Nodes have internal IPs only
35-
enable_private_endpoint = false # Master is accessible via Public IP (required for Terraform from outside VPC)
34+
enable_private_nodes = true # Nodes have internal IPs only
35+
enable_private_endpoint = false # Master is accessible via Public IP (required for Terraform from outside VPC)
3636
master_ipv4_cidr_block = var.control_plane_cidr
3737
}
3838
}

examples/terraform/envoy-ratelimiter/ratelimit.tf

Lines changed: 89 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,35 @@ resource "time_sleep" "wait_for_cluster" {
2525
depends_on = [google_container_cluster.primary]
2626
}
2727

28+
# Namespace
29+
resource "kubernetes_namespace" "ratelimit_namespace" {
30+
metadata {
31+
name = var.namespace
32+
}
33+
34+
depends_on = [time_sleep.wait_for_cluster]
35+
}
36+
37+
2838
# ConfigMap
2939
resource "kubernetes_config_map" "ratelimit_config" {
3040
metadata {
31-
name = "ratelimit-config"
41+
name = "ratelimit-config"
42+
namespace = var.namespace
3243
}
3344

3445
data = {
3546
"config.yaml" = var.ratelimit_config_yaml
3647
}
3748

38-
depends_on = [time_sleep.wait_for_cluster]
49+
depends_on = [kubernetes_namespace.ratelimit_namespace]
3950
}
4051

4152
# Redis Deployment
4253
resource "kubernetes_deployment" "redis" {
4354
metadata {
44-
name = "redis"
55+
name = "redis"
56+
namespace = var.namespace
4557
labels = {
4658
app = "redis"
4759
}
@@ -81,13 +93,14 @@ resource "kubernetes_deployment" "redis" {
8193
}
8294
}
8395

84-
depends_on = [time_sleep.wait_for_cluster]
96+
depends_on = [kubernetes_namespace.ratelimit_namespace]
8597
}
8698

8799
# Redis Service
88100
resource "kubernetes_service" "redis" {
89101
metadata {
90-
name = "redis"
102+
name = "redis"
103+
namespace = var.namespace
91104
}
92105

93106
spec {
@@ -101,13 +114,14 @@ resource "kubernetes_service" "redis" {
101114
}
102115
}
103116

104-
depends_on = [time_sleep.wait_for_cluster]
117+
depends_on = [kubernetes_namespace.ratelimit_namespace]
105118
}
106119

107120
# Rate Limit Deployment
108121
resource "kubernetes_deployment" "ratelimit" {
109122
metadata {
110-
name = "ratelimit"
123+
name = "ratelimit"
124+
namespace = var.namespace
111125
labels = {
112126
app = "ratelimit"
113127
}
@@ -131,8 +145,8 @@ resource "kubernetes_deployment" "ratelimit" {
131145

132146
spec {
133147
container {
134-
name = "ratelimit"
135-
image = var.ratelimit_image
148+
name = "ratelimit"
149+
image = var.ratelimit_image
136150
command = ["/bin/ratelimit"]
137151

138152
port {
@@ -147,7 +161,15 @@ resource "kubernetes_deployment" "ratelimit" {
147161

148162
env {
149163
name = "USE_STATSD"
150-
value = "true"
164+
value = var.enable_metrics ? "true" : "false"
165+
}
166+
env {
167+
name = "DISABLE_STATS"
168+
value = var.enable_metrics ? "false" : "true"
169+
}
170+
env {
171+
name = "LOG_FORMAT"
172+
value = "json"
151173
}
152174
env {
153175
name = "LOG_LEVEL"
@@ -209,28 +231,38 @@ resource "kubernetes_deployment" "ratelimit" {
209231
}
210232
}
211233

212-
container {
213-
name = "statsd-exporter"
214-
image = var.statsd_exporter_image
215-
216-
port {
217-
name = "metrics"
218-
container_port = 9102
219-
}
220-
port {
221-
name = "statsd-udp"
222-
container_port = 9125
223-
protocol = "UDP"
224-
}
225-
# statsd-exporter does not use much resources, so setting resources to the minimum
226-
resources {
227-
requests = {
228-
cpu = "50m"
229-
memory = "64Mi"
234+
dynamic "container" {
235+
for_each = var.enable_metrics ? [1] : []
236+
content {
237+
name = "statsd-exporter"
238+
image = var.statsd_exporter_image
239+
args = ["--log.format=json"]
240+
241+
dynamic "port" {
242+
for_each = var.enable_metrics ? [1] : []
243+
content {
244+
name = "metrics"
245+
container_port = 9102
246+
}
247+
}
248+
dynamic "port" {
249+
for_each = var.enable_metrics ? [1] : []
250+
content {
251+
name = "statsd-udp"
252+
container_port = 9125
253+
protocol = "UDP"
254+
}
230255
}
231-
limits = {
232-
cpu = "100m"
233-
memory = "128Mi"
256+
# statsd-exporter does not use much resources, so setting resources to the minimum
257+
resources {
258+
requests = {
259+
cpu = "50m"
260+
memory = "64Mi"
261+
}
262+
limits = {
263+
cpu = "100m"
264+
memory = "128Mi"
265+
}
234266
}
235267
}
236268
}
@@ -246,7 +278,7 @@ resource "kubernetes_deployment" "ratelimit" {
246278
}
247279

248280
depends_on = [
249-
time_sleep.wait_for_cluster,
281+
kubernetes_namespace.ratelimit_namespace,
250282
kubernetes_config_map.ratelimit_config,
251283
kubernetes_service.redis
252284
]
@@ -258,7 +290,8 @@ resource "kubernetes_deployment" "ratelimit" {
258290

259291
resource "kubernetes_horizontal_pod_autoscaler_v2" "ratelimit" {
260292
metadata {
261-
name = "ratelimit-hpa"
293+
name = "ratelimit-hpa"
294+
namespace = var.namespace
262295
}
263296

264297
spec {
@@ -274,7 +307,7 @@ resource "kubernetes_horizontal_pod_autoscaler_v2" "ratelimit" {
274307
metric {
275308
type = "Resource"
276309
resource {
277-
name = "cpu"
310+
name = "cpu"
278311
target {
279312
type = "Utilization"
280313
average_utilization = var.hpa_cpu_target_percentage
@@ -285,7 +318,7 @@ resource "kubernetes_horizontal_pod_autoscaler_v2" "ratelimit" {
285318
metric {
286319
type = "Resource"
287320
resource {
288-
name = "memory"
321+
name = "memory"
289322
target {
290323
type = "Utilization"
291324
average_utilization = var.hpa_memory_target_percentage
@@ -294,13 +327,14 @@ resource "kubernetes_horizontal_pod_autoscaler_v2" "ratelimit" {
294327
}
295328
}
296329

297-
depends_on = [time_sleep.wait_for_cluster]
330+
depends_on = [kubernetes_namespace.ratelimit_namespace]
298331
}
299332

300333
# Rate Limit Internal Service
301334
resource "kubernetes_service" "ratelimit" {
302335
metadata {
303-
name = "ratelimit"
336+
name = "ratelimit"
337+
namespace = var.namespace
304338
}
305339

306340
spec {
@@ -323,20 +357,24 @@ resource "kubernetes_service" "ratelimit" {
323357
port = 6070
324358
target_port = 6070
325359
}
326-
port {
327-
name = "metrics"
328-
port = 9102
329-
target_port = 9102
360+
dynamic "port" {
361+
for_each = var.enable_metrics ? [1] : []
362+
content {
363+
name = "metrics"
364+
port = 9102
365+
target_port = 9102
366+
}
330367
}
331368
}
332369

333-
depends_on = [time_sleep.wait_for_cluster]
370+
depends_on = [kubernetes_namespace.ratelimit_namespace]
334371
}
335372

336373
# Rate Limit External Service (LoadBalancer)
337374
resource "kubernetes_service" "ratelimit_external" {
338375
metadata {
339-
name = "ratelimit-external"
376+
name = "ratelimit-external"
377+
namespace = var.namespace
340378
annotations = {
341379
"networking.gke.io/load-balancer-type" = "Internal"
342380
}
@@ -360,12 +398,15 @@ resource "kubernetes_service" "ratelimit_external" {
360398
port = 6070
361399
target_port = 6070
362400
}
363-
port {
364-
name = "metrics"
365-
port = 9102
366-
target_port = 9102
401+
dynamic "port" {
402+
for_each = var.enable_metrics ? [1] : []
403+
content {
404+
name = "metrics"
405+
port = 9102
406+
target_port = 9102
407+
}
367408
}
368409
}
369410

370-
depends_on = [time_sleep.wait_for_cluster]
411+
depends_on = [kubernetes_namespace.ratelimit_namespace]
371412
}

examples/terraform/envoy-ratelimiter/variables.tf

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ variable "hpa_memory_target_percentage" {
107107
variable "ratelimit_image" {
108108
description = "Docker image for Envoy Rate Limit service"
109109
type = string
110-
default = "envoyproxy/ratelimit:e9ce92cc"
110+
default = "envoyproxy/ratelimit:e9ce92cc"
111111
}
112112

113113
variable "redis_image" {
@@ -125,7 +125,7 @@ variable "statsd_exporter_image" {
125125
variable "ratelimit_log_level" {
126126
description = "Log level for ratelimit service"
127127
type = string
128-
default = "debug"
128+
default = "info"
129129
}
130130

131131
variable "ratelimit_grpc_max_connection_age" {
@@ -175,4 +175,15 @@ variable "ratelimit_resources" {
175175
memory = "512Mi"
176176
}
177177
}
178-
}
178+
}
179+
variable "namespace" {
180+
description = "The Kubernetes namespace to deploy resources into"
181+
type = string
182+
default = "envoy-ratelimiter"
183+
}
184+
185+
variable "enable_metrics" {
186+
description = "Whether to deploy the statsd-exporter sidecar for Prometheus metrics"
187+
type = bool
188+
default = false
189+
}

0 commit comments

Comments
 (0)