导读:本期聚焦于黑豹创作的《服务网格究竟如何注入 Sidecar 并劫持出入站流量?》,敬请观看详情。服务网格控制平面负责下发配置,数据平面则由每个 Pod 内的 Sidecar 代理组成。要让 Sidecar 真正介入业务流量,必须依次完成注入和劫持两个动作。注入阶段通常借助 Kubernetes 动态准入控制器 MutatingWebhook,在 Pod 创建前修改 Pod Spec,添加 istio-proxy 容器和 istio-init 初始化容器,并挂载证书与配置文件。劫持阶段依赖初始化容器执行 iptables 规则,在 nat 表的 PREROUTING 链把入站请求重定向到 15006 端口,在 OUTPUT 链把出站请求重定向到 15001 端口,同时通过 UID 与回环地址判断避免代理自身流量形成环路。这种机制让业务容器无需修改代码即可获得流量管理、可观测性和加密传输能力。本文基于 Istio 与 Envoy 的典型实现拆解注入流程、iptables 规则细节以及基于 eBPF 的演进方案。

服务网格中的 Sidecar 模式并不是简单地把代理容器塞进 Pod,而是需要让代理成为业务容器的网络出入口。要做到这一点,平台必须解决两个连续动作:注入和劫持。注入负责在 Pod 创建阶段把 Sidecar 容器、初始化容器以及相关配置写入 Pod 定义;劫持则依赖共享网络命名空间和内核流量控制能力,把原本直连应用进程的 TCP 连接重定向到 Sidecar 代理端口。本文基于 Istio 与 Envoy 的典型实现拆解这两个阶段的内部机制。

服务网格究竟如何注入 Sidecar 并劫持出入站流量?

一、Sidecar 注入:从手工配置到动态准入控制

在 Kubernetes 中,Pod 可以包含多个容器,这是 Sidecar 注入的基础。Sidecar 注入有两种常见方式:手动修改部署清单和自动注入。手动方式最直观,直接在 Deployment 的 Pod 模板中加入 istio-proxy 容器和 istio-init 初始化容器,同时挂载服务网格证书、策略配置以及指向控制平面的环境变量。手动方式的缺点十分明显:每个工作负载都要维护重复的容器定义,一旦网格升级,所有资源清单都需要同步调整,而且容易遗漏挂载项或环境变量。

自动注入解决了这一运维难题。控制平面会创建一个 MutatingWebhookConfiguration,指向 Sidecar 注入服务。当 API Server 收到 Pod 创建请求并完成认证授权后,会进入准入控制阶段。Webhook 收到经过序列化的 AdmissionReview 请求,其中包含原始 Pod 对象。注入器根据命名空间标签 istio-injection=enabled 或 Pod 注解判断是否需要注入,然后返回一个 JSON Patch,对 Pod Spec 进行补丁操作。补丁会添加初始化容器、Sidecar 容器、卷挂载和环境变量,同时给业务容器增加相关标记。整个过程业务容器定义保持不变,但注入后的 Pod 会持久化变更,控制器、调度器和运行时看到的都是补丁后的完整对象。

apiVersion: v1
kind: Pod
metadata:
  name: reviews-v1-7cbb959c74-9q2vj
  labels:
    app: reviews
spec:
  containers:
  - name: reviews
    image: istio/examples-bookinfo-reviews-v1:1.16.2
  - name: istio-proxy
    image: docker.io/istio/proxyv2:1.19.0
    args:
    - proxy
    - sidecar
    - --domain
    - $(POD_NAMESPACE).svc.cluster.local
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    ports:
    - containerPort: 15090
      name: http-envoy-prom
  initContainers:
  - name: istio-init
    image: docker.io/istio/proxyv2:1.19.0
    command:
    - istio-iptables
    args:
    - -p
    - "15001"
    - -z
    - "15006"
    - -u
    - "1337"
    - -m
    - REDIRECT
    - -i
    - "*"
    - -b
    - "*"
    - -d
    - "15090,15021,15020"

从上面的 Pod 片段可以看到,自动注入后的 Pod 会多出两个重要组件。istio-proxy 是长期运行的 Envoy 代理容器,负责承载数据平面流量;istio-init 是初始化容器,只在 Pod 启动时执行一次,生成 iptables 规则。初始化容器的命令参数中,-p 指定出站重定向端口 15001,-z 指定入站重定向端口 15006,-u 和 -m 分别控制代理 UID 与重定向模式。初始化容器完成规则写入后退出,随后业务容器和 Envoy 容器同时启动。由于 iptables 规则已经存在,业务容器启动后发出的第一条连接就会自动经过 Envoy。

注入器还需要处理命名空间标签变化、Pod 注解覆盖、注入模板版本冲突等边界情况。例如同一个命名空间下可能包含已经注入的 Deployment,也可能包含明确不想注入的 Job。此时可以通过 Pod 注解 sidecar.istio.io/inject 对单个 Pod 进行覆盖,优先级高于命名空间标签。理解注入器的补丁逻辑,有助于排查为什么某些 Pod 没有 Sidecar,或者为什么升级控制平面后新 Pod 的代理版本与旧 Pod 不一致。

二、基于 iptables 的流量劫持规则与匹配逻辑

初始化容器运行完成后,Pod 的网络命名空间已经配置好一系列 iptables 规则。由于业务容器和 Envoy 共享同一个 Linux network namespace,应用发出的 TCP 包会经过内核 netfilter 框架,iptables 规则可以在内核路径上拦截并修改这些包。Istio 默认使用 NAT 表的 REDIRECT 目标,对入站和出站流量分别重定向。入站连接先经过 PREROUTING 链,被跳转到 ISTIO_INBOUND 链;出站连接经过 OUTPUT 链,跳转到 ISTIO_OUTPUT 链。最终入站流量被重定向到 15006 端口,出站流量被重定向到 15001 端口,由 Envoy 监听并处理。

