Sidecar Envoy cho Kubernetes: Quản lý egress proxy rotating residential
22 tháng 10, 2026
Giới thiệu
Khi chạy nhiều microservice cần truy cập tài nguyên bên ngoài – API công khai, dịch vụ quảng cáo, hay trang web thương mại điện tử – việc để từng pod tự quản lý proxy dẫn đến cấu hình lặp lại, khó quan sát và dễ gây rò rỉ IP. Giải pháp phổ biến trong môi trường cloud‑native là triển khai Envoy sidecar cùng mỗi workload. Sidecar đóng vai trò là điểm xuất (egress) duy nhất, áp dụng chính sách xoay IP, kiểm tra sức khỏe và xuất metric tập trung. Bài viết đi sâu vào cách xây dựng sidecar này cho pool proxy residential xoay vòng, từ cấu hình Envoy bootstrap đến integration với Prometheus/OpenTelemetry.
Tại sao dùng sidecar proxy?
- Tách biệt logic proxy – Ứng dụng chỉ cần gọi
http://localhost:8080; sidecar lo toàn bộ việc chọn IP, thêm header xác thực, xử lý retry. - Chính sách thống nhất – Rate limit, circuit breaker, TLS termination được định nghĩa một lần ở Envoy thay vì lặp lại trong code Python/Node.js.
- Quan sát tập trung – Metrics latency, error rate, pool size hiển thị trên Grafana cho toàn cluster.
- Bảo mật – Credentials proxy (user/pass hoặc token) chỉ tồn tại trong ConfigMap/Secret của sidecar, không lộ ra container ứng dụng.
Kiến trúc tổng quan
+----------------+ +-------------------+ +-------------------+
| App Container | ---> | Envoy Sidecar | ---> | Rotating Proxy |
| (scraper, bot) | | (listener 8080) | | Pool (residential)|
+----------------+ +-------------------+ +-------------------+
| | |
| OpenTelemetry SDK | |
v v v
+----------------+ +-------------------+ +-------------------+
| OTel Collector | ---> | Prometheus | ---> | Grafana / Alertmanager |
+----------------+ +-------------------+ +-------------------+
- App Container – không nhận biết proxy; gửi request HTTP bình thường.
- Envoy Sidecar – listener inbound trên
0.0.0.0:8080, cluster outbound trỏ đến upstream pool. - Rotating Proxy Pool – có thể là API của nhà cung cấp residential trả về danh sách
ip:porttheo TTL, hoặc một service nội bộ quản lý vòng đời IP. - OTel Collector – thu thập trace/metric từ Envoy (Envoy hỗ trợ OTLP native) và forward sang Prometheus.
Cài đặt Envoy sidecar
1. Chuẩn bị ConfigMap cho Envoy bootstrap
Tạo file envoy-bootstrap.yaml chứa cấu hình listener, cluster và health‑check. Envoy sẽ nhận request từ app, chọn upstream theo round‑robin weighted bằng endpoint được cập nhật động qua EDS (Endpoint Discovery Service) hoặc đơn giản là static list với health_check định kỳ.
# envoy-bootstrap.yaml
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 127.0.0.1
port_value: 9901
static_resources:
listeners:
- name: inbound_http
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: inbound_http
route_config:
name: local_route
virtual_hosts:
- name: egress_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: rotating_proxy_cluster
retry_policy:
retry_on: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes
num_retries: 3
per_try_timeout: 2s
http_filters:
- name: envoy.filters.http.router
clusters:
- name: rotating_proxy_cluster
type: EDS
eds_cluster_config:
service_name: rotating_proxy
eds_config:
ads: {}
lb_policy: ROUND_ROBIN
health_checks:
- timeout: 2s
interval: 10s
unhealthy_threshold: 2
healthy_threshold: 1
http_health_check:
path: "/health"
expected_statuses: ["200"]
outlier_detection:
consecutive_5xx: 3
interval: 10s
base_ejection_time: 30s
max_ejection_percent: 50
Giải thích:
- Listener
inbound_httpnhận traffic từ app trên cổng 8080. - Route trỏ tới cluster
rotating_proxy_clusterkiểu EDS – cho phép cập nhật endpoint mà không restart Envoy. retry_policyvàoutlier_detectiontự động loại IP lỗi 5xx hoặc timeout.- Health‑check HTTP
/healthtrên từng IP proxy (nhà cung cấp thường expose endpoint này) giúp Envoy biết IP còn sống.
2. Cung cấp endpoint động qua EDS (hoặc SDS)
Nếu nhà cung cấp proxy có API trả về danh sách IP mới mỗi 5 phút, bạn có thể chạy một EDS server nhẹ (Go/Python) đọc API, render thành định dạng ClusterLoadAssignment và serve gRPC cho Envoy. Ví dụ Python minimal:
# eds_server.py
import grpc, time, requests
from envoy.service.endpoint.v3 import endpoint_pb2, endpoint_pb2_grpc
class EndpointService(endpoint_pb2_grpc.EndpointDiscoveryServiceServicer):
def StreamEndpoints(self, request_iterator, context):
while True:
resp = requests.get("https://api.proxyvendor.com/v1/ips", timeout=5).json()
endpoints = []
for item in resp["data"]:
endpoints.append(endpoint_pb2.LbEndpoint(
endpoint=endpoint_pb2.Endpoint(
address=endpoint_pb2.Address(
socket_address=endpoint_pb2.SocketAddress(
address=item["ip"],
port_value=item["port"]
)
)
)
))
assignment = endpoint_pb2.ClusterLoadAssignment(
cluster_name="rotating_proxy",
endpoints=[endpoint_pb2.LocalityLbEndpoints(lb_endpoints=endpoints)]
)
yield endpoint_pb2.EndpointResponse(endpoints=[assignment])
time.sleep(300) # 5 phút
server = grpc.server(futures.ThreadPoolExecutor(max_workers=2))
endpoint_pb2_grpc.add_EndpointDiscoveryServiceServicer_to_server(EndpointService(), server)
server.add_insecure_port('[::]:18000')
server.start()
server.wait_for_termination()
Deploy EDS server dưới dạng Deployment riêng, sau đó trỏ eds_config.ads trong bootstrap Envoy tới service eds-server:18000.
3. Health‑check và circuit breaker tại tầng ứng dụng
Envoy đã có health‑check passively, nhưng bạn có thể bổ sung active health‑check từ sidecar tới từng IP proxy qua endpoint /health của proxy vendor. Nếu vendor không cung cấp, hãy tự triển khai một lightweight checker (curl) chạy trong sidecar container thứ hai (init container) và cập nhật label proxy-health trên EndpointSlice của Kubernetes – Envoy sẽ đọc qua EDS.
Xuất metric ra Prometheus/OpenTelemetry
Envoy hỗ trợ statsd, Prometheus (/stats/prometheus) và OpenTelemetry (OTLP) ngay trong binary. Cách đơn giản nhất cho stack Kubernetes là bật Prometheus endpoint và scrape bởi Prometheus Operator.
Thêm vào bootstrap:
stats_sinks:
- name: envoy.stat_sinks.prometheus
typed_config:
"@type": type.googleapis.com/envoy.config.metrics.v3.PrometheusSink
emit_labels: true
Sau đó tạo ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: envoy-sidecar
labels:
release: prometheus
spec:
selector:
matchLabels:
app: my-scraper
endpoints:
- port: envoy-prom
path: /stats/prometheus
interval: 15s
Metrics quan trọng:
envoy_cluster_upstream_rq_total– tổng request per upstream IP.envoy_cluster_upstream_rq_time_bucket– histogram latency.envoy_cluster_upstream_cx_destroy_remote_active_rq– connection reset.envoy_cluster_membership_healthy– số IP healthy.
Với OpenTelemetry, bật otelcol sidecar cùng pod và cấu hình Envoy tracing để gửi trace OTLP:
tracing:
http:
name: envoy.tracers.opentelemetry
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig
grpc_service:
envoy_grpc:
cluster_name: otel_collector
Ví dụ triển khai hoàn chỉnh (Deployment YAML)
apiVersion: apps/v1
kind: Deployment
metadata:
name: scraper-deployment
spec:
replicas: 3
selector:
matchLabels:
app: scraper
template:
metadata:
labels:
app: scraper
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9901"
spec:
serviceAccountName: scraper-sa
containers:
- name: app
image: myorg/scraper:latest
env:
- name: HTTP_PROXY
value: "http://127.0.0.1:8080"
- name: HTTPS_PROXY
value: "http://127.0.0.1:8080"
ports:
- containerPort: 8000
- name: envoy
image: envoyproxy/envoy:v1.28-latest
args: ["-c", "/etc/envoy/envoy.yaml", "--service-cluster", "scraper"]
volumeMounts:
- name: envoy-config
mountPath: /etc/envoy
ports:
- containerPort: 8080
name: inbound
- containerPort: 9901
name: admin
- containerPort: 9100
name: prom
- name: eds-client
image: myorg/eds-client:latest # sidecar gọi EDS server để cập nhật endpoint
env:
- name: EDS_SERVER
value: "eds-server:18000"
volumes:
- name: envoy-config
configMap:
name: envoy-bootstrap
Lưu ý:
- Container
appchỉ cần setHTTP_PROXY/HTTPS_PROXYtrỏ về localhost:8080. envoycontainer mount ConfigMapenvoy-bootstrap(nội dung từ phần trước).eds-clientcó thể là một binary nhỏ gọi gRPC stream và ghi ra file/etc/envoy/eds.yamlđể Envoy reload qua--config-yaml(hoặc dùng xDS aggregation).
Kiểm thử và quan sát
- Deploy stack lên cluster (kube‑apply).
- Port‑forward Envoy admin:
kubectl port-forward pod/<pod> 9901:9901và truy cậphttp://localhost:9901/stats/prometheusđể thấy metric. - Tạo request từ app:
curl -x http://127.0.0.1:8080 https://httpbin.org/ip. Kiểm tra log Envoy (kubectl logs -c envoy <pod>) – bạn sẽ thấy upstream IP được chọn. - Grafana dashboard – import dashboard Envoy (ID 13277) và thêm panel:
rate(envoy_cluster_upstream_rq_total{cluster="rotating_proxy_cluster"}[1m])– RPS per IP.histogram_quantile(0.95, sum(rate(envoy_cluster_upstream_rq_time_bucket{cluster="rotating_proxy_cluster"}[5m])) by (le, upstream_host))– p95 latency per IP.envoy_cluster_membership_healthy{cluster="rotating_proxy_cluster"}– số IP healthy.
- Alerting – tạo rule Prometheus:
- alert: ProxyHighErrorRate
expr: sum(rate(envoy_cluster_upstream_rq{cluster="rotating_proxy_cluster",response_code=~"5.."}[5m])) by (upstream_host) /
sum(rate(envoy_cluster_upstream_rq_total{cluster="rotating_proxy_cluster"}[5m])) by (upstream_host) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "Proxy {{ $labels.upstream_host }} error rate > 5%"
Best practices
- Tách ConfigMap theo môi trường – dev/staging/prod dùng bootstrap khác nhau (timeout, retry).
- Giới hạn cardinality label – chỉ label
upstream_host(IP:port) vàcluster; tránh labelpathhayquery. - Bucket histogram tuỳ chỉnh – thêm bucket 0.05, 0.1, 0.2, 0.5, 1, 2, 5s cho phù hợp latency proxy residential.
- Rotation TTL – cấu hình EDS server trả về
endpoint.ttl(Envoy 1.27+) để tự expire IP sau 5‑10 phút, tránh IP bị block. - Secret management – lưu username/password proxy trong
Secretvà mount vào Envoy quainline_bytestrongtransport_socket(TLS) hoặcmetadatađể Envoy thêm headerProxy-Authorizationtự động. - Canary rollout – khi thay đổi cấu hình Envoy, dùng
rolloutstrategymaxSurge: 25%,maxUnavailable: 0để không làm gián đoạn traffic. - Correlation ID – bật
request_id_headers: ["x-request-id"]trong HttpConnectionManager để trace end‑to‑end từ app qua sidecar đến target.
Kết luận
Việc đặt Envoy sidecar ở mọi pod Kubernetes biến việc quản lý proxy rotating residential từ "cài đặt thủ công từng script" thành một infrastructure as code có thể quan sát, tự động failover và scale. Chỉ với một ConfigMap bootstrap, một EDS server nhẹ và vài dòng Deployment YAML, bạn có được:
- Điểm egress duy nhất – ứng dụng không cần biết proxy.
- Health‑check & circuit breaker tích hợp sẵn – IP lỗi bị loại trong giây.
- Metric & trace chuẩn OpenTelemetry – dashboard realtime, alert tự động.
- Bảo mật credential – secret chỉ ở sidecar.
Hãy bắt đầu bằng cách thêm ConfigMap envoy-bootstrap vào repo GitOps, deploy EDS server và bật Prometheus scrape. Chi phí tích hợp khoảng vài giờ, nhưng giá trị vận hành (giảm 70% thời gian debug proxy, tăng success rate scraping từ 92% lên 98%) kéo dài suốt vòng đời dự án.