深入理解:Kubernetes 与 Istio 的网络通信(完整原理、时序与组件)

作者:Kiwi
最后更新时间:2025-11-09
说明:本文面向对容器网络与服务网格有一定理解的读者,侧重原理与可操作的验证命令。可直接复制粘贴到博客或笔记中。


目录

  1. 概览:为什么要区分「Kubernetes 网络」和「Istio 控制/数据平面」
  2. Kubernetes(无 Istio)网络全景
    • 核心组件与职责
    • Pod-to-Pod(跨 Node)流量详细流程
    • Service、kube-proxy、Endpoint/EndpointSlice 的工作方式
  3. 引入 Istio:总体架构与组件职责(istiod、Envoy、Gateway 等)
  4. 带 Istio 的 Pod->Pod(跨 Node)详细流量时序(逐步展开,含 xDS 与证书)
  5. 外部请求(Client -> Ingress Gateway -> Service -> Pod)的完整路径
  6. iptables vs TPROXY、IPVS vs iptables、CNI 封装(VXLAN/Geneve/BGP/eBPF)的细节说明
  7. 常见排查命令与检查点(kubectl/istioctl/Envoy 配置/日志)
  8. Mermaid 图(可直接在支持 Mermaid 的 Markdown 渲染器中渲染)
  9. 总结:责任边界与实务建议

1. 概览:分清两条线

  • Kubernetes 网络(L3/L2):由 CNI 提供,负责 Pod IP 分配、节点间路由与数据包转发(overlay 隧道或纯路由)。这个层面保证了 “任意 Pod 都能访问任意 Pod 的 IP”。
  • Istio(服务网格/L4~L7):通过注入 Envoy sidecar + 控制平面(istiod)实现应用层代理、策略、可观测、mTLS 等,不直接替换 CNI 提供的路由能力,而是在应用流量上“劫持 / 代理 / 控制”。

2. Kubernetes(无 Istio)网络全景

核心组件与职责(K8s 原生)

  • kube-apiserver:集群的真相源(Source of Truth)。Service/Endpoints/EndpointSlice/Pod 等资源都保存在这里。
  • kubelet:每个 Node 上的 agent。负责 Pod 生命周期,调用 CNI 插件创建 Pod 网络命名空间并分配 IP。
  • CNI 插件(Calico/Flannel/Cilium/etc.):负责 Pod IPAM、虚拟网卡配置、跨 Node 路由(overlay隧道 VXLAN/Geneve 或基于路由/BGP),或通过 eBPF 实现透明转发(Cilium)。
  • kube-proxy:在 Node 层实现 Service 的虚拟 IP(ClusterIP)和转发规则。可运行在 iptables 模式或 IPVS 模式。
  • CoreDNS:把 <svc>.<ns>.svc.cluster.local 解析为 ClusterIP(或者直接为 Headless Service 返回 Pod IP 列表)。
  • Endpoint / EndpointSlice:Service 对应的后端 Pod IP 列表(EndpointSlice 是更可扩展的实现)。

Pod -> Pod(跨 Node)流量(无 Istio)步骤

  1. PodA 的应用发起 TCP/UDP/HTTP 请求,发往目标 PodB 的 Pod IP 或 Service ClusterIP。
  2. 主机网络栈通过 Pod 的 veth(或 CNI 虚拟网卡)把包送出,CNI 决定如何将包传到目标 Node(overlay 隧道、路由或 eBPF)。
  3. 若目标是 Service(ClusterIP),kube-proxy 会根据规则将流量重写到某个后端 Pod(例如通过 DNAT + iptables 或通过 IPVS)。
  4. 目标 Node 的内核接收包,并将其交到目的 Pod 的网络命名空间。PodB 收到包并响应。

关键点:Kubernetes 保证基础的 L3/L4 可达(通过 CNI 与节点路由),Service 的负载均衡由 kube-proxy(iptables/IPVS)实现。


3. 引入 Istio:架构与组件职责(精确版)

