在 Istio 中,istio-proxy(基于 Envoy 的 Sidecar 容器)本身并不直接设置 IPTables 规则。IPTables 规则的设置是由一个专门的 Init 容器(称为 istio-init)在 Pod 启动的早期阶段完成的。下面我会详细说明这个过程和时间点。
1. Istio 的注入流程
当你在 Pod 上启用 Istio Sidecar 注入(通过 sidecar.istio.io/inject: "true" 注解),Istio 的 MutatingWebhook 会修改 Pod 的 Spec,注入两个关键组件:
- Init 容器:istio-init:负责初始化网络配置,包括设置 IPTables 规则。
- Sidecar 容器:istio-proxy:运行 Envoy 代理,处理实际的流量。
这些容器会在 Pod 的生命周期中按特定顺序执行。
2. IPTables 规则设置的时间点
IPTables 规则是在 istio-init Init 容器运行时设置的。具体时间点如下:
- Pod 创建时:Kubernetes 在 Pod 开始启动时,首先运行所有的 Init 容器。
- istio-init 执行期间:istio-init 容器启动后,会执行一系列命令来配置 Pod 的网络环境,其中包括设置 IPTables 规则,用于将流量重定向到 istio-proxy(Envoy)。
istio-init 的工作流程
- 镜像:istio-init 使用的是 Istio 的代理镜像(例如 istio/proxyv2:1.20.0),但它的入口命令被设置为初始化脚本。
- 执行命令:istio-init 的主要任务是通过脚本(通常是 istio-iptables.sh)设置 IPTables 规则。典型规则包括:
- 将入站流量重定向到 istio-proxy 的监听端口(如 15001)。
- 将出站流量重定向到 istio-proxy 的出站端口(如 15006)。
- 绕过某些特定流量(如元数据服务或健康检查)。
- 完成并退出:istio-init 完成后会退出(Exit Code 0),标志着 Init 阶段结束。
时间点总结
- 在所有主容器启动之前:根据 Kubernetes 的生命周期,Init 容器必须在所有主容器(包括业务容器和 istio-proxy)启动之前完成。
- 早于 istio-proxy 运行:IPTables 规则设置完成后,istio-proxy 才会启动并开始监听流量。
3. 注入后的 Pod 配置示例
以下是注入后 Pod 的简化配置,展示了 istio-init 的角色:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
annotations:
sidecar.istio.io/inject: "true"
spec:
initContainers:
- name: istio-init
image: istio/proxyv2:1.20.0
args:
- istio-iptables
- -p
- "15001" # 入站端口
- -z
- "15006" # 出站端口
- -u
- "1337" # UID 重定向绕过
securityContext:
capabilities:
add:
- NET_ADMIN # 需要权限修改 IPTables
containers:
- name: app
image: my-app-image
- name: istio-proxy
image: istio/proxyv2:1.20.0
4. 为什么 istio-proxy 不设置 IPTables
- istio-proxy 是流量代理:它的职责是接收和处理通过 IPTables 重定向的流量,而不是配置网络规则。
- 权限分离:设置 IPTables 需要 NET_ADMIN 权限,而 istio-proxy 通常以非特权用户(UID 1337)运行,不具备直接修改 IPTables 的能力。
- 启动顺序:如果 istio-proxy 负责设置 IPTables,它需要在自身启动后再配置网络,这会导致逻辑复杂性和潜在的启动延迟。
5. 与 holdApplicationUntilProxyStarts 的关系
即使启用了 holdApplicationUntilProxyStarts: true,IPTables 规则的设置仍然发生在 istio-init 阶段,不受此注解影响。注解只控制业务容器和 istio-proxy 的启动顺序,确保业务容器在 istio-proxy 就绪后再启动,而 IPTables 早已由 istio-init 配置完成。
6. 验证 IPTables 规则设置的时间
你可以通过以下方法验证:
- 检查 Pod 日志:查看 istio-init 容器的日志,确认其执行时间和退出状态。
bash
kubectl logs <pod-name> -c istio-init
- 查看 IPTables:在 Pod 启动后,使用调试工具进入容器,检查 IPTables 规则。
bash
iptables -t nat -L -n -v
总结
Istio 的 IPTables 规则是由 istio-init Init 容器在 Pod 启动的 Init 阶段设置的,具体时间点是:
- 早于所有主容器(包括 istio-proxy 和业务容器)启动。
- 在 istio-init 容器运行并完成后。
istio-proxy 本身不设置 IPTables,它只依赖 istio-init 配置好的规则来处理流量。这种设计分离了网络初始化和流量代理的职责,确保了启动顺序的清晰性和安全性。如果还有疑问,欢迎继续探讨!