主题
第十二部分:K8s 网络模型与 CNI 深度解析
本章深入讲解 K8s 网络模型的四大问题、Service 实现机制、CNI 插件原理与 DNS 优化,是高级运维的核心知识。
12.1 K8s 网络的四大问题
K8s 网络模型需要解决四个核心问题:
| 问题 | 描述 | 解决方案 |
|---|---|---|
| 容器间通信 | 同一 Pod 内的容器互相访问 | 共享 localhost + IPC namespace |
| Pod 间通信 | 跨节点 Pod 互相访问 | CNI 插件(Calico/Cilium/Flannel) |
| Pod 与 Service | Pod 访问 ClusterIP | kube-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 模式
| 特性 | iptables | IPVS |
|---|---|---|
| 规则复杂度 | 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 DaemonSet12.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 匹配)
↓
反向代理到后端 ServiceIngress Controller 选型:
| 控制器 | 特点 | 适用场景 |
|---|---|---|
| nginx-ingress | 成熟稳定,功能丰富 | 通用场景 |
| Traefik | 自动服务发现,配置简洁 | 中小规模 |
| Kong | 插件生态丰富,支持 gRPC | API 网关场景 |
| Cilium Gateway | eBPF 实现,高性能 | 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: 80Gateway 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 用 VXLAN12.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 |
| Service | iptables O(n) vs IPVS O(1),大规模选 IPVS |
| Ingress | HTTP 反向代理;Gateway API 是其下一代替代 |
| CNI 选型 | Calico BGP(同网络)/ VXLAN(跨网络);Cilium eBPF(高性能) |
| DNS | NodeLocal DNSCache 大幅减少 CoreDNS 压力 |
练习
- 在测试集群切换 kube-proxy 到 IPVS 模式,对比 iptables 规则数量变化。
- 使用
tcpdump抓包分析 Pod 跨节点通信的完整路径。 - 部署 NodeLocal DNSCache 并对比 DNS 查询延迟。
- 用 Cilium Hubble 观测集群 L3-L7 流量。