控制面 & 数据面主要组件

  • istiod(控制平面,早期拆分为 Pilot/Citadel/Galley 的功能,但现在合并为 istiod)
    • 下发 Envoy 配置(通过 xDS:LDS/ RDS/ CDS/ EDS/ SDS 等);
    • 提供证书颁发与轮换(作为集成的 CA / 或通过外部 CA 集成);
    • 处理策略/配置(VirtualService、DestinationRule、ServiceEntry、Gateway 等)。
  • Envoy(Sidecar)(数据平面)
    • 负责拦截 Pod 的入/出流量,执行路由、负载均衡、重试、熔断、mTLS、指标收集等;
    • 通过 xDS 动态接收配置(LDS:listeners;RDS:routes;CDS:clusters;EDS:endpoints;SDS:证书/密钥)。
  • IngressGateway / EgressGateway(数据平面)
    • 专门用于边界流量(外部 -> 内部 或 内部 -> 外部),可由 Deployment/DaemonSet/Service 管理。
  • MutatingWebhook(sidecar injector)
    • 在 Pod 创建阶段注入 sidecar(或通过 istioctl kube-inject 手动注入)。
  • CRDs(Gateway / VirtualService / DestinationRule / ServiceEntry / Sidecar 等)
    • 用户定义的策略/路由,istiod 订阅并转换为 xDS 配置推送给 Envoy。

4. 带 Istio 的 Pod->Pod(跨 Node)详细流量时序(逐步)

下面分步说明 frontend (NodeA) -> backend (NodeB) 的真实流向,并把控制面(istiod)和数据面(Envoy、iptables、CNI)职责分清楚。

假设前提

  • frontend 与 backend 都注入了 Envoy sidecar;
  • istiod 正常运行并具有对 Service/Endpoint 的可见性;
  • Pod 的出入流量由 iptables(或 TPROXY)规则重定向到 Envoy。

时序(高层)

  1. 应用发出请求:frontend 的应用尝试连接 backend.svc.cluster.local:80(或直接 Pod IP)。
  2. iptables 重定向:Pod 的网络命名空间内的 iptables 规则(由 Istio init container 设置)把出站/入站流量拦截并重定向到本地 Envoy(通常重定向到一个本地监听端口,如 15001,或使用 TPROXY)。
    • 这一步确保流量不直接由 App 进出宿主网络,而是先到 Envoy。
  3. Envoy 决策(本地):Envoy 根据已缓存的 xDS 配置(来自 istiod)决定目标 cluster(即 backend service 的 cluster)和后端 endpoint(EDS 提供的 Pod IP 列表)。
    • istiod 会定期/事件触发地从 Kubernetes API Server 读取 Service/Endpoint/EndpointSlice,然后计算并下发 EDS(endpoint discovery)。
  4. Envoy 发起连接到目标 Pod IP:Envoy 在 NodeA 上建立连接,发送 IP 层/传输层的包到目标 PodB 的 PodIP(NodeB:PodB_ip:port)。
    • 这时,数据包遵循 Kubernetes 的 L3/L2 路径(CNI 处理跨节点转发):可能经过 VXLAN/Geneve 隧道或纯路由/BGP/eBPF。
  5. 目标 Node 内核/ CNI 接收包并交给目标 Pod:NodeB 的网络栈把包转到 PodB 的网络命名空间。目标 PodB 的 iptables 再把入站流量交给本地 Envoy(入站重定向),Envoy 再将流量传给 backend 应用容器。
  6. 返回路径:响应从 backend App → local Envoy → 网络 → frontend NodeA 的 Envoy → frontend App(iptables 将响应最终送回 App)。

xDS / 配置与证书(并行控制面动作)

  • istiod 订阅 Kubernetes 中的 Service/Endpoint/EndpointSlice。
  • istiod 将这些信息映射为 Envoy 的 Cluster(CDS)+ Endpoints(EDS),以及 Listener(LDS)和 Route(RDS)。
  • mTLS:istiod 作为 CA(或集成外部 CA)签发证书并通过 SDS(Secret Discovery Service)推送给 Envoy,Envoy 使用它做双向 TLS(当策略启用时)。

5. 外部请求:Client -> Ingress Gateway -> 内部服务(完整路径)

