一、从"容器间无法通信"说起
2020年,我第一次在生产环境部署Kubernetes集群时,遇到了一个让我抓耳挠腮的问题:
Pod创建成功了,但是:
- Pod之间无法通信
- Pod无法访问Service
- Pod无法访问公网
- DNS解析不工作
排查了整整两天,服务器重启了三次,配置文件改了几十个版本,最后发现:
问题很简单,就是Node节点的iptables规则被意外清空了。
这个经历让我深刻认识到:Kubernetes的网络模型和CNI插件,是容器世界最核心也最复杂的部分之一。
二、Kubernetes网络模型:理解四类通信
2.1 Pod网络基础
Kubernetes的网络模型遵循一个简单原则:每个Pod都有一个唯一的IP,每个Pod都可以通过这个IP与其他Pod通信。
┌─────────────────────────────────────────────────────┐
│ Node 1 │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Pod A │ │ Pod B │ │
│ │ 10.1.1.10 │◄─┼──► 10.1.1.11 │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ └────────┬────────┘ │
│ ▼ │
│ ┌──────────┐ │
│ │ cni0 │ (网桥) │
│ │ 10.1.1.1 │ │
│ └────┬─────┘ │
└────────────────┼────────────────────────────────────┘
│ eth0 (Node IP: 192.168.1.10)
▼
┌──────────────┐
│ 物理网络 │
│ (交换机) │
└──────────────┘
2.2 四类网络通信
Kubernetes网络模型定义了四种通信场景:
1. Pod-to-Pod(同Node)
Pod A ←→ Pod B(同一个Node上)
2. Pod-to-Pod(跨Node)
Pod A (Node1) ←→ Pod B (Node2)
3. Pod-to-Service
Pod A ←→ Service(ClusterIP/NodePort/LoadBalancer)
4. Pod-to-External
Pod A ←→ 集群外部服务(公网、数据库等)
2.3 为什么需要CNI
CNI(Container Network Interface)是Kubernetes和网络插件之间的接口标准。
┌─────────────────────────────────────────────┐
│ Kubernetes kubelet │
│ │
│ 创建Pod → 调用CNI插件 → 配置网络 │
│ ↓ │
│ ┌───────────────────────────────────────┐ │
│ │ CNI配置文件 │ │
│ │ /etc/cni/net.d/10-calico.conflist │ │
│ │ /etc/cni/net.d/calico-kubeconfig │ │
│ └───────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────┐ │
│ │ CNI插件二进制文件 │ │
│ │ /opt/cni/bin/calico │ │
│ │ /opt/cni/bin/calico-ipam │ │
│ │ /opt/cni/bin/flannel │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
2.4 CNI的工作流程
Pod创建时的网络配置流程:
1. kubelet创建Pod基础设施(pause容器)
↓
2. kubelet调用CNI ADD:
- 读取CNI配置
- 执行CNI插件二进制
↓
3. CNI插件完成网络配置:
- 分配IP(IPAM)
- 创建veth pair
- 配置网络命名空间
- 更新路由表
- 配置iptables规则
↓
4. Pod获得网络连通性
三、主流CNI插件对比:选型指南
3.1 插件对比表
| 特性 | Flannel | Calico | Cilium | Weave |
|---|---|---|---|---|
| 网络模型 | VXLAN/Host-GW | 路由/BGP | eBPF | VXLAN |
| 性能 | 中等 | 高 | 最高 | 中等 |
| 网络策略 | 基础 | 完整 | 完整+L7 | 基础 |
| 运维复杂度 | 低 | 中 | 高 | 低 |
| 社区活跃度 | 高 | 高 | 高 | 中 |
| 主要厂商 | CoreOS | Tigera | Isovalent | Weaveworks |
3.2 Flannel:简单易用
Flannel是最简单的CNI插件,适合刚接触Kubernetes的团队。
Flannel工作原理:
┌──────────────────────────────────────────────────┐
│ Node 1 │
│ Pod A: 10.244.0.10 ──► veth0 ──► cni0 ──► eth0│
│ 封装VXLAN包 ───────────────────────►│
│ │ │
└─────────────────────┼────────────────────────────┘
│ VXLAN(UDP端口8472)
▼
┌─────────────────────┼────────────────────────────┐
│ Node 2 │
│ ◄── VXLAN包 │
│ ▼ │
│ Pod B: 10.244.1.10 ◄── veth0 ◄── cni0 ◄── eth0 │
└──────────────────────────────────────────────────┘
yaml
# Flannel配置
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan",
"VNI": 4096,
"DirectRouting": false
}
}
bash
# 部署Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 查看Flannel状态
kubectl get pods -n kube-flannel
kubectl logs -n kube-flannel -l app=flannel
3.3 Calico:功能强大
Calico是目前生产环境使用最广泛的CNI插件,支持网络策略和BGP路由。
Calico网络架构:
┌─────────────────────────────────────────────────────────┐
│ │
│ Node 1 Node 2 │
│ ┌─────────┐ ┌─────────┐ │
│ │ Pod A │◄─ Felix (路由) ────────────►│ Pod B │ │
│ │10.244.0.10│ │10.244.1.10│ │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
│ └──────────► BIRD (BGP) ◄───────────────┘ │
│ │ │
│ ┌────┴────┐ │
│ │ Route Reflector │ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────┘
yaml
# Calico配置
apiVersion: v1
kind: ConfigMap
metadata:
name: calico-config
namespace: kube-system
data:
# Pod网段
cidr: "10.244.0.0/16"
# Calico backend
calico_backend: "bird"
# Felix配置
veth_mtu: "1440"
yaml
# Calico BGP配置
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: true # 节点间BGP全连接
asNumber: 64512 # 自治系统号
---
# BGP Peer配置(与外部路由器对接)
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: router-peer
spec:
peerIP: 192.168.1.1
asNumber: 64513
bash
# 安装Calico
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
# 查看Calico状态
kubectl get pods -n kube-system | grep calico
kubectl exec -n kube-system calico-node-xxxx -- calico-node status
3.4 Cilium:eBPF新一代
Cilium是目前最先进的CNI插件,利用eBPF实现高性能和L7网络策略。
Cilium架构(基于eBPF):
┌────────────────────────────────────────────────────────┐
│ Node │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ eBPF程序 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ tc过滤 │ │ XDP │ │ sockmap │ │ │
│ │ │(流量控制) │ │(高速转发)│ │(Socket) │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ │ └────────────┴────────────┘ │ │
│ │ │ │ │
│ │ ┌─────┴─────┐ │ │
│ │ │ eBPF Map │ │ │
│ │ │ (路由表) │ │ │
│ │ └───────────┘ │ │
│ └────────────────────┬───────────────────────────────┘ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Pod A │ │ Pod B │ │ Pod C │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└────────────────────────────────────────────────────────┘
yaml
# Cilium配置
apiVersion: v1
kind: ConfigMap
metadata:
name: cilium-config
namespace: kube-system
data:
# eBPF模式
bpf-lb-mode: "xdp" # XDP或虾口
enable-bpf-clock-probe: "true"
# 自动MTU调整
auto-direct-node-routes: "true"
enable-masquerade: "true"
# Hubble(可观测性)
enable-hubble: "true"
hubble-relay-enabled: "true"
yaml
# CiliumNetworkPolicy - L7网络策略
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: http-policy
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/.*"
- method: "POST"
path: "/api/v1/orders"
四、Pod网络原理:深入理解网络配置
4.1 veth pair:连接容器与主机
veth(Virtual Ethernet)是一对虚拟网卡,一头在容器内,一头在主机上。
bash
# 查看Pod的网络接口
kubectl exec -it nginx-pod -- ip addr
# 容器内输出示例:
# 1: lo: <LOOPBACK,UP,LOWER_UP>
# 2: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP>
# inet 10.244.0.10/32
# 查看Node上的veth pair
ip link show | grep cali
# 输出示例:
# 5: cali1234567890@if2: <BROADCAST,MULTICAST,UP,LOWER_UP>
# 其中 @if2 表示对应容器的eth0(容器内是if2)
4.2 网络命名空间隔离
每个Pod运行在自己的网络命名空间中:
bash
# 查看容器的网络命名空间
nsenter --target <PID> --net ip addr
# 或者使用crictl
crictl inspect <container-id> | jq .info.pid
nsenter --target <PID> --net ip addr
4.3 CNI插件的工作细节
以Flannel为例,看Pod创建时CNI做了什么:
bash
# 1. kubelet调用CNI
# /opt/cni/bin/flannel < /etc/cni/net.d/flannel.conflist
# 2. Flannel分配IP(从预定义的网段)
# Pod A获得 10.244.0.10
# Pod B获得 10.244.0.11
# 3. 创建veth pair
ip link add veth123456 type veth peer name eth0
# 4. 将一端移到容器网络命名空间
ip link set eth0 netns <container-pid>
# 5. 在容器内配置IP
ip netns exec <container-pid> ip addr add 10.244.0.10/32 dev eth0
ip netns exec <container-pid> ip link set eth0 up
# 6. 在主机端配置veth
ip link set veth123456 up
# 7. 配置网桥
brctl addif cni0 veth123456
# 8. 添加路由
ip route add 10.244.0.10 dev cni0
五、Service网络:从Pod IP到ClusterIP
5.1 Service是如何工作的
┌─────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Pod A │ │ Pod B │ │ Pod C │ │
│ │ nginx:v1 │ │ nginx:v1 │ │ nginx:v1 │ │
│ │ 10.244.0.10│ │ 10.244.0.11│ │ 10.244.0.12│ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
└─────────┼─────────────────┼─────────────────┼─────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────┐
│ kube-proxy (iptables) │
│ │
│ Service: nginx-svc │
│ ClusterIP: 10.96.0.100 │
│ Port: 80 │
│ │
│ iptables规则: │
│ -A KUBE-SVC-XXXX -d 10.96.0.100 -p tcp │
│ --dport 80 -j KUBE-SEP-XXXX │
└──────────────────────────────────────────────┘
5.2 kube-proxy的工作模式
iptables模式(默认)
bash
# 查看kube-proxy生成的iptables规则
iptables -t nat -L KUBE-SERVICES -n
# 输出示例
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-XXXXXXXX tcp -- 0.0.0.0/0 10.96.0.100 tcp dpt:80
# kube-proxy生成的负载均衡规则
iptables -t nat -L KUBE-SVC-XXXXXXXX -n
# 输出示例
Chain KUBE-SVC-XXXXXXXX (1 references)
target prot opt source destination
KUBE-SEP-AAAA all -- 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.333333333
KUBE-SEP-BBBB all -- 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.500000000
KUBE-SEP-CCCC all -- 0.0.0.0/0 0.0.0.0/0
IPVS模式(高性能)
bash
# kube-proxy切换到IPVS模式
kubectl edit configmap kube-proxy -n kube-system
# 修改mode
data:
config.conf: |
mode: "ipvs"
ipvs:
scheduler: "rr" # 轮询
minSyncPeriod: 5s
syncPeriod: 30s
bash
# 查看IPVS规则
ipvsadm -L -n
# 输出示例
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Weight ActiveConn InActConn
TCP 10.96.0.100:80 rr
-> 10.244.0.10:80 1 5 0
-> 10.244.0.11:80 1 3 0
-> 10.244.0.12:80 1 4 0
5.3 DNS与Service
CoreDNS为Service提供DNS解析:
bash
# Pod内DNS配置
cat /etc/resolv.conf
# 输出示例
nameserver 10.96.0.10 # CoreDNS Service IP
search namespace.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
# DNS解析示例
# nginx-svc.frontend.svc.cluster.local
# 可简写为:
# nginx-svc.frontend (同namespace可省略svc.cluster.local)
# nginx-svc (同namespace可再省略namespace)
yaml
# CoreDNS配置
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
六、网络策略:Pod级别的安全隔离
6.1 默认情况下Pod可被任意访问
yaml
# 默认网络策略(无隔离)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {} # 空选择器 = 所有Pod
policyTypes:
- Ingress
- Egress
6.2 网络策略示例
1. 允许特定Pod访问
yaml
# 只允许带有app=frontend标签的Pod访问nginx
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-nginx
namespace: default
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
2. 允许命名空间访问
yaml
# 允许特定命名空间的Pod访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-production
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- namespaceSelector:
matchLabels:
name: production
podSelector:
matchLabels:
app: frontend
3. 限制Egress流量
yaml
# 限制Pod只能访问外部数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-egress
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
# 允许访问CoreDNS
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# 允许访问数据库
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 3306
6.3 Calico网络策略
Calico支持更丰富的网络策略:
yaml
# Calico GlobalNetworkPolicy
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: isolate-all
spec:
selector: all()
types:
- Ingress
- Egress
ingress:
- action: Deny
egress:
- action: Deny
七、网络故障排查:从入门到精通
7.1 常见网络问题
问题1:Pod无法访问其他Pod
bash
# 1. 检查Pod IP是否配置正确
kubectl exec -it <pod> -- ip addr
kubectl exec -it <pod> -- ip route
# 2. 从源Pod ping目标Pod
kubectl exec -it <source-pod> -- ping <target-pod-ip>
# 3. 检查CNI插件状态
kubectl get pods -n kube-system | grep cni
kubectl logs -n kube-system <cni-pod> --tail=100
# 4. 检查Node上的网络配置
ip link
ip addr
ip route
brctl show
问题2:Pod无法访问Service
bash
# 1. 检查Service是否存在
kubectl get svc <service-name>
# 2. 检查Service的Endpoints
kubectl get endpoints <service-name>
# 3. 检查kube-proxy状态
kubectl get pods -n kube-system -l k8s-app=kube-proxy
kubectl logs -n kube-system <kube-proxy-pod> --tail=50
# 4. 检查iptables规则
iptables -t nat -L KUBE-SVC-XXXX -n
# 5. 从Pod内测试DNS解析
kubectl exec -it <pod> -- nslookup <service-name>
问题3:Pod无法访问公网
bash
# 1. 检查Node是否能访问公网
ping 8.8.8.8
# 2. 检查NAT和 masquerade规则
iptables -t nat -L POSTROUTING -n
# 3. 检查CNI插件的masquerade配置
# Flannel需要配置:
# "delegate": { "masquerade": true }
# 4. 检查VPC路由
# 确保VPC路由表有 0.0.0.0/0 指向NAT网关或Internet网关
7.2 网络诊断工具箱
bash
#!/bin/bash
# network-diagnose.sh - Kubernetes网络诊断脚本
NAMESPACE=$1
POD=$2
TARGET=$3
echo "=== Kubernetes网络诊断 ==="
# 1. Pod基础网络信息
echo -e "\n[1] Pod网络信息"
kubectl exec -it $POD -n $NAMESPACE -- ip addr
kubectl exec -it $POD -n $NAMESPACE -- ip route
# 2. DNS解析测试
echo -e "\n[2] DNS解析测试"
kubectl exec -it $POD -n $NAMESPACE -- nslookup kubernetes.default
kubectl exec -it $POD -n $NAMESPACE -- cat /etc/resolv.conf
# 3. 目标连通性测试
echo -e "\n[3] 连通性测试"
kubectl exec -it $POD -n $NAMESPACE -- ping -c 3 $TARGET
kubectl exec -it $POD -n $NAMESPACE -- curl -v --connect-timeout 5 http://$TARGET
# 4. 查看iptables规则(Node上执行)
echo -e "\n[4] kube-proxy规则"
iptables -t nat -L KUBE-SERVICES -n | head -20
# 5. 检查CNI插件状态
echo -e "\n[5] CNI插件状态"
kubectl get pods -n kube-system | grep -E "cni|flannel|calico"
echo -e "\n=== 诊断完成 ==="
7.3 抓包分析
bash
# 在Node上抓包分析Pod网络流量
# 找到Pod对应的veth设备
PACKET_COUNT=$(ip link show type veth | wc -l)
echo "veth设备数量: $PACKET_COUNT"
# 抓取特定Pod的流量
# 先找到Pod的veth peer
POD_NAME="nginx-7fb96c846b-xkf42"
POD_NAMESPACE="default"
CNI_TYPE="calico"
# 获取Pod的PID(通过crictl)
CONTAINER_ID=$(kubectl get pod $POD_NAME -n $POD_NAMESPACE -o jsonpath='{.status.containerStatuses[0].containerID}' | sed 's/containerd:\/\///')
PID=$(crictl inspect $CONTAINER_ID | jq .info.pid)
# 在Node上抓包
tcpdump -i veth0 -nn host 10.244.0.10 -w /tmp/pod-capture.pcap
# 分析抓包结果
tcpdump -r /tmp/pod-capture.pcap -nn
八、生产环境最佳实践
8.1 CNI选型建议
选型建议:
入门/小规模:
→ Flannel (简单够用,性能足够)
生产环境/中大规模:
→ Calico (功能丰富,社区活跃)
大规模/高性能要求:
→ Cilium (eBPF,性能最优)
需要与现有网络集成:
→ Calico BGP模式
8.2 网络配置检查清单
yaml
# 生产环境网络配置Checklist
基础设施:
[x] CNI插件已安装并正常运行
[x] Pod网段规划合理(/16或更大)
[x] Node之间网络互通(物理网络)
[x] 禁用swap(Kubernetes要求)
CNI配置:
[x] MTU配置正确(考虑封装开销)
[x] IP分配策略配置
[x] NAT masquerade配置
[x] 关键Service网段路由配置
网络策略:
[x] 已配置默认拒绝策略
[x] 关键Pod有访问控制策略
[x] 跨命名空间访问已控制
监控:
[x] CNI插件有监控指标
[x] 网络流量有监控
[x] 网络策略有审计日志
8.3 MTU配置
yaml
# MTU配置对性能影响很大
# Flannel示例
# 物理网络MTU: 1500
# VXLAN开销: 50字节 (外层IP+UDP+VXLAN头)
# 推荐Pod MTU: 1450
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
data:
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan",
"VNI": 4096,
"DirectRouting": false,
"MTU": 1450 # 指定MTU
}
}
8.4 高可用网络架构
生产环境推荐架构:
┌────────────────────────────────────────────────────────┐
│ 负载均衡层 │
│ (MetalLB / 云厂商LB) │
└────────────────────────┬───────────────────────────────┘
│
┌────────────────────────┼───────────────────────────────┐
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Kubernetes Cluster │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ │
│ │ │ Calico │ │ Calico │ │ Calico │ │ │
│ │ │ (BGP) │◄─┼►(BGP) ◄─┼►(BGP) │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ Pod │ │ Pod │ │ Pod │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Route Reflector │ │ │
│ │ │ (BGP路由中枢) │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ 物理网络/BGP │
│ (承载Calico路由) │
└─────────────────────┘
九、踩坑实录:容器网络那些坑
坑1:Pod无法分配IP(IP耗尽)
某次扩容集群,Pod调度到新Node后发现无法分配IP,新Pod一直处于Pending状态。
原因:Flannel的IPAM是按Node分配的,每个Node分配一个子网段。新Node没有分配子网。
解决:在新Node启动前,确保flannel网络已配置好,或者使用IPAM插件统一管理IP池。
坑2:跨Node Pod通信丢包严重
集群运行一段时间后,发现跨Node的Pod通信丢包率很高,延迟也不稳定。
排查:用iperf3测试带宽,发现带宽只有预期的一半。
原因:MTU设置不对,VXLAN封装后数据包超过物理网络MTU,导致分片和丢包。
解决:调整MTU设置,确保考虑VXLAN头部开销。
坑3:kube-proxy重启后Service不可用
kube-proxy重启后,部分Service无法访问。
原因:kube-proxy使用iptables模式,重启后需要重新同步规则,在规则同步完成前服务不可用。
解决:生产环境使用IPVS模式,性能更好,规则同步更快。
坑4:网络策略不生效
配置了NetworkPolicy,但Pod之间仍然可以通信。
原因:使用的CNI插件不支持NetworkPolicy(如Flannel默认不支持),或者策略配置选择器有误。
解决:使用Calico/Cilium等支持网络策略的插件,或者检查策略配置是否正确。
坑5:删除Pod后IP未释放
某些Pod被删除后,其IP没有释放回IP池,导致IP浪费,最终IP耗尽。
原因:CNI插件的IP释放机制有bug,或者Pod异常退出导致清理钩子没有执行。
解决:定期检查IP使用情况,清理孤儿资源,或者升级CNI插件版本。
十、总结
容器网络是Kubernetes最核心也最复杂的部分:
- CNI标准:统一的接口,让不同网络插件可以互换
- Flannel:简单够用,适合入门和小规模场景
- Calico:功能丰富,是生产环境的主流选择
- Cilium:eBPF驱动,性能最优,代表未来方向
- Service网络:kube-proxy + iptables/IPVS实现服务发现和负载均衡
- 网络策略:Pod级别的安全隔离,控制流量访问
最佳实践:
- 生产环境使用Calico或Cilium
- 合理规划Pod网段,预留扩展空间
- 配置MTU时考虑网络封装开销
- 使用NetworkPolicy进行访问控制
- kube-proxy使用IPVS模式
- 建立网络监控和故障告警机制
血的教训:
网络问题排查起来往往耗时耗力,因为涉及的知识面很广(Linux内核、网络协议、云网络等)。建议平时多学习网络基础知识,建立完善的监控体系,出现问题时能快速定位。
思考题: 你们集群用的是什么CNI插件?有没有遇到过头疼的网络问题?如果Pod之间需要加密通信,你会怎么实现?
个人观点,仅供参考