Home avatar

蜷缩的蜗牛

专注云原生运维

Envoy与Nginx正向代理压测方案

目标

  • 对比 Envoy 与 Nginx 在正向代理场景下的吞吐、延迟、失败率与连接行为(TIME_WAIT)。

环境

  • Envoy:监听 9094,管理口 9902,启用来源/目标 RBAC、动态前向代理(c-ares DNS)、访问日志与本地限流。
  • Nginx:监听 8080,启用 HTTP/1.1 长连接与 reuseport、CONNECT 支持,变量上游转发。
  • 系统(Linux 参考):ip_local_port_range=20000–65535tcp_tw_reuse=1tcp_timestamps=1tcp_max_tw_buckets=200000

指标采集

  • 吞吐与延迟:QPS、平均耗时、P50/P90/P99。
  • 失败率:HTTP 4xx/5xx 比例、连接错误(如 connect() failed)。
  • 连接行为:TIME_WAIT 总量与趋势。
  • 代理内部指标:
    • Envoy:curl http://localhost:9902/stats | head -n 200,关注 cluster.dynamic_forward_proxy_cluster.*dns_cache.*local_ratelimit.*http.*
    • Nginx:访问日志与错误日志,统计 5xx 与连接失败。

压测命令

  • HTTP(Envoy):
    • docker run --rm rakyll/hey -z 60s -c 200 -x http://host.docker.internal:9094 http://example.org/
  • HTTP(Nginx):
    • docker run --rm rakyll/hey -z 60s -c 200 -x http://host.docker.internal:8080 http://example.org/
  • HTTPS(CONNECT)功能验证(并发 curl):
    • docker run --rm curlimages/curl:8.5.0 -sS --proxy http://host.docker.internal:9094 https://ifconfig.io

TIME_WAIT 采样

  • macOS:watch -n 5 'netstat -an | grep TIME_WAIT | wc -l'
  • Linux:watch -n 5 'ss -tan state time-wait | wc -l'

输出记录模板

  • 工具命令、QPS、平均耗时、P95/P99、失败率、TIME_WAIT 初值/峰值/稳态值、Envoy/Nginx关键指标快照。

