Kubernetes(K8S)的网络模型通过一系列机制实现了 Pod 内部容器间通信 、Pod 与 Pod 间通信 以及 Pod 与外部网络的通信。以下是各场景的详细实现原理和解决方案:
一、Pod 内部的容器间通信
核心机制:共享网络命名空间
-
实现原理:
- 每个 Pod 中的所有容器共享同一个 Linux 网络命名空间(Network Namespace),类似于同一台主机上的多个进程。
- Pod 内的容器通过
localhost
直接通信,无需经过 NAT 或其他网络跳转。
-
技术细节:
- Kubernetes 通过
pause
容器(Infra 容器)创建网络命名空间,其他容器通过--net=container:<pause-container-id>
加入该命名空间。 - 容器间的通信通过本地环回接口完成,例如容器 A 监听
localhost:8080
,容器 B 通过localhost:8080
访问。
- Kubernetes 通过
yaml
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: web
image: nginx
ports:
- containerPort: 80
- name: log-collector
image: busybox
command: ["sh", "-c", "while true; do curl localhost:80; sleep 10; done"]
log-collector
容器通过localhost:80
直接访问同一 Pod 内的web
容器。
二、Pod 与 Pod 之间的通信
核心机制:扁平化网络模型
Kubernetes 要求所有 Pod 无论位于哪个节点,都能直接通过 IP 地址通信。这通过 CNI(Container Network Interface)插件 实现。
1. 同一节点上的 Pod 通信
-
实现原理:
- 每个节点上的 Pod 通过虚拟网桥(如
docker0
、cni0
)连接。 - Pod 的虚拟网卡(如
veth0
)连接到网桥,网桥作为二层交换机转发流量。
- 每个节点上的 Pod 通过虚拟网桥(如
css
Pod A (10.244.1.2) → veth → cni0 → veth → Pod B (10.244.1.3)
2. 跨节点上的 Pod 通信
-
实现原理:
- 依赖 CNI 插件实现跨节点路由,常见方案包括 Overlay 网络 或 路由协议(如 BGP) 。
-
典型方案:
-
Flannel(VXLAN 模式) :
- 在每个节点上创建隧道接口(如
flannel.1
),将 Pod 流量封装为 UDP 包,跨节点传输。
- 在每个节点上创建隧道接口(如
-
Calico(BGP 模式) :
- 节点作为 BGP 路由器,直接交换 Pod 子网路由信息,无需封装。
-
Cilium(eBPF 优化) :
- 通过 eBPF 程序在内核层处理路由和策略,性能更高
-
示例:
-
节点 1 的 Pod(
10.244.1.2
)访问节点 2 的 Pod(10.244.2.3
):- Calico(BGP) :节点 1 直接通过物理网络将流量转发到节点 2。
- Flannel(VXLAN) :节点 1 将原始数据包封装为 VXLAN 帧,发送到节点 2 解封装
三、Pod 与外部网络的通信
核心机制:Service 与 Ingress
Pod 需要暴露到集群外部或被外部服务访问,主要通过以下两种方式:
1. 从 Pod 访问外部网络(出站流量)
-
实现原理:
- Pod 的流量通过节点的网络接口(如
eth0
)进行 SNAT(源地址转换),使得外部服务看到的源 IP 为节点 IP。 - 由节点的
iptables
或 CNI 插件(如 Cilium 的 eBPF)实现 NAT 规则。
- Pod 的流量通过节点的网络接口(如
bash
# Pod 内部执行
curl https://api.example.com
- 数据流:
Pod → Node 的 eth0 → 外部网络
,外部服务看到的源 IP 为节点 IP。
2. 从外部访问 Pod(入站流量)
Kubernetes 通过 Service 和 Ingress 抽象实现外部访问:
(1) Service 类型
-
ClusterIP(默认) :
- 提供集群内部访问的虚拟 IP,外部无法直接访问。
-
NodePort:
- 在节点上开放一个端口(如
30080
),流量通过NodeIP:NodePort
转发到 Pod。
- 在节点上开放一个端口(如
-
LoadBalancer:
- 云厂商(如 AWS、GCP)自动创建负载均衡器,将外部流量路由到 Service。
-
ExternalName:
- 将 Service 映射到外部 DNS 名称(如
redis.example.com
)。
- 将 Service 映射到外部 DNS 名称(如
(2) Ingress
-
通过 Ingress 控制器(如 Nginx、Traefik)实现 HTTP/HTTPS 路由:
- 根据域名和路径将流量分发到不同的 Service。
- 支持 TLS 终止和七层负载均衡。
(2) Ingress
-
通过 Ingress 控制器(如 Nginx、Traefik)实现 HTTP/HTTPS 路由:
- 根据域名和路径将流量分发到不同的 Service。
- 支持 TLS 终止和七层负载均衡。
yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
selector:
app: web
- 外部用户通过
http://<NodeIP>:30080
访问 Pod。
四、关键技术组件
-
kube-proxy:
- 维护节点上的
iptables
或IPVS
规则,实现 Service 的负载均衡。
- 维护节点上的
-
CNI 插件:
- 负责 Pod 网络的创建、IP 分配和跨节点路由(如 Calico、Flannel)。
-
Ingress 控制器:
- 处理外部 HTTP/HTTPS 流量(如 Nginx Ingress Controller)。
五、网络模型总结
场景 | 解决方案 |
---|---|
Pod 内部容器间通信 | 共享网络命名空间(localhost + 端口) |
同一节点 Pod 通信 | 虚拟网桥(如 cni0 ) |
跨节点 Pod 通信 | CNI 插件(Overlay 或 BGP 路由) |
Pod 访问外部网络 | SNAT(节点 IP 转换) |
外部访问 Pod | Service(NodePort/LoadBalancer) + Ingress(七层路由) |
六、常见问题与调试
-
Pod 无法跨节点通信:
- 检查 CNI 插件配置(如 Calico 的 BGP 对等状态)。
- 确认防火墙是否放行节点间流量(如 VXLAN 的 UDP 8472 端口)。
-
Service 无法访问:
- 检查
kube-proxy
是否正常运行:
ini
kubectl get pods -n kube-system -l k8s-app=kube-proxy
- 验证
iptables
规则:
perl
iptables-save | grep <service-name>
DNS 解析失败:
- 检查 CoreDNS 是否正常:
ini
kubectl get pods -n kube-system -l k8s-app=kube-dns
七、总结
Kubernetes 通过 CNI 插件 实现 Pod 间扁平化网络,借助 Service 和 Ingress 管理外部访问,同时依赖 kube-proxy 和 节点网络栈 处理流量转发。理解这些机制是构建稳定、高效容器网络的关键。实际部署时,需根据场景选择合适的 CNI 插件(如 Calico 用于生产环境,Flannel 用于测试),并结合云厂商服务优化外部访问。