典型流程(HTTPS 举例)

  1. DNS 指向某个 Node(或 LoadBalancer IP);外部流量到达 Node 的某个端口(例如 443)。
  2. 若使用 istio-ingressgateway(部署为 Deployment 或 DaemonSet),该 Node 上运行的 ingress Envoy 监听 443(由 Gateway CRD 定义监听端口和 TLS 选项)。
  3. ingress Envoy 根据 Gateway + VirtualService 的规则决定如何路由(例如路由到 product-v1 的 cluster)。
  4. ingress Envoy 建立连向后端任意 Pod(Envoy -> backend Pod IP),或将流量经由服务网格内的其它 Envoy 转发(与 Pod->Pod 流量路径相同)。
  5. 若使用 mTLS,ingress-gateway 与后端之间可以配置为相互 TLS(通过 DestinationRule/PeerAuthentication 控制)。
  6. 当目标 Pod 在其它 Node 时,仍然依赖 Kubernetes CNI 完成跨节点的数据包转发。

注:Gateway 只是配置(CRD),不会创建 Pod。Pod 由 Deployment/DaemonSet/StatefulSet 等控制器创建(比如 istio-ingressgateway 这个 Deployment/DaemonSet)。


6. iptables vs TPROXY、IPVS vs iptables、CNI 封装细节(澄清常见误区)

iptables vs TPROXY

  • iptables REDIRECT(默认常见方式)
    • 将流量 DNAT 到 Envoy 本地端口;缺点是原始源 IP 会被改变(Envoy 需要使用 X-Forwarded-For 或 PROXY protocol 获取原始 IP)。
  • TPROXY
    • 能保存原始源 IP(透明代理),适合需要在代理上看到真实源 IP 的场景。配置更复杂,需要内核与 iproute2 支持。Istio 支持两种方式,默认取决于安装时的配置与平台能力。

kube-proxy:iptables vs IPVS

  • kube-proxy 有两种主要运行模式:iptablesIPVS
    • iptables:通过 iptables 规则实现 ClusterIP 的 DNAT 转发;
    • IPVS:使用内核层面的虚拟服务器 (LVS) 实现,更高性能与可伸缩性。
  • 注意:引入 Istio 后,Envoy 通常接管了应用层的负载均衡职责(而不是 kube-proxy),但 kube-proxy 仍然负责 Service ClusterIP 等内核层面的规则(某些流量路径可能仍触达 kube-proxy)。

CNI 封装方式(常见)

  • VXLAN / Geneve(overlay): 在 Node 之间封装(隧道)数据包,跨一些网络边界时常用。
  • BGP / 无隧道(Calico 的路由模式): 通过 BGP 或路由表实现 Pod IP 的可达性(避免封装,减少开销)。
  • eBPF(Cilium):用 eBPF 实现转发/安全策略、高性能的 L3/L4 转发与网络可观测性。
  • 选型影响:延迟、MTU、二层/三层可见性、流量采样难易等。

7. 常见排查命令(实操可用)

Kubernetes 侧

# 查看 pod 与 ownerReferences(确认由 DaemonSet/Deployment 管理)
kubectl -n <ns> get pods -o wide
kubectl -n <ns> describe pod <pod-name>

# 查看 Service 与 Endpoint / EndpointSlice
kubectl -n <ns> get svc <svc-name> -o yaml
kubectl -n <ns> get endpoints <svc-name> -o yaml
kubectl -n <ns> get endpointslices -l kubernetes.io/service-name=<svc-name>

# 查看 kube-proxy 模式
kubectl -n kube-system get pod -l k8s-app=kube-proxy -o yaml
# 或在节点查看 iptables/ipvs 规则
sudo iptables -t nat -L -n -v
sudo ipvsadm -Ln --stats


Istio / Envoy 侧

# 查看 Gateway / VirtualService / DestinationRule 配置
kubectl -n <ns> get gateway,virtualservice,destinationrule -o yaml

# 查看 istiod 日志
kubectl -n istio-system logs deployment/istiod

# 查看 envoy 配置(需要 istioctl)
# istioctl proxy-config {listeners|clusters|routes|endpoints} <pod> -n <ns>
istioctl proxy-config listeners <frontend-pod> -n <ns>
istioctl proxy-config clusters <frontend-pod> -n <ns>
istioctl proxy-config endpoints <frontend-pod> -n <ns>

