【架构实战】容器网络CNI:让Pod与Pod、Pod与外界自由通信

一、从"容器间无法通信"说起

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级别的安全隔离,控制流量访问

最佳实践:

  1. 生产环境使用Calico或Cilium
  2. 合理规划Pod网段,预留扩展空间
  3. 配置MTU时考虑网络封装开销
  4. 使用NetworkPolicy进行访问控制
  5. kube-proxy使用IPVS模式
  6. 建立网络监控和故障告警机制

血的教训:

网络问题排查起来往往耗时耗力,因为涉及的知识面很广(Linux内核、网络协议、云网络等)。建议平时多学习网络基础知识,建立完善的监控体系,出现问题时能快速定位。

思考题: 你们集群用的是什么CNI插件?有没有遇到过头疼的网络问题?如果Pod之间需要加密通信,你会怎么实现?


个人观点,仅供参考

相关推荐
JAVA面经实录9171 小时前
原码反码补码编码架构与进制底层设计思想
java·架构
容器魔方1 小时前
Kthena Router ScorePlugin 架构与基准测试分析
人工智能·云原生·容器·架构·开源
小杍随笔1 小时前
【iNovel 前端架构深度解析:基于 Vue 3 + TypeScript + Tauri 的跨端小说写作工具】
前端·架构·typescript
龙佚1 小时前
噪声抑制技术:让语音更清晰
算法·架构
无限进步_1 小时前
【Linux】网络发展背景与协议分层模型
linux·运维·网络
heimeiyingwang1 小时前
【架构实战】链路追踪SkyWalking:让请求无所遁形
架构·skywalking
ZStack开发者社区2 小时前
智算云时代,ZStack如何在实践中重塑全栈硬件加速架构?
架构
代钦塔拉2 小时前
CPU架构篇:Intel、AMD与x86、x64、ARM全解析
arm开发·架构
郑寿昌2 小时前
AI重构存储:2026智能数据革命
人工智能·架构