4. 容器网络基础:CNI插件、Pod网络模型与DNS映射

容器网络是Kubernetes集群的神经中枢,它决定了Pod如何通信、Service如何负载均衡、以及CoreDNS如何将服务名解析为可访问的IP地址。本章深入剖析CNI插件(Calico/Flannel/Weave)的实现原理、Pod网络模型的核心机制,以及Service与Endpoint的DNS映射关系,为后续的CoreDNS治理和网络运维打下坚实基础。

4.1 CNI插件:容器网络的基石

CNI(Container Network Interface)是Kubernetes与容器运行时之间的网络配置标准。每个CNI插件负责为Pod分配IP地址、配置网络接口、以及实现网络策略。生产环境中,Calico、Flannel和Weave是最主流的三种选择。

特性 Calico Flannel Weave
网络模型 纯三层BGP路由 Overlay VXLAN/Host-GW Overlay UDP/VXLAN
性能 接近原生(无封包开销) 中等(VXLAN封包约50字节开销) 中等(UDP封包开销较大)
网络策略 原生支持(iptables/IPVS) 不支持(需额外组件) 原生支持(内置加密)
跨节点通信 BGP路由直接交换 VXLAN隧道或Host-GW 自建Overlay隧道
加密支持 需额外配置(WireGuard) 不支持 内置加密(Weave Net)
规模上限 数千节点(BGP可扩展) 数百节点(VXLAN组播限制) 数百节点(隧道开销)
运维复杂度 中高(需BGP配置) 低(开箱即用) 中(需管理Weave Router)
选型建议: 生产环境优先选择Calico,其三层路由模型性能最优,且原生支持NetworkPolicy。Flannel适合开发测试环境或对网络策略无要求的场景。Weave适合需要跨集群加密通信的合规场景。

4.2 Pod网络模型:IP-per-Pod与通信路径

Kubernetes采用“IP-per-Pod”模型,即每个Pod拥有独立的IP地址,Pod内的所有容器共享该IP和网络命名空间。这种模型简化了端口映射和通信逻辑,但要求CNI插件必须解决跨节点Pod的连通性问题。

Pod网络模型与跨节点通信路径 Node 1 (10.0.1.0/24) Pod A eth0: 10.0.1.2 容器1: nginx 容器2: sidecar veth cbr0 网桥 10.0.1.1/24 Node 2 (10.0.2.0/24) Pod B eth0: 10.0.2.3 容器: app veth cbr1 网桥 10.0.2.1/24 宿主机网络层 eth0: 192.168.1.10 (Node1) ↔ eth0: 192.168.1.20 (Node2) 路由表 / 隧道 / BGP 邻居 CNI插件层(Calico/Flannel/Weave) IP分配(host-local / dhcp) | 路由注入 | 隧道管理 | 网络策略 Calico: BGP Route Reflector | Flannel: etcd subnet lease | Weave: Router mesh Pod 网桥 宿主机网络 CNI插件层
关键路径解析: Pod A(10.0.1.2)访问 Pod B(10.0.2.3)时,数据包经过:Pod A eth0 → veth pair → cbr0 网桥 → 宿主机路由表 → CNI插件封装(VXLAN/BGP)→ 对端宿主机 → cbr1 网桥 → veth pair → Pod B eth0。CNI插件决定了中间封装方式。

4.3 Service与Endpoint的DNS映射关系

Service是Kubernetes中访问Pod的抽象层,它通过标签选择器动态关联一组Pod(Endpoint)。CoreDNS负责将Service名称解析为Cluster IP,而Cluster IP再通过iptables/IPVS规则转发到后端Pod IP。理解这个映射链是CoreDNS治理的核心。

4.3.1 映射链路全景

Service → Endpoint → Pod DNS映射链路 客户端Pod curl my-svc:8080 CoreDNS my-svc → 10.96.0.10 (Cluster IP) Service ClusterIP: 10.96.0.10 Selector: app=web EndpointSlice 10.0.1.2:8080 10.0.2.3:8080 kube-proxy 转发层(iptables / IPVS) DNAT规则:10.96.0.10:8080 → 10.0.1.2:8080 或 10.0.2.3:8080(负载均衡) Pod A (10.0.1.2) app=web Pod B (10.0.2.3) app=web Pod C (10.0.3.4) app=web

4.3.2 DNS记录类型与解析行为

DNS记录类型 查询名称 返回结果 典型场景
A记录 my-svc.default.svc.cluster.local Cluster IP(如 10.96.0.10) 普通Service访问
SRV记录 _http._tcp.my-svc.default.svc.cluster.local 端口号 + 域名 服务发现与端口协商
PTR记录 10.0.1.2.in-addr.arpa Pod域名 反向DNS查询
CNAME my-svc.default.svc.cluster.local 外部域名(ExternalName Service) 服务别名
常见陷阱: 当Service的 publishNotReadyAddresses 为false(默认)时,未就绪的Pod不会出现在EndpointSlice中,CoreDNS也不会返回其IP。这会导致滚动更新期间出现短暂的DNS解析“空窗期”,需要配合就绪探针和优雅终止来规避。

4.4 实战:CoreDNS与CNI插件的协同工作

在真实集群中,CoreDNS的Pod本身也运行在CNI插件管理的网络之上。CoreDNS需要能够访问kube-apiserver获取Service和Endpoint信息,同时需要监听集群DNS查询流量。以下是一个典型的CoreDNS部署配置片段:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf {
            max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
spec:
  replicas: 2
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      containers:
      - name: coredns
        image: coredns/coredns:1.11.1
        args: [ "-conf", "/etc/coredns/Corefile" ]
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
CNI对CoreDNS的影响: 如果使用Calico且启用了NetworkPolicy,需要确保CoreDNS的Pod能够被集群内所有命名空间访问。通常建议为CoreDNS创建一个独立的网络策略,允许所有来源的DNS查询(UDP/TCP 53端口),避免因策略误配导致集群DNS解析中断。

4.5 网络排查常用命令

  • 检查Pod网络连通性: kubectl exec -it <pod> -- ping <target-ip>
  • 查看CNI插件状态: kubectl get pods -n kube-system | grep calico 或 kubectl get pods -n kube-system | grep flannel
  • 验证DNS解析: kubectl exec -it <pod> -- nslookup kubernetes.default.svc.cluster.local
  • 查看Endpoint变化: kubectl get endpointslices -n <namespace> -o yaml
  • 追踪数据包路径: kubectl exec -it <pod> -- traceroute <target-ip>
核心结论: CNI插件决定了Pod IP的分配和跨节点通信方式,Service提供了稳定的DNS名称和负载均衡入口,CoreDNS将服务名解析为Cluster IP,kube-proxy再将Cluster IP转发到具体的Pod IP。这四个组件构成了Kubernetes容器网络的完整链路,任何一环出现问题都会导致服务访问异常。