2. 容器网络缓存机制:Sidecar模式下的流量劫持、iptables规则与流量重定向、连接跟踪与缓存失效
2.1 Sidecar 模式下的流量劫持原理
在 Kubernetes 环境中,Envoy 作为 Sidecar 代理通常采用透明劫持(Transparent Interception)的方式接管 Pod 内应用容器的进出流量。其核心思想是:应用容器完全感知不到代理的存在,所有出站(Egress)和入站(Ingress)流量都被 iptables 规则静默重定向到 Envoy 的监听端口。
关键概念:透明劫持不修改应用代码,不要求应用显式配置代理地址。Envoy 通过
SO_ORIGINAL_DST 和 TPROXY 等机制还原原始目标地址,实现七层代理的零侵入接入。
下图展示了 Sidecar 模式下流量劫持的完整路径:
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 缓存失效的典型场景
- Pod 滚动更新:旧 Pod 被销毁,conntrack 中指向旧 IP 的条目变为无效,新连接必须重新建立。
- Envoy 热重启:Envoy 在重新加载配置时,旧监听器关闭,conntrack 中关联的 ESTABLISHED 连接被重置。
- iptables 规则变更:修改 REDIRECT 目标端口或新增规则后,conntrack 中的旧转换条目与当前规则不匹配。
- 网络策略更新: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 缓存失效的完整链路:
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 的计数器是否增长。如果计数器不变,说明流量未被劫持。