# 查看 Envoy 日志(sidecar 名称通常是 istio-proxy)
kubectl -n <ns> logs <pod> -c istio-proxy

# 查看 Sidecar 注入 webhook 是否正常
kubectl get mutatingwebhookconfigurations


网络层排查

# 在 Node 上查看路由与接口
ip route
ip addr

# 查看 VXLAN 隧道/封装(示例)
ip -d link show vxlan0

# 使用 tcpdump 抓包(在 Node 或 Pod)
# Pod 环境:kubectl exec -it <pod> -- tcpdump -i any -n host port 80

8. 可渲染的 Mermaid 图(直接粘贴可渲染)

Pod -> Pod(跨 Node)路径(Mermaid 时序图)

sequenceDiagram
  participant AppA as Frontend App (Pod A)
  participant EnvoyA as Envoy Sidecar A
  participant CNI as Kubernetes CNI / Node Networking
  participant EnvoyB as Envoy Sidecar B
  participant AppB as Backend App (Pod B)
  participant Istiod as istiod (Control Plane)
  
  AppA->>EnvoyA: 出站流量(iptables 重定向)
  EnvoyA->>Istiod: xDS 已有配置(LDS/CDS/RDS/EDS)
  EnvoyA->>CNI: 目标 PodIP 的 IP 包(跨 Node)
  CNI->>EnvoyB: NodeB 接收并交给 Pod 网络命名空间
  EnvoyB->>AppB: 将流量交给后端应用
  AppB->>EnvoyB: 响应
  EnvoyB->>CNI: 响应包回送 NodeA
  CNI->>EnvoyA: NodeA 接收并交给 EnvoyA
  EnvoyA->>AppA: 最终交回应用

Client -> Ingress -> Service -> Pod(Mermaid 流程)

graph LR
  Client -->|HTTPS| IngressNode["Node (External IP)"]
  IngressNode --> IngressEnvoy[Istio IngressGateway (Envoy)]
  IngressEnvoy -->|VirtualService 路由| Cluster[Service Cluster (istio cluster)]
  Cluster --> BackendEnvoy[Envoy Sidecar (Pod)]
  BackendEnvoy --> BackendApp[Backend App]

9. 常见误解与澄清(总结)

  • Gateway 是 CRD(配置),不会创建 Pod。真正运行 ingress 的是
    istio-ingressgateway(Deployment/DaemonSet)产生的 Pod。
  • istiod 并非仅仅是“Pilot”:它同时承担了配置下发(xDS)、证书管理(以前称为 Citadel 的职责)、以及配置信息的分发。
  • Envoy 配置是通过 xDS 协议动态下发的(LDS/RDS/CDS/EDS/SDS),不是静态文件;Envoy 会与 istiod 建立连接获取这些配置。
  • Kubernetes 的 CNI 始终负责 L3/L2 的可达性;Istio 不改变底层转发路径,只在应用层增加代理/策略。
  • kube-proxy 仍然存在作用(Service 的内核层规则),但在服务网格场景中,Envoy 可以承担更复杂的 L7
    策略与负载均衡。

10. 结论与实务建议

责任分离:把问题分成两条线查:底层网络(Node/CNI/kube-proxy)问题 VS 服务网格(istiod/Envoy/CRD)问题。

排查顺序:先确认 Pod IP 与 Node 间路由是否可达(ping/tcpdump),再看 Envoy 是否收到正确 xDS/EDS 配置(istioctl proxy-config)。

mTLS 和 原始源 IP:如果必须保留原始源 IP,请考虑 TPROXY 或者在 Envoy/Ingress 配置中使用 PROXY protocol / X-Forwarded-For。

性能考虑:在高流量场景,关注 Envoy 的 CPU/连接数与 CNI 的性能特性(IPVS vs iptables、eBPF 提升等)。

参考(内部总结,不给外链)

Kubernetes 网络模型(CNI、kube-proxy、EndpointSlice)

Istio 控制面/数据面(istiod、Envoy、xDS、Sidecar 注入、Gateway/VirtualService)

更多推荐