2. 容器网络缓存机制:Sidecar模式下的流量劫持、iptables规则与流量重定向、连接跟踪与缓存失效

2.1 Sidecar 模式下的流量劫持原理

在 Kubernetes 环境中,Envoy 作为 Sidecar 代理通常采用透明劫持(Transparent Interception)的方式接管 Pod 内应用容器的进出流量。其核心思想是:应用容器完全感知不到代理的存在,所有出站(Egress)和入站(Ingress)流量都被 iptables 规则静默重定向到 Envoy 的监听端口。

关键概念:透明劫持不修改应用代码,不要求应用显式配置代理地址。Envoy 通过 SO_ORIGINAL_DST 和 TPROXY 等机制还原原始目标地址,实现七层代理的零侵入接入。

下图展示了 Sidecar 模式下流量劫持的完整路径:

Sidecar 模式流量劫持路径 应用容器 App (port 8080) Envoy Sidecar Inbound: 15006 Outbound: 15001 iptables 规则链 PREROUTING (NAT) OUTPUT (NAT) RETURN / REDIRECT TPROXY / DNAT conntrack 表 连接状态跟踪 缓存失效场景 Pod 迁移 / 规则变更 出站流量 重定向 跟踪 说明: 应用出站流量 → iptables OUTPUT 链 → REDIRECT 到 Envoy 15001 → Envoy 处理 → 原始目标

2.2 iptables 规则与流量重定向

Sidecar 模式下的 iptables 规则通常由 istio-init 或 CNI 插件在 Pod 启动时注入。规则主要分布在 NAT 表的 PREROUTING 和 OUTPUT 链中,实现入站和出站流量的重定向。

2.2.1 核心规则清单

链 表 匹配条件 动作 说明
PREROUTING nat 入站 TCP REDIRECT → 15006 将进入 Pod 的流量重定向到 Envoy Inbound
OUTPUT nat 出站 TCP(非 localhost) REDIRECT → 15001 将应用发出的流量重定向到 Envoy Outbound
OUTPUT nat 目标为 Envoy 自身端口 RETURN 避免 Envoy 自身流量被循环重定向
PREROUTING mangle TPROXY 标记 TPROXY 保留原始目标地址(透明代理模式)
排查要点:当出现连接超时或拒绝时,首先检查 iptables -t nat -L -n -v 的计数器。如果 REDIRECT 规则的 packet 计数为 0,说明流量未被劫持,可能是规则未生效或应用使用了 localhost 地址。

2.2.2 典型规则示例

# 查看 NAT 表规则
iptables -t nat -L -n -v

# 典型输出(简化)
Chain PREROUTING (policy ACCEPT)
target     prot opt source         destination
ISTIO_INBOUND  tcp  --  0.0.0.0/0   0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target     prot opt source         destination
ISTIO_OUTPUT   tcp  --  0.0.0.0/0   0.0.0.0/0

Chain ISTIO_OUTPUT (1 references)
target     prot opt source         destination
RETURN     tcp  --  0.0.0.0/0   127.0.0.1/8    # 跳过 localhost
RETURN     tcp  --  0.0.0.0/0   0.0.0.0/0     owner UID match 1337  # 跳过 Envoy 自身
REDIRECT   tcp  --  0.0.0.0/0   0.0.0.0/0     redir ports 15001     # 重定向到 Envoy

2.3 连接跟踪与缓存失效

Linux 连接跟踪(conntrack)是 iptables 实现有状态过滤和 NAT 的基础。在 Sidecar 模式下,conntrack 记录了所有经过 iptables 重定向的连接状态。当 Pod 发生迁移、Envoy 重启或规则变更时,conntrack 表中的缓存条目可能失效,导致连接中断或异常。

2.3.1 conntrack 表结构

字段 说明 缓存失效影响
src / dst 原始源/目标 IP 和端口 Pod IP 变更后条目失效
reply-src / reply-dst NAT 转换后的地址 Envoy 端口变更后需刷新
state 连接状态(ESTABLISHED, NEW, RELATED) 状态不匹配导致丢包
mark 连接标记(用于策略路由) 标记丢失导致路由错误

2.3.2 缓存失效的典型场景

  1. Pod 滚动更新:旧 Pod 被销毁,conntrack 中指向旧 IP 的条目变为无效,新连接必须重新建立。
  2. Envoy 热重启:Envoy 在重新加载配置时,旧监听器关闭,conntrack 中关联的 ESTABLISHED 连接被重置。
  3. iptables 规则变更:修改 REDIRECT 目标端口或新增规则后,conntrack 中的旧转换条目与当前规则不匹配。
  4. 网络策略更新:Kubernetes NetworkPolicy 变更导致 conntrack 中的连接被新的防火墙规则拒绝。
常见故障现象:应用日志中出现大量 Connection reset by peer 或 Broken pipe,同时 Envoy 访问日志显示 NC (No Cluster) 或 UF (Upstream Failure)。此时应检查 conntrack 表是否包含大量无效条目。

2.3.3 排查命令

# 查看 conntrack 表(需要 root 权限)
conntrack -L -n | head -20

# 统计 conntrack 表大小
conntrack -S

# 按源 IP 过滤
conntrack -L -n --src 10.0.0.5

# 清除特定连接(谨慎使用)
conntrack -D -p tcp --dport 15001

# 查看 conntrack 超时参数
sysctl net.netfilter.nf_conntrack_tcp_timeout_established

2.4 流量重定向与缓存失效的关联分析

下图展示了流量重定向过程中 conntrack 缓存失效的完整链路:

流量重定向与 conntrack 缓存失效链路 阶段 1 应用发起连接 src: PodIP:12345 阶段 2 iptables REDIRECT dst: 127.0.0.1:15001 阶段 3 conntrack 记录 orig → reply 映射 阶段 4 Envoy 处理 还原原始目标 缓存失效触发条件 Pod 删除 / Envoy 重启 / 规则变更 conntrack 条目被标记为 INVALID 结果:连接中断 / 超时 / RST 应用层表现为 Broken pipe 或 Connection reset

2.5 最佳实践与避坑指南

  • 避免 localhost 直连:应用应使用 Pod IP 或 Service 名称通信,不要使用 127.0.0.1 绕过 iptables 劫持。
  • 监控 conntrack 表大小:设置告警 nf_conntrack_count > nf_conntrack_max * 0.8,防止表满导致丢包。
  • 优雅处理 Envoy 重启:使用 --drain-time-s 参数让 Envoy 在关闭前等待现有连接完成。
  • 定期清理无效条目:在 Pod 生命周期钩子中执行 conntrack -D 清理与旧 Pod 相关的连接。
  • 使用 TPROXY 替代 REDIRECT:TPROXY 模式能保留原始目标地址,减少 conntrack 转换带来的复杂性。
快速验证命令:在 Pod 内执行 curl -v http://service-name,同时观察 iptables -t nat -L ISTIO_OUTPUT -n -v 的计数器是否增长。如果计数器不变,说明流量未被劫持。