跳到主要内容

K8s 网络模型与 CNI

K8s 网络模型

Kubernetes 对网络有三个基本要求:

  1. Pod 到 Pod:所有 Pod 可以互相通信,无需 NAT
  2. Pod 到 Service:Pod 可以通过 Service 访问其他 Pod
  3. 外部到 Service:外部流量可以通过 Service 进入集群

每个 Pod 有独立的 IP 地址(来自 Pod CIDR),同 Node 的 Pod 通过 Bridge 通信,跨 Node 的 Pod 通过 Overlay 网络或路由转发。

CNI 插件对比

CNI(Container Network Interface)是 K8s 网络的插件规范。

特性FlannelCalicoCilium
定位简单的 Overlay路由 + 策略eBPF 驱动
数据平面VXLAN / host-gwBGP / VXLAN / eBPFeBPF
NetworkPolicy❌ 不支持✅ 完整支持✅ 增强版(L7)
性能中等高(BGP 模式)最高(eBPF)
加密WireGuardWireGuard / IPsecWireGuard / IPsec
学习曲线
适用场景开发/测试生产通用大规模/高性能

Flannel

最简单的 CNI 插件,适合小型集群和学习。

# 安装 Flannel
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

VXLAN 模式:将 Pod 流量封装在 UDP 数据包中,通过 Overlay 网络转发。 host-gw 模式:直接添加路由规则,要求 Node 在同一个二层网络,性能更好。

Calico

生产环境最常用的 CNI 方案。

# 安装 Calico
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

BGP 模式:通过 BGP 协议交换路由信息,无封装开销,性能最优(需要网络支持)。 VXLAN 模式:Overlay 方式,兼容性好。 eBPF 模式:替代 kube-proxy,更高性能。

Calico NetworkPolicy 示例
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-web
namespace: default
spec:
selector: app == 'web'
ingress:
- action: Allow
source:
selector: app == 'frontend'
destination:
ports:
- 80
egress:
- action: Allow

Cilium

基于 eBPF 的下一代 CNI,性能最好。

# 安装 Cilium
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium \
--namespace kube-system \
--set kubeProxyReplacement=true

核心优势

  • eBPF 数据平面:绕过 iptables,直接在内核处理网络
  • L7 策略:可以按 HTTP 路径、gRPC 方法做流量控制
  • 可观测性:Hubble 提供网络流量可视化
Cilium L7 策略示例
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-access
spec:
endpointSelector:
matchLabels:
app: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "80"
rules:
http:
- method: "GET"
path: "/api/v1/.*"

Service 网络实现

iptables 模式(默认)

kube-proxy 为每个 Service 创建 iptables 规则:

# 查看 iptables 规则
iptables -t nat -L KUBE-SERVICES -n

# 示例:Service 10.96.0.10:80 → Pod 10.244.1.5:8080, 10.244.2.3:8080
# KUBE-SVC-xxx 链随机分发到 KUBE-SEP-xxx 链
# KUBE-SEP-xxx 做 DNAT 到具体 Pod IP

问题:规则数量与 Service × Endpoints 成正比,大规模集群性能差。

IPVS 模式

使用 Linux 内核的 IPVS 模块,适合大规模集群。

# 切换到 IPVS 模式
kubectl edit configmap kube-proxy -n kube-system
# mode: "ipvs"
# 重启 kube-proxy
kubectl rollout restart daemonset kube-proxy -n kube-system

# 查看 IPVS 规则
ipvsadm -Ln
特性iptablesIPVS
规则查找线性遍历 O(n)哈希表 O(1)
负载均衡随机RR / WRR / LC / SH 等
适用规模<1000 Service大规模集群
连接追踪conntrack内置

DNS 解析

CoreDNS 为 K8s 提供服务发现。

# Pod 内的 /etc/resolv.conf
nameserver 10.96.0.10 # CoreDNS Service IP
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

# 解析规则(在 default namespace 中)
nslookup myapp # → myapp.default.svc.cluster.local
nslookup myapp.other-ns # → myapp.other-ns.svc.cluster.local
ndots 优化

ndots:5 意味着包含少于 5 个点的域名都会先拼接 search 域。访问外部域名(如 api.example.com)会产生多次无效 DNS 查询。对于频繁访问外部域名的 Pod,可以降低 ndots:

spec:
dnsConfig:
options:
- name: ndots
value: "2"

常见面试问题

Q1: K8s 中 Pod 之间如何通信?

答案

K8s 网络模型要求所有 Pod 可直接通过 IP 互通:

  • 同 Node:通过 Linux Bridge(如 cni0)直接转发
  • 跨 Node:通过 CNI 插件实现,两种方式:
    • Overlay(Flannel VXLAN / VXLAN 模式):封装→传输→解封装
    • 路由(Calico BGP / Flannel host-gw):直接路由,性能更好

Q2: iptables vs IPVS 模式的区别?

答案

  • iptables:线性匹配规则,小集群简单够用,大规模(>1000 Service)性能下降明显
  • IPVS:内核哈希表查找 O(1),支持多种负载均衡算法(RR/WRR/LC),适合大规模集群
  • 实践中 >1000 Service 建议切换 IPVS

Q3: 如何选择 CNI 插件?

答案

场景推荐
开发/测试/学习Flannel(简单易用)
生产通用Calico(成熟稳定,NetworkPolicy 支持好)
大规模/高性能Cilium(eBPF,L7 策略,Hubble 可观测性)

选型关键因素:是否需要 NetworkPolicy、集群规模、性能要求、运维能力。

相关链接