流量劫持并不是无脑把所有包都丢给代理,否则代理自身发出的流量会再次命中 OUTPUT 链并被重定向,形成无限循环。因此规则中使用 owner 模块匹配代理进程的 UID 和 GID,遇到 UID 1337 的包直接 RETURN。对于发往本机回环地址的流量、用于健康检查的端口以及通过参数排除的端口,也会提前返回。DNS 请求同样是重点:Istio 会捕获 TCP 53 端口的 DNS 流量并交由代理处理,以便实现基于服务名的流量管理,但 UDP 53 是否捕获取决于配置。通过 RETURN 规则和匹配顺序,内核可以在重定向和放行之间取得平衡。

# 查看 istio-init 生成的规则
iptables -t nat -L -n -v

# 简化后的关键匹配链
PREROUTING  -p tcp -j ISTIO_INBOUND
OUTPUT      -p tcp -j ISTIO_OUTPUT

ISTIO_INBOUND  -p tcp --dport 15008 -j RETURN
ISTIO_INBOUND  -p tcp -j ISTIO_IN_REDIRECT
ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006

ISTIO_OUTPUT  -s 127.0.0.6/32 -o lo -j RETURN
ISTIO_OUTPUT  -m owner --uid-owner 1337 -j RETURN
ISTIO_OUTPUT  -m owner --gid-owner 1337 -j RETURN
ISTIO_OUTPUT  -d 127.0.0.1/32 -j RETURN
ISTIO_OUTPUT  -p tcp -j ISTIO_REDIRECT
ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001

iptables 规则按照链的顺序逐条匹配,命中后执行对应动作。对于入站流量,来自集群内其他 Pod 的请求会先到达 PREROUTING,被重定向到 Envoy 的 15006 入站监听器。Envoy 完成身份验证、路由选择、重试和指标采集后,再作为客户端向本地业务容器发起新的连接。对于出站流量,业务容器发出的连接会经过 OUTPUT 链,被重定向到 Envoy 的 15001 出站监听器,由 Envoy 根据服务发现结果选择目标实例。由于连接被拆分,代理需要维护两段连接状态,依赖 conntrack 和内核对连接状态的跟踪。这也意味着当代理重启或规则变化时,已有连接可能被中断。

这种基于 iptables 的劫持方案成熟稳定,但也存在明显局限。规则数量增多后,新建连接需要逐条匹配,延迟会线性上升;大型集群中几千条服务路由不会直接变成 iptables 规则,但 Sidecar 级别的规则仍然可能影响性能。此外,iptables 依赖 NET_ADMIN 能力,必须通过 init 容器在应用启动前写入,运行期动态调整相对困难。因此社区开始探索更高效的内核扩展方案。

三、绕过机制与基于 eBPF 的演进方向

流量劫持中的绕过机制是排查问题的关键。UID 1337 并不是随意选择的,它对应 Envoy 进程运行时使用的用户 ID。Istio 在容器安全上下文中设置 runAsUser 和 runAsGroup 为 1337,这样 owner 模块可以准确识别代理发出的流量。业务容器通常使用普通用户 ID,不会被排除。回环地址排除解决了健康检查和与自身通信的问题,避免代理把访问本机的请求再重定向回自己。端口排除列表则保护 Prometheus 抓取端口 15090、状态端口 15021 等管理接口不被业务流量干扰。用户还可以通过 Pod 注解 traffic.sidecar.istio.io/excludeOutboundPorts 排除特定端口,这在对接外部数据库或非标准协议时非常实用。

当 iptables 规则出现异常时,常见现象包括业务 Pod 启动后所有出站请求超时、健康检查失败、访问外部 HTTPS 服务返回 502,或者 Envoy 日志显示连接建立后立即关闭。这些问题经常被误判为服务发现故障,实际上可能是 iptables 规则被 CNI 插件覆盖,或者 Node 节点上的 iptables 组件未正确加载 owner 模块。查看初始化容器日志并用 iptables -t nat -L -n -v 命令核对规则,往往比只看应用日志更接近根因。

eBPF 为流量劫持提供了新的实现路径。eBPF 可以把钩子挂载到内核网络路径上,使用哈希表 map 保存规则,绕过 iptables 的链式遍历。典型项目如 Cilium、Merbridge 通过 eBPF 直接把连接重定向到 Envoy,无需初始化容器配置 iptables,也不需要授予 Pod 额外网络能力。Merbridge 在 connect 和 sockops 等 hook 点处理,能够减少内核网络栈上的包处理开销。Istio 在 Ambient Mesh 模式下进一步简化 Sidecar,节点级 ztunnel 负责 mTLS 和 L4 策略,并通过隧道或 eBPF 将流量导向 waypoint 代理。对于传统 Sidecar 架构,eBPF 逐步替代 iptables 是趋势,但生产环境仍会长期存在 iptables 方案,因为其兼容性成熟,排查工具丰富,对内核版本的要求也更宽松。

Sidecar 注入和流量劫持体现了控制平面与数据平面、Kubernetes 与内核能力的精密协作。理解这些底层机制,有助于排查服务网格中常见的连接被重置、健康检查失败、访问外部服务返回异常等问题。线上故障中,用 iptables -t nat -L -n -v 检查规则是否被覆盖,用 istioctl proxy-status 检查代理配置同步状态,能够快速缩小问题范围。随着 eBPF 和 Ambient Mesh 走向成熟,未来的流量拦截方式会变得更轻量、更高效,但注入与劫持的基本思想仍然会延续。

服务网格Sidecar注入流量劫持修改时间:2026-08-21 23:22:25

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。