Envoy作为sidecar在服务网格中怎么配置
摘要:# 别再把Envoy当“黑盒子”了:手把手教你配好服务网格里的“门卫” 说实话,第一次接触服务网格里的Envoy sidecar,我脑子里就俩字:懵圈。 文档里动不动就是`listener`、`cluster`、`filter chain`,一堆配置项…
别再把Envoy当“黑盒子”了:手把手教你配好服务网格里的“门卫”
说实话,第一次接触服务网格里的Envoy sidecar,我脑子里就俩字:懵圈。
文档里动不动就是listener、cluster、filter chain,一堆配置项看得人眼晕。很多团队的做法是——直接照搬官网示例,或者用现成的工具一键生成,然后祈祷它别出问题。结果真到流量异常或者要调优的时候,全傻眼了,因为根本不知道里面是怎么转的。
我自己就经历过,一个配置错误导致整个服务的时延莫名其妙涨了200ms,查了大半天才定位到是Envoy里一个超时参数没配好。所以今天,咱们不聊那些虚的架构理念,就坐下来,像给自家大门换把锁一样,把Envoy sidecar的配置那点事儿,掰开揉碎了讲明白。
一、先泼盆冷水:Envoy不是“即插即用”的护身符
很多人有个误解,觉得在Kubernetes里给Pod注入个sidecar,服务网格就建成了,安全性和可观测性就自动加满了。
醒醒吧。 这就好比给你家装了个最顶级的智能门锁,结果你把钥匙插在门上不拔——防护形同虚设。
Envoy作为一个高性能代理,能力确实强,但它的默认配置往往是个“宽松模式”。不经过针对性调整,它可能连最基本的四层攻击(比如SYN Flood)都防得不彻底,更别说应对复杂的应用层CC攻击了。它的核心价值在于提供了极其精细的流量操控能力,但具体怎么控,得你来定义。
二、核心配置解剖:你的流量到底经历了什么?
咱们别被那些术语吓到。你可以把Envoy sidecar想象成你们小区门口那个特别认真的保安亭。每一个进出小区的请求(流量),都得在这儿过一遍。
它的工作流程,主要围绕着三份核心“花名册”:
1. 监听器 (Listener) - “保安亭设在哪儿?”
这就是Envoy的“耳朵”,它决定了代理监听哪个端口、什么类型的流量(TCP/HTTP)。在Kubernetes里,最常见的就是监听Pod的15001端口(入站流量)和15006端口(出站流量),这是Istio等网格的默认设置。
关键配置点(容易踩坑):
traffic_direction:这个标签至关重要,告诉Envoy这个监听器是处理INBOUND(进站)还是OUTBOUND(出站)流量。配反了,流量路径全乱。filter_chains:这是重头戏,决定了听到流量后“怎么处理”。下面会细说。
2. 过滤器链 (Filter Chains) - “保安检查什么项目?”
这是Envoy的灵魂。一个监听器下可以挂多条过滤器链,每条链是一系列过滤器的有序组合。流量按顺序经过这些过滤器,就像快递经过安检机的不同检测模块。
常用的核心过滤器:
tcp_proxy:处理原始TCP流量,比如数据库、Redis连接。配置简单,但也就只能做简单的转发和统计。http_connection_manager(HCM):这是HTTP流量的核心枢纽。它本身又是一个“盒子”,里面可以装更多HTTP级别的过滤器(http_filters),比如:router:最终将流量路由到具体的目的地集群(Cluster)。fault:注入故障,做混沌工程测试。cors:处理跨域请求。lua:用Lua脚本实现自定义逻辑,非常灵活。ext_authz:调用外部服务做鉴权,这是实现零信任架构的关键。
一个极简但完整的入站HTTP配置逻辑是: Listener (监听15080端口) -> Filter Chain -> HCM过滤器 -> router过滤器 -> 将流量转发到本地服务(127.0.0.1:8080)。
3. 集群 (Cluster) - “快递最终送到哪栋楼?”
Cluster定义了流量的目的地,可以是一个静态的IP列表,也可以是一个动态的服务发现端点(如Kubernetes的Service)。
动态服务发现是服务网格的精华。通常,Envoy会通过xDS协议(如EDS, CDS)从控制面(如Istiod)动态获取Cluster和Endpoint的信息。这意味着,当后端服务实例扩缩容时,Envoy能几乎实时地更新路由目标,这是实现高可用的基础。
# 这是一个静态Cluster配置的例子(实际网格中多用动态发现)
clusters:
- name: my_service
connect_timeout: 1s # 连接超时,设太短在慢网络下容易误杀
type: STATIC
load_assignment:
cluster_name: my_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.1.1
port_value: 8080
三、从“能用”到“好用”:几个关键的调优配置
如果你只配了上面那些,Envoy只能算“能跑起来”。想让它在生产环境真正扛得住、稳如狗,下面这些参数你得琢磨琢磨。
-
连接池管理 (
circuit_breakers): 这是防止故障扩散的第一道闸。给每个上游服务(Cluster)设置最大连接数、最大请求数。当某个服务响应变慢,堆积的请求触发了熔断器,Envoy会快速失败,避免线程被拖死,把问题隔离在单个服务内。很多服务雪崩,源头就是这里没设限。 -
超时与重试 (
timeout,retry_policy):timeout:给路由(Route)或Cluster设置全局超时。别指望应用自己都设对了,在网格层做一次兜底。retry_policy:重试是把双刃剑。配置不当(比如对非幂等POST请求重试)就是灾难。一定要配retriable_status_codes(如502、503),并限制重试次数(num_retries)和超时(per_try_timeout)。
-
健康检查 (
health_checks): 让Envoy主动探测上游Endpoints的健康状态,自动踢掉不健康的实例。配合服务发现,这是实现无缝滚动升级和故障自愈的基石。 -
访问日志 (
access_log): 别小看日志。把%DOWNSTREAM_REMOTE_ADDRESS%(客户端IP)、%REQUEST_ID%、%RESPONSE_CODE%、%DURATION%(响应时间)这些关键字段打出来。当出现慢请求或攻击时,这是你排查问题唯一可靠的“黑匣子”数据。可以输出到文件,也可以直接对接stdout被Fluentd收集。
四、一个接地气的场景:如何用Envoy防一波简单的CC攻击?
假设你的用户服务user-service被恶意刷接口了。纯靠默认配置,Envoy只会老实转发,你的应用CPU可能直接被打满。
这时候,你可以在user-service的入站HCM过滤器链里,加一个本地限流过滤器(虽然Envoy原生更推荐用envoy.filters.http.local_ratelimit,但为了说明原理,我们想想看怎么利用现有能力):
- 思路一:利用连接池和请求限制。 在
user-service对应的Cluster配置里,把circuit_breakers里的max_requests设置成一个合理的阈值。这能瞬间限制住单个Envoy实例发往该服务的最大并发请求数,粗暴但有效,防止应用进程崩溃。 - 思路二(更精细):写个Lua脚本。 在
http_filters里插入一个envoy.filters.http.lua过滤器。在这个Lua脚本里,你可以根据请求路径(比如/api/v1/login)、来源IP,实现一个简单的内存计数器,在1秒内超过N次请求,就直接返回429(Too Many Requests)。这其实就是个简易版的WAF功能,在应用侧实现零成本。 - 真正的生产级方案: 配置
ext_authz过滤器,将请求信息(IP、路径、Header)发给一个专门的限流服务(如redis+cell算法实现分布式限流)。这样,所有sidecar的限流决策都是统一和精准的。
五、写在最后:别追求“最全配置”,要追求“最懂流量”
Envoy的配置项多如牛毛,但80%的场景,你只需要理解好上面那20%的核心。
我的建议是:先让流量通起来,然后加上熔断、超时、重试和基础监控。 等业务稳定了,再根据实际遇到的痛点(比如链路追踪需要增强、某个接口需要特殊限流),去查阅文档,引入更高级的过滤器或配置。
永远记住,Envoy sidecar是你应用的“外交官”和“保镖”。它的配置,本质上就是你流量治理策略的代码化。你越了解你的业务流量特征(哪些是关键接口,哪些能容忍延迟,哪些必须保证绝对正确),就越能配好Envoy。
最后说句大实话:与其在网上找一份“最优配置模板”,不如打开你们公司的监控系统,看着真实的流量曲线和错误日志,去思考Envoy该怎么帮你解决这些问题。配置,是死的;对流量的理解,才是活的。
行了,关于Envoy sidecar的配置,今天就聊这么多。如果你正在为某个具体的配置问题头疼,不妨在评论区说说,咱们一起琢磨琢磨。

