Istio 作为目前最流行的 Service Mesh 解决方案之一,其核心能力在于透明地接管和控制服务之间的所有网络流量。这种“透明”的魔力是如何实现的呢?答案藏在 Kubernetes Pod 内部的网络配置——尤其是 Linux 的强大防火墙工具 iptables。
本文将深入探讨 Istio 如何利用 Sidecar 注入和 iptables 规则,实现对进出 Pod 流量的完全控制,并提供实际操作步骤来验证这些规则。
1. Istio 流量接管的核心机制
Istio 实现透明代理的关键在于两个组件:
- Envoy Sidecar Proxy: 注入到应用 Pod 中的轻量级代理,它负责处理所有的网络I/O。
- ****istio-init** 容器:** 这是一个 Init 容器,负责在主应用和 Envoy 启动之前,配置必要的 iptables 规则,确保所有流量都流经 Envoy。
当 Pod 启动时,istio-init 会运行,它通过配置 iptables 的 NAT 表,将原本流向或流出应用容器的网络数据包重定向到 Envoy Sidecar 监听的特定端口。
2. 理解关键的 iptables 链和端口
Istio 主要在 nat 表中创建规则,重点关注以下端口和链:
| 链 | 作用 | 目标端口 | 流量类型 |
|---|---|---|---|
| PREROUTING (入站) | 截获所有进入 Pod 的流量 | 15006 | INBOUND |
| OUTPUT (出站) | 截获所有源自 Pod 的流量 | 15001 | OUTBOUND |
Envoy 在端口 15001 上接收出站应用流量,并在 15006 上接收入站流量(如果配置了特定端口拦截)。
3. 实操:验证 Istio 的 iptables 规则
为了探究 Istio 实际是如何配置的,我们需要在一个启用了 Istio Sidecar 注入的命名空间中部署一个测试应用,并进入 Sidecar 容器查看其网络配置。
步骤 3.1 部署测试 Pod
首先,确保你的 Kubernetes 集群已经安装 Istio,并且目标命名空间已启用 Sidecar 注入(例如,标签 istio-injection=enabled)。
部署一个简单的 sleep Pod:
apiVersion: v1
kind: Pod
metadata:
name: sleep-test
spec:
containers:
- name: sleep
image: curlimages/curl
command: ["/bin/sleep", "365d"]
imagePullPolicy: IfNotPresent
# 部署 Pod
kubectl apply -f sleep-pod.yaml
# 确认 Pod 正在运行,并且有两个容器 (sleep 和 istio-proxy)
kubectl get pods sleep-test
步骤 3.2 检查 iptables 规则
我们可以通过进入 istio-proxy 容器来查看 Pod 命名空间内的网络配置,因为 istio-proxy 容器共享 Pod 的网络命名空间。
查看 nat 表中所有规则:
# 使用 istio-proxy 容器执行 iptables 命令
kubectl exec sleep-test -c istio-proxy -- iptables -t nat -L
你将看到类似如下的关键输出片段(细节可能因 Istio 版本和配置而异):
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
ISTIO_INBOUND all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ISTIO_OUTPUT all -- anywhere anywhere
# ... 其他链定义 ...
Chain ISTIO_OUTPUT (2 references)
target prot opt source destination
RETURN all -- anywhere 127.0.0.6/32 # 排除特定的本地流量
ISTIO_REDIRECT tcp -- anywhere anywhere ! owner UID 1337 redir ports 15001 # 关键:重定向到 15001
Chain ISTIO_INBOUND (1 references)
target prot opt source destination
ISTIO_IN_REDIRECT tcp -- anywhere anywhere tcp dpt:80 # 示例:如果是访问应用端口 80
Chain ISTIO_REDIRECT (2 references)
target prot opt source destination
REDIRECT all -- anywhere anywhere redir ports 15001
规则解析
- 出站流量 (OUTPUT** -> ISTIO_OUTPUT):** 当 sleep-test Pod 中的应用尝试连接外部服务时,数据包进入 OUTPUT 链。它被重定向到 ISTIO_OUTPUT 链。这里的关键规则是使用 ! owner UID 1337 (即非 Envoy 自身发出的流量)将所有 TCP 流量导向 ISTIO_REDIRECT,最终通过 REDIRECT 规则将流量强制送往 Envoy 的 15001 端口。
- 入站流量 (PREROUTING** -> ISTIO_INBOUND):** 当外部流量到达 Pod IP 时,数据包进入 PREROUTING 链,并被导向 ISTIO_INBOUND。如果该流量的目标端口是应用容器监听的端口(例如 80),则会被重定向到 Envoy 的入站监听器(通常是 15006 端口)。
4. 总结
Istio 通过精心配置的 iptables 规则,实现了对应用流量的透明代理。应用容器无需知道 Envoy Sidecar 的存在,因为所有网络 I/O 在内核级别就被操作系统重定向了。正是这种底层网络的接管能力,使得 Istio 能够一致地应用路由策略、安全策略(mTLS)、可观测性(指标和追踪)等 Service Mesh 核心功能。
汤不热吧