一键脚本

  • 路径:scripts/run_benchmark.sh
  • 使用:bash scripts/run_benchmark.sh
  • 可选参数(环境变量):
    • DURATION 压测时长秒(默认 60
    • CONCURRENCY 并发数(默认 200
    • TARGET HTTP目标(默认 http://example.org/
    • ENVOY_PROXY(默认 http://host.docker.internal:9094
    • NGINX_PROXY(默认 http://host.docker.internal:8080
    • CONNECT_TARGET(默认 https://ifconfig.io
    • CONNECT_COUNT(默认 50
    • CONNECT_PARALLEL(默认 10
  • 输出目录:docs/results/<timestamp>/,包含 hey 输出、TIME_WAIT 采样、Envoy stats 快照与 CONNECT 结果。

结论预期

  • Envoy:动态前向代理与连接合并带来更高复用率;在大量不同上游域名场景下,TIME_WAIT 峰值与稳态值更低,失败率更低,P99更稳。
  • Nginx:变量上游难以池化复用,可能导致频繁建连与大量 TIME_WAIT,高并发下更易受端口耗尽影响。

风险与注意

  • 白名单:测试目标域必须在 Envoy 白名单内,否则会被 RBAC 返回 403。
  • CONNECT:压测工具有限,建议以功能验证与失败率统计为主,配合 HTTP 压测综合判断。
  • 正则复杂度:避免单条 RE2 规则过大;当前已拆分并使用低复杂度通配(*.{region}.log.aliyuncs.com)。

可执行指引(一步步)

  • 前置条件

Envoy正向代理配置解析

概述

  • 本文解析当前 Envoy 正向代理的完整配置与设计考量,包含来源与目标的 RBAC、动态前向代理与 DNS 缓存、访问日志与限流等。

Envoy 完整配置

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9902
  access_log_path: /tmp/admin_access.log

layered_runtime:
  layers:
  - name: static-layer
    static_layer:
      envoy.resource_limits.listener.forward_proxy_listener.connection_limit: 5000
      overload.global_downstream_max_connections: 5000

static_resources:
  listeners:
  - name: forward_proxy_listener
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 9094
    enable_reuse_port: true
    filter_chains:
    - filters:
      - name: envoy.filters.network.rbac
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
          stat_prefix: inbound_rbac
          rules:
            action: ALLOW
            policies:
              allow_local_and_private:
                permissions:
                - any: true
                principals:
                - remote_ip:
                    address_prefix: 127.0.0.1
                    prefix_len: 32
                - remote_ip:
                    address_prefix: ::1
                    prefix_len: 128
                - remote_ip:
                    address_prefix: 10.0.0.0
                    prefix_len: 8
                - remote_ip:
                    address_prefix: 192.168.0.0
                    prefix_len: 16
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: forward_proxy
          codec_type: AUTO
          use_remote_address: true
          http_protocol_options:
            allow_absolute_url: true
          http2_protocol_options:
            allow_connect: true
          http3_protocol_options:
            allow_extended_connect: true
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: /dev/stdout
              log_format:
                json_format:
                  start_time: "%START_TIME%"
                  downstream_remote_address: "%DOWNSTREAM_REMOTE_ADDRESS%"
                  method: "%REQ(:METHOD)%"
                  authority: "%REQ(:AUTHORITY)%"
                  path: "%REQ(:PATH)%"
                  protocol: "%PROTOCOL%"
                  response_code: "%RESPONSE_CODE%"
                  response_flags: "%RESPONSE_FLAGS%"
                  bytes_received: "%BYTES_RECEIVED%"
                  bytes_sent: "%BYTES_SENT%"
                  duration_ms: "%DURATION%"
                  upstream_cluster: "%UPSTREAM_CLUSTER%"
                  upstream_host: "%UPSTREAM_HOST%"
                  upstream_service_time_ms: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%"
                  request_id: "%REQ(X-REQUEST-ID)%"
                  x_forwarded_for: "%REQ(X-FORWARDED-FOR)%"
          route_config:
            name: local_route
            virtual_hosts:
            - name: forward_proxy_vhost
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: dynamic_forward_proxy_cluster
              - match:
                  connect_matcher: {}
                route:
                  cluster: dynamic_forward_proxy_cluster
                  upgrade_configs:
                  - upgrade_type: CONNECT
                    connect_config: {}
          http_filters:
          - name: envoy.filters.http.rbac
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
              rules:
                action: DENY
                policies:
                  deny_sensitive_ip_targets:
                    permissions:
                    - or_rules:
                        rules:
                        - header:
                            name: ":authority"
                            exact_match: "localhost"
                        - header:
                            name: ":authority"
                            safe_regex_match:
                              google_re2: {}
                              regex: "^127\\.0\\.0\\.1(?::\\d+)?$"
                        - header:
                            name: ":authority"
                            safe_regex_match:
                              google_re2: {}
                              regex: "^169\\.254\\.169\\.254(?::\\d+)?$"
                        - header:
                            name: ":authority"
                            safe_regex_match:
                              google_re2: {}
                              regex: "^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(?::\\d+)?$"
                        - header:
                            name: ":authority"
                            safe_regex_match:
                              google_re2: {}
                              regex: "^192\\.168\\.\\d{1,3}\\.\\d{1,3}(?::\\d+)?$"
                        - header:
                            name: ":authority"
                            safe_regex_match:
                              google_re2: {}
                              regex: "^172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}(?::\\d+)?$"
                    principals:
                    - any: true
          - name: envoy.filters.http.rbac
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC
              rules:
                action: ALLOW
                policies:
                  allow_whitelist_domains:
                    permissions:
                    - or_rules:
                        rules:
                        - header:
                            name: ":authority"
                            exact_match: "baidu.com"
                        - header:
                            name: ":authority"
                            exact_match: "ifconfig.io"
                        - header:
                            name: ":authority"
                            safe_regex_match:
                              google_re2: {}
                              regex: ".*\\.[a-z0-9-]+\\.log\\.aliyuncs\\.com(?::\\d+)?$"
                    principals:
                    - any: true
          - name: envoy.filters.http.dynamic_forward_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
              dns_cache_config:
                name: dynamic_forward_proxy_cache_config
                dns_lookup_family: V4_ONLY
                host_ttl: 300s
                dns_cache_circuit_breaker:
                  max_pending_requests: 1024
                typed_dns_resolver_config:
                  name: envoy.network.dns_resolver.cares
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig
                    resolvers:
                    - socket_address:
                        address: 8.8.8.8
                        port_value: 53
                    - socket_address:
                        address: 223.5.5.5
                        port_value: 53
          - name: envoy.filters.http.local_ratelimit
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
              stat_prefix: rl
              filter_enabled:
                runtime_key: local_rate_limit_enabled
                default_value:
                  numerator: 100
                  denominator: HUNDRED
              filter_enforced:
                runtime_key: local_rate_limit_enforced
                default_value:
                  numerator: 100
                  denominator: HUNDRED
              token_bucket:
                max_tokens: 100
                tokens_per_fill: 100
                fill_interval: 1s
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: dynamic_forward_proxy_cluster
    connect_timeout: 2s
    lb_policy: CLUSTER_PROVIDED
    cluster_type:
      name: envoy.clusters.dynamic_forward_proxy
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
        allow_coalesced_connections: true
        dns_cache_config:
          name: dynamic_forward_proxy_cache_config
          dns_lookup_family: V4_ONLY
          host_ttl: 300s
          dns_cache_circuit_breaker:
            max_pending_requests: 1024
          typed_dns_resolver_config:
            name: envoy.network.dns_resolver.cares
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig
              resolvers:
              - socket_address:
                  address: 8.8.8.8
                  port_value: 53
              - socket_address:
                  address: 223.5.5.5
                  port_value: 53

设计要点

  • 来源 RBAC:仅允许本地与私网来源接入代理,降低滥用风险。
  • 目标 RBAC:阻断 localhost/127.0.0.1/169.254.169.254 与私网目标,防止穿透内网资源。
  • 白名单通配:*.{region}.log.aliyuncs.com(:port)?,适配 ap-southeast-1/cn-hangzhou 等地域。
  • 动态前向代理:开启 allow_coalesced_connections 合并连接,提升复用、降低 TIME_WAIT
  • DNS 解析:统一使用 c-ares 与相同缓存参数,保证解析稳定性。
  • 访问日志与限流:JSON 结构化访问日志,令牌桶本地限流保护瞬时峰值。

分段解析与用途说明

  • Admin 管理端(envoy/envoy-forward-proxy.yaml:1–6)
    • 提供 9902 管理接口与 /stats 指标;access_log_path 记录 admin 访问路径,便于审计。
  • 运行时连接限制(envoy/envoy-forward-proxy.yaml:8–13)
    • connection_limitglobal_downstream_max_connections 控制下游最大连接数;防止代理被瞬时并发拖垮。
  • 监听器(envoy/envoy-forward-proxy.yaml:17–23)
    • 9094 监听正向代理入口;enable_reuse_port 提升多 worker 可接受新连接能力,降低 accept 锁竞争。
  • 网络层 RBAC(来源限制,envoy/envoy-forward-proxy.yaml:25–47)
    • 允许 127.0.0.1/::1/10.0.0.0/8/192.168.0.0/16 来源;阻止公网来源滥用代理。
  • HTTP 连接管理(envoy/envoy-forward-proxy.yaml:49–59)
    • allow_absolute_url 支持 HTTP 代理规范;启用 HTTP/2 allow_connectHTTP/3 allow_extended_connect 支持隧道。
  • 访问日志(envoy/envoy-forward-proxy.yaml:60–82)
    • 输出 JSON 至 stdout,包含 authority/response_code/duration_ms/upstream_* 等关键字段,便于观测与问题定位。
  • 路由配置(envoy/envoy-forward-proxy.yaml:83–99)
    • 常规 HTTP:命中 prefix "/",路由到 dynamic_forward_proxy_cluster 进行转发与连接池复用。
    • CONNECT 隧道:connect_matcher: {} 捕获 CONNECT 方法,并通过 upgrade_type: CONNECT + connect_config: {} 开启隧道透传,TLS 握手由客户端与目标站点直接完成。
    • 工作原理:
      • HTTP:客户端通过代理发送绝对 URL(需打开 allow_absolute_url,见 envoy/envoy-forward-proxy.yaml:54–55),Envoy 按目标域名使用动态前向代理的 DNS 缓存与上游连接池转发请求。
      • HTTPS:客户端先发 CONNECT 目标域名:443;代理建立隧道后返回 200 Connection Established,后续 TLS 流量仅透传(不解密)。
    • 协议支持:允许在 HTTP/2 与 HTTP/3 下使用 CONNECT(见 envoy/envoy-forward-proxy.yaml:56–59)。
    • 与 RBAC 的关系:HTTP 层 RBAC 规则会先于路由执行;若目标域名命中敏感 IP 阻断或不在白名单内,则直接返回 403(参考 envoy/envoy-forward-proxy.yaml:101–161),不会进入路由阶段。
  • HTTP 层 RBAC(敏感目标阻断,envoy/envoy-forward-proxy.yaml:101–140)
    • DENY 策略先行:阻断 localhost/127.0.0.1/169.254.169.254 与私网地址作为目标,避免代理访问云元数据或内网服务。
  • HTTP 层 RBAC(域名白名单,envoy/envoy-forward-proxy.yaml:141–161)
    • ALLOW 策略仅放行指定域名与通配:.*\.[a-z0-9-]+\.log\.aliyuncs\.com(?::\d+)?$;支持不同地域与可选端口。
  • 动态前向代理过滤器(envoy/envoy-forward-proxy.yaml:162–182)
    • 管理 DNS 缓存与解析(c-ares);TTL 300s,最大挂起解析 1024;与集群侧配置保持一致性,避免解析差异。
  • 本地限流(envoy/envoy-forward-proxy.yaml:182–199)
    • 令牌桶每秒 100filter_enabled/enforced 100% 打开;用于抑制突发流量,保护代理稳定。
  • 路由器(envoy/envoy-forward-proxy.yaml:200–203)
    • 最终将请求按上游选择转发,结合动态前向代理提供的连接池与缓存复用。
  • 动态前向代理集群(envoy/envoy-forward-proxy.yaml:204–229)
    • allow_coalesced_connections 合并同域连接,显著提升上游复用,减少短连接与 TIME_WAIT;DNS 配置与过滤器侧保持一致。

调优建议与用法

  • 长连接与连接复用
    • 保持客户端与代理使用 HTTP/1.1 并移除 Connection: close;在上游域名稳定的场景下复用效果更显著。
  • DNS 稳定性
    • 指定权威与就近 DNS(如 8.8.8.8/223.5.5.5),并统一在过滤器与集群侧设置相同 TTL 与 resolver,减少解析不一致导致的失败。
  • 白名单策略
    • 若需收紧到特定地域:将正则中 [a-z0-9-]+ 改为 ap-southeast-[0-9]+ 等更严格模式。
  • 安全边界
    • 来源与目标双 RBAC:来源只允许内网接入;目标阻断敏感 IP 与仅放行必要域名,防止被用作内网跳板。

常见问题

  • 403 被 RBAC 拦截
    • 检查目标域名是否在白名单通配内(envoy/envoy-forward-proxy.yaml:157–161);或是否命中 DENY 规则(envoy/envoy-forward-proxy.yaml:111–139)。
  • RE2 正则复杂度限制
    • 单条规则过于复杂会报 program size 过大;已采用拆分与低复杂度通配,必要时进一步拆分或改用更精确匹配。
  • CONNECT 访问失败
    • 确认客户端使用代理访问 https://目标域名:443/,代理侧允许 CONNECT(envoy/envoy-forward-proxy.yaml:93–99)。

参考

  • 云原生运维:https://www.kbsonlong.com/
  • Kubernetes 文档:https://kubernetes.io/zh-cn/docs/home/
  • Istio 官方文档:https://istio.io/latest/zh/docs/
  • Linux 内核文档:https://docs.kernel.org/translations/zh_CN/index.html

Istio Pilot Discovery 深入剖析与流程图

Istio Pilot-Discovery 深入剖析与流程图

本文对 Istio 控制面的核心组件 Pilot-Discovery(通常作为 Istiod 的发现服务部分)进行系统性拆解与讲解,并配套 Mermaid 流程图来说明其关键启动路径、ADS 连接与订阅、以及 Push 配置下发流程。全文以仓库中的源码为依据,保证技术细节准确可溯源。

06-Kubelet 源码解析:从启动到 Pod 管理与指标监控

本文基于1.29.0版本

Kubelet 源码解析:从启动到 Pod 管理与指标监控

摘要

Kubelet 是 Kubernetes 集群中不可或缺的节点代理,负责管理 Pod 的生命周期、监控资源并确保节点上的容器按照预期状态运行。本文旨在通过对 Kubelet 源码的深度剖析,揭示其核心工作机制,内容涵盖从启动初始化、核心工作循环、Pod 生命周期管理到基于 cAdvisor 的指标监控全流程。通过对这些关键模块的分析,我们将构建一个关于 Kubelet 如何作为节点"管家"维持集群稳定性的完整视图。

05-Kube-Controller-Manager源码分析(HPA控制器)

本文基于1.29.0版本

HPA 控制器源码分析

简介

Horizontal Pod Autoscaler (HPA) 是 Kubernetes 中实现应用水平自动扩缩容的核心控制器。它通过监控指定的指标(如 CPU 利用率、内存使用量或自定义指标),自动调整 Deployment、ReplicaSet 或 StatefulSet 等工作负载的副本数,以应对流量波动和资源需求变化。

何时使用 RAG vs 微调

图片 2

充分利用 LLM 的全部潜力需要在检索增强生成 (RAG) 和微调之间选择正确的技术。

让我们研究一下何时对 LLM、较小模型和预训练模型使用 RAG 与微调。我们将涵盖:

0%