Skip to content

第十二部分:K8s 网络模型与 CNI 深度解析

本章深入讲解 K8s 网络模型的四大问题、Service 实现机制、CNI 插件原理与 DNS 优化,是高级运维的核心知识。


12.1 K8s 网络的四大问题

K8s 网络模型需要解决四个核心问题:

问题描述解决方案
容器间通信同一 Pod 内的容器互相访问共享 localhost + IPC namespace
Pod 间通信跨节点 Pod 互相访问CNI 插件(Calico/Cilium/Flannel)
Pod 与 ServicePod 访问 ClusterIPkube-proxy(iptables/IPVS)
外部访问 Service外部流量进入集群NodePort / LoadBalancer / Ingress / Gateway API

12.2 Pod 网络原理

12.2.1 网络命名空间

每个 Pod 拥有独立的网络命名空间(Network Namespace):
- 独立的 IP 地址
- 独立的端口空间
- 独立的路由表和 iptables 规则

Pod 内的容器共享网络命名空间:
- 容器间通过 localhost 通信
- 共享同一个 IP 和端口空间(因此端口不能冲突)

12.2.2 CNI 工作流程

Pod 创建

kubelet 调用 CNI 插件

CNI 插件:
  1. 创建 veth pair(一端在 Pod namespace,一端在宿主机)
  2. 分配 IP 地址(从 IPAM 获取)
  3. 配置路由(Pod → 宿主机 → 其他 Pod)
  4. 设置网络策略(如有 NetworkPolicy)

12.3 Service 实现机制

12.3.1 iptables 模式 vs IPVS 模式

特性iptablesIPVS
规则复杂度O(n),Service 越多规则越多O(1),哈希表查找
适用规模< 1000 Service> 1000 Service
负载均衡算法仅随机rr/wrr/lc/sh/sed/nq
连接保持不支持支持 session affinity
内核模块默认加载需要额外加载 ip_vs
bash
# 检查 kube-proxy 模式
kubectl get cm kube-proxy -n kube-system -o yaml | grep mode

# 切换到 IPVS 模式
kubectl edit cm kube-proxy -n kube-system
# 修改 mode: "ipvs"
# 然后重启 kube-proxy DaemonSet

12.3.2 Service 类型详解

ClusterIP(默认)
  → 集群内虚拟 IP,仅内部可访问
  → iptables/IPVS 实现流量转发

NodePort
  → 在集群所有节点上暴露固定端口(30000-32767)
  → 外部通过 NodeIP:NodePort 访问
  → 注意:NodePort 不等于外部端口,中间还经过 kube-proxy 转发

LoadBalancer
  → 自动创建云厂商负载均衡器
  → 适用于公有云环境(AWS ELB、阿里云 SLB)
  → 私有云需要 MetalLB 等方案

ExternalName
  → 不做代理,返回 CNAME DNS 记录
  → 适用于将集群内流量指向集群外服务

12.3.3 Session Affinity(会话保持)

yaml
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600

注意事项:

  • 基于客户端源 IP 做哈希
  • 经过 SNAT(如经过另一个 Service)后源 IP 会变,亲和失效
  • 使用 externalTrafficPolicy: Local 保留客户端真实 IP

12.4 Ingress 与 Gateway API

12.4.1 Ingress 工作原理

外部请求 → 负载均衡器 → Ingress Controller Pod

                    读取 Ingress 规则(Host/Path 匹配)

                    反向代理到后端 Service

Ingress Controller 选型:

控制器特点适用场景
nginx-ingress成熟稳定,功能丰富通用场景
Traefik自动服务发现,配置简洁中小规模
Kong插件生态丰富,支持 gRPCAPI 网关场景
Cilium GatewayeBPF 实现,高性能Cilium CNI 用户

12.4.2 Gateway API(Ingress 的下一代替代)

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
spec:
  gatewayClassName: cilium
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - name: tls-cert
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-route
spec:
  parentRefs:
  - name: my-gateway
  hostnames: ["app.example.com"]
  rules:
  - matches:
    - path: { type: PathPrefix, value: /api }
    backendRefs:
    - name: api-service
      port: 80

Gateway API 相比 Ingress 的优势:

  • 支持 TCP/UDP/gRPC(不仅限 HTTP)
  • 角色分离:平台团队管 Gateway,应用团队管 Route
  • 标准化的扩展机制(Filter 链)
  • 跨命名引用(ReferenceGrant)

12.5 CNI 插件对比

12.5.1 Calico

两种模式:
- BGP 模式:Pod IP 直接路由,无封装开销(同 L2/L3 网络)
- VXLAN 模式:隧道封装,跨 L3 网络(有 ~5% 性能损耗)

生产建议:同机房/同 VPC 用 BGP,跨机房/跨 VPC 用 VXLAN

12.5.2 Cilium(eBPF)

Cilium 用 eBPF 替代 iptables:
- 所有网络策略、负载均衡、可观测性都通过 eBPF 程序实现
- 性能比 iptables 高 10 倍以上(大规模 Service 场景)
- Hubble 提供 L3-L7 全链路可观测性
- 支持 Gateway API 原生实现

12.6 CoreDNS 优化

yaml
# Corefile 优化配置
.:53 {
    errors
    health { lameduck 5s }
    ready
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        fallthrough in-addr.arpa ip6.arpa
    }
    # 缓存优化
    cache 30 {
        success 9984 30     # 正向缓存 9984 条,TTL 30s
        denial 9984 5       # 负向缓存
    }
    # 上游 DNS 转发
    forward . /etc/resolv.conf {
        max_concurrent 1000
    }
}

# NodeLocal DNSCache:减少 CoreDNS 压力
# 在每个节点运行本地 DNS 缓存,命中率 > 95%

12.7 本章小结

核心概念关键要点
Pod 网络每个 Pod 独立 namespace,容器共享 localhost
Serviceiptables O(n) vs IPVS O(1),大规模选 IPVS
IngressHTTP 反向代理;Gateway API 是其下一代替代
CNI 选型Calico BGP(同网络)/ VXLAN(跨网络);Cilium eBPF(高性能)
DNSNodeLocal DNSCache 大幅减少 CoreDNS 压力

练习

  1. 在测试集群切换 kube-proxy 到 IPVS 模式,对比 iptables 规则数量变化。
  2. 使用 tcpdump 抓包分析 Pod 跨节点通信的完整路径。
  3. 部署 NodeLocal DNSCache 并对比 DNS 查询延迟。
  4. 用 Cilium Hubble 观测集群 L3-L7 流量。

上一章:第十一部分:Pod 与工作负载深度解析 下一章:第十三部分:存储、调度与资源管理深度解析