摘要:网络是 Kubernetes 最复杂的部分之一。本文从基本原则出发,详解 K8s 网络四大要求、Pod 内/间通信机制、Service 网络实现、DNS 解析、CNI 插件对比及 NetworkPolicy 配置,并提供生产环境排查与选型建议。
一、K8s 网络四大基本要求
Kubernetes 网络模型遵循四条基本原则,保证 Pod 网络扁平、可预测,便于服务发现与负载均衡。
| 规则 | 说明 |
|---|---|
| Pod 内容器通信 | 同一 Pod 内多容器通过 localhost 通信,共享网络命名空间 |
| Pod 间通信 | 所有 Pod 之间可不经 NAT 直接互通,无需端口映射 |
| 节点与 Pod 通信 | 节点可直接与所有 Pod 通信,无需额外网关 |
| Pod IP 一致性 | Pod 自身 IP 与其它 Pod 看到的 IP 一致,无地址转换 |
核心是:每个 Pod 拥有独立 IP,Pod 网络是扁平的。
Pod 内容器: localhost 通信
Pod 与 Pod: 无 NAT 直接互通
Node 与 Pod: 直接通信
Pod IP 一致性
每个 Pod 独立 IP
说明:以上规则保证 Pod 网络扁平、可预测,便于服务发现与负载均衡。
二、K8s 三层网络
Kubernetes 中存在三种网络:节点网络(物理/虚拟机的宿主机网络)、Pod 网络(由 CNI 管理的虚拟网络)、Service 网络(ClusterIP 等虚拟 IP,存在于 iptables/IPVS 规则中)。
Service 网络
Svc-A: 10.96.0.100
Pod 网络 Pod Network
Pod-A: 10.244.1.5
Pod-B: 10.244.2.3
节点网络 Node Network
Node-1: 192.168.1.10
Node-2: 192.168.1.11
CNI 插件管理
kube-proxy
说明:节点网络承载节点间通信;Pod 网络由 CNI 分配和管理;Service 网络为虚拟 IP,由 kube-proxy 通过 iptables/IPVS 实现。
| 网络类型 | IP 范围示例 | 说明 |
|---|---|---|
| 节点网络 | 192.168.1.0/24 | 宿主机物理/虚拟网络 |
| Pod 网络 | 10.244.0.0/16 | CNI 管理的 Pod IP |
| Service 网络 | 10.96.0.0/12 | ClusterIP,仅存在于规则中 |
三、Pod 内通信
同一 Pod 内多个容器共享网络命名空间,通过 localhost 通信。容器间通过回环接口(lo)通信,延迟极低,无跨网络栈开销。
Pod 共享网络命名空间
App 容器 :8080
localhost
Sidecar :9090
工作原理 :kubelet 创建 Pod 时,先创建 pause 容器作为网络命名空间占位,其他容器通过 container.network 共享该命名空间。App 访问 Sidecar 时使用 http://localhost:9090。同一 Pod 内不同容器不能绑定相同端口。
3.1 完整示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: app
image: nginx:alpine
ports:
- containerPort: 80
- name: sidecar
image: busybox
command: ["sleep", "3600"]
bash
# 验证:从 app 容器访问 sidecar 的 localhost
kubectl exec multi-container-pod -c app -- wget -qO- http://localhost:80
# 查看 Pod 网络命名空间内的网络接口
kubectl exec multi-container-pod -c app -- ip addr
# 可见 eth0(veth)、lo(回环),与同 Pod 其他容器共享
四、Pod 间通信
4.1 同节点 Pod 间通信
同一节点上的 Pod 通过 Linux Bridge(如 cbr0)进行二层转发。数据包经 veth 对进入 Bridge,再转发到目标 Pod。
Node 1
veth pair
veth pair
Pod A 10.244.1.2
cbr0 10.244.1.0/24
Pod B 10.244.1.3
工作原理:每个 Pod 的 veth 一端在 Pod 网络命名空间,另一端连接到 cbr0。Pod A 的数据包经 veth 进入 cbr0,由 Bridge 二层转发到 Pod B 的 veth,无需经过节点网络栈。
4.2 跨节点 Pod 间通信
不同节点上的 Pod 需经过节点网络。流量从源 Pod 经 cbr0 到 eth0,经物理网络或隧道到达目标节点的 eth0,再经 cbr0 到目标 Pod。
Node 2
Node 1
物理网络/隧道
Pod A 10.244.1.2
cbr0 10.244.1.0/24
eth0 192.168.1.10
eth0 192.168.1.11
cbr0 10.244.2.0/24
Pod B 10.244.2.3
实现方式:跨节点通信由 CNI 实现,常见方式包括 VXLAN 等 Overlay、BGP 路由通告、或云厂商 VPC 路由。
五、Service 网络工作原理
Service 的 ClusterIP 是虚拟 IP,没有对应的网络接口。kube-proxy 在 iptables/IPVS 中配置 DNAT 规则,将访问 ClusterIP 的流量转发到后端 Pod IP。
访问 my-svc 10.96.0.100:80
10.96.0.100:80 → 10.244.2.3:8080
Pod A
DNS 解析
iptables/IPVS DNAT
Pod B
iptables 模式:kube-proxy 为每个 Service 创建 KUBE-SERVICES 链,规则匹配 ClusterIP:port 后 DNAT 到 KUBE-SEP-xxx 链,再随机选择 Endpoint 做 DNAT。
IPVS 模式:kube-proxy 使用 ipvs 模块,支持 rr、lc、dh 等负载均衡算法,规则数量多时性能优于 iptables。
bash
# 查看 kube-proxy 模式
kubectl get cm -n kube-system kube-proxy -o yaml | grep mode
六、DNS 解析
6.1 域名格式
集群内使用 CoreDNS 解析 Service 域名。Pod 的 /etc/resolv.conf 指向 CoreDNS(如 10.96.0.10)。
| 域名格式 | 示例 | 说明 |
|---|---|---|
| 短名称 | my-svc |
同命名空间内使用 |
| 命名空间 | my-svc.namespace |
跨命名空间 |
| 完整 FQDN | my-svc.namespace.svc.cluster.local |
完整域名 |
6.2 CoreDNS 配置
yaml
# 典型 CoreDNS ConfigMap
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
}
6.3 ndots 优化
Pod 的 resolv.conf 中 options ndots:5 表示域名中少于 5 个点则先尝试加集群后缀。频繁访问外部域名时,建议使用完整域名或调整 ndots 以减少无效查询。
yaml
# 自定义 ndots
spec:
dnsConfig:
options:
- name: ndots
value: "2"
七、CNI 插件
CNI 是 kubelet 与网络插件之间的标准接口。kubelet 在创建/删除 Pod 时调用 CNI 插件,完成 IP 分配、网络配置和清理。
创建 Pod
删除 Pod
kubelet
CNI 插件
分配 IP 配置网络
回收 IP 清理网络
7.1 CNI 插件对比
| 插件 | 架构 | 性能 | NetworkPolicy | 适用场景 |
|---|---|---|---|---|
| Calico | BGP/VXLAN | 高,无 Overlay 时最优 | 原生支持 | 生产环境、多集群 |
| Cilium | eBPF | 极高,内核旁路 | 原生支持 | 高性能、可观测性 |
| Flannel | VXLAN/host-gw | 中等 | 需额外组件 | 入门、简单场景 |
| Weave Net | VXLAN | 中等 | 支持 | 小规模集群 |
| AWS VPC CNI | VPC 直连 | 高 | 支持 | AWS 环境 |
7.2 Calico
- 架构:支持 BGP 直连或 VXLAN Overlay,BGP 模式下无封装开销
- NetworkPolicy:原生实现,支持 Ingress/Egress、命名空间选择器
- 适用:生产环境、需要细粒度网络策略
7.3 Cilium
- 架构:基于 eBPF,在内核层面实现网络策略与负载均衡
- 性能:绕过 iptables,规则规模大时性能优势明显
- 可观测性:内置 Hubble 提供网络可观测性
7.4 Flannel
- 架构:VXLAN 或 host-gw,部署简单
- NetworkPolicy:默认不支持,需配合 Calico 等
- 适用:开发测试、小规模集群
八、NetworkPolicy
NetworkPolicy 用于限制 Pod 之间的网络访问。通过 podSelector、namespaceSelector 和 ports 定义入站/出站规则。依赖 CNI 实现,Calico、Cilium 支持,Flannel 默认不支持。
8.1 完整示例
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- port: 8080
protocol: TCP
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- port: 5432
protocol: TCP
- to:
- namespaceSelector: {}
ports:
- port: 53
protocol: UDP
8.2 字段说明
| 字段 | 说明 |
|---|---|
| podSelector | 选择应用策略的 Pod |
| policyTypes | Ingress(入站)、Egress(出站) |
| ingress.from | 允许访问的来源:podSelector、namespaceSelector、ipBlock |
| ingress.ports | 允许的端口列表 |
| egress.to | 允许访问的目标 |
| egress.ports | 允许的出站端口 |
允许 port 8080
允许
拒绝
frontend role=frontend
backend app=backend
monitoring ns
other-pod 无标签
九、kubectl 网络相关命令
bash
# 查看 Pod IP
kubectl get pods -o wide
# 查看 Service
kubectl get svc
# 从 Pod 内测试 DNS
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes
# 查看 CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 查看 kube-proxy 模式
kubectl get cm -n kube-system kube-proxy -o yaml | grep mode
# 验证 NetworkPolicy
kubectl get networkpolicy -A
十、网络诊断
10.1 Pod 之间不通
bash
# 检查 Pod 是否在同一 CNI 网络
kubectl get pods -o wide
# 从 Pod A ping Pod B IP
kubectl exec -it <pod-a> -- ping <pod-b-ip>
# 检查 NetworkPolicy 是否阻断
kubectl get networkpolicy -A
# 检查 CNI 插件状态
kubectl get pods -n kube-system -l k8s-app=calico-node
10.2 Service 无法访问
bash
# 检查 Service 的 endpoints
kubectl get endpoints <service-name>
# 检查 kube-proxy 是否正常运行
kubectl get pods -n kube-system -l k8s-app=kube-proxy
# 检查 iptables 规则(Node 上执行)
iptables-save | grep <service-clusterip>
10.3 DNS 解析失败
bash
# 检查 CoreDNS 状态
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 检查 CoreDNS 配置
kubectl get configmap coredns -n kube-system -o yaml
# 从 Pod 内测试
kubectl run -it --rm debug --image=busybox -- nslookup kubernetes.default.svc.cluster.local
十一、FAQ
11.1 Pod 网络不通如何排查?
- 确认 Pod 状态与 IP:
kubectl get pods -o wide - 检查 CNI 插件:
kubectl get pods -n kube-system中 Calico/Cilium/Flannel 是否 Running - 检查 NetworkPolicy:
kubectl get networkpolicy -A是否有限制规则 - 跨节点时检查节点间路由或 Overlay 隧道是否正常
11.2 DNS 解析慢如何优化?
- 调整 ndots:外部域名多时降低 ndots 减少无效查询
- 使用完整域名:避免多次 DNS 查询
- 增加 CoreDNS 副本数:
kubectl scale deployment coredns -n kube-system --replicas=3 - 启用 CoreDNS 缓存:确认
cache 30等配置
11.3 CNI 选型建议?
- 云厂商环境:优先考虑 VPC CNI(如 AWS VPC CNI)以利用 VPC 安全组
- 自建集群:Calico(BGP 直连)或 Cilium(eBPF 高性能)
- 需要 NetworkPolicy:排除 Flannel 单机部署,选 Calico 或 Cilium
- 小规模/开发:Flannel 部署简单,可快速验证
11.4 Service ClusterIP 无法 ping 通?
ClusterIP 是虚拟 IP,仅存在于 iptables/IPVS 规则中,不绑定网卡。ping 使用 ICMP,kube-proxy 只配置了 TCP/UDP 的 DNAT,因此 ClusterIP 无法 ping 通。使用 curl 或 wget 测试 HTTP 服务即可。
十二、生产建议
| 类别 | 建议 |
|---|---|
| CNI | 生产环境选用 Calico 或 Cilium,确保 NetworkPolicy 支持 |
| DNS | 合理配置 ndots,外部域名使用完整 FQDN |
| kube-proxy | 大规模集群优先 IPVS 模式 |
| NetworkPolicy | 按最小权限配置 Ingress/Egress,默认拒绝、显式放行 |
| 监控 | 监控 CoreDNS、kube-proxy、CNI 组件健康状态 |
十三、总结
| 组件 | 职责 |
|---|---|
| CNI | Pod 网络分配与管理,跨节点通信 |
| kube-proxy | Service ClusterIP 转发,iptables/IPVS 规则 |
| CoreDNS | 集群内 DNS 解析,服务发现 |
| NetworkPolicy | 网络访问控制,依赖 CNI 实现 |
CNI 插件
Pod 网络
kube-proxy
Service 网络
CoreDNS
服务发现
NetworkPolicy
访问控制