前置知识: 云计算

Kubernetes 网络

7 min中级

K8s 网络模型四层:CNI 插件、Pod 网络、Service(kube-proxy)与 Ingress/NetworkPolicy。

前置知识与学习目标

Kubernetes 网络解决四个递进的问题:容器之间怎么通(Pod 网络)、 服务怎么被发现与负载均衡(Service)、外部流量怎么进来 (Ingress)、谁能访问谁(NetworkPolicy)。这四层各由一个组件家族 实现,理解分层是排错的前提——「Pod 连不上 Service」和「外部连不上 Ingress」是两种完全不同的问题。

完成本文后,你应当能够:说出 K8s 网络模型的三条基本要求;理解 CNI 插件与 kube-proxy 的分工;看懂 iptables 规则大致含义;写出带 TLS 的 Ingress 与默认拒绝的 NetworkPolicy。

1. Kubernetes 网络模型

1.1 三条基本要求

K8s 对「 underneath」的网络实现不做规定,但所有 CNI 都必须满足:

要求含义
Pod 间直接通信Pod 到 Pod 不经过 NAT 直接可达
Node 与 Pod 互通节点与 Pod 通信也无需 NAT
Pod 拥有独立 IP每个 Pod 一个集群内唯一的 IP

「每个 Pod 一个 IP」意味着 Pod 内部视图就是一台普通主机:容器间用 localhost 互访,外部看到的 IP 与容器内 ip addr 看到的一致。这让 传统网络工具(ping、tcpdump)都能直接用于 Pod,也消除了端口映射的 心智负担——对比 Docker 默认桥接模式下「容器端口映射到宿主机」的模型。

1.2 四层流量视角

flowchart TD
    I[Ingress / LB<br/>外部流量入口] --> S[Service 网络<br/>虚拟 IP ClusterIP]
    S --> P[Pod 网络<br/>容器真实 IP]
    P --> N[Node 网络<br/>物理/底层网络]

注意 Service IP 是虚拟的:没有接口持有这个地址,它只存在于 kube-proxy 写入的转发规则里。所以 ping ClusterIP 不通(ICMP 不被 代理)但 TCP 端口可达——这是新手排错第一坑。

2. CNI 插件:Pod 网络的实现者

2.1 常见 CNI 对比

插件数据面特点
CalicoBGP/VXLAN/IPIP网络策略成熟、纯三层可选
FlannelVXLAN/host-gw简单易用(不支持 NetworkPolicy)
CiliumeBPF高性能、L3-L7 策略、可观测
AntreaOVSVMware 生态

2.2 两种基本组网思路

模式描述适用
Overlay(VXLAN/IPIP 封装)Pod 流量封装在底层网络之上二层不通的底层网络、公有云 VPC
路由(BGP/host-gw)底层网络直接学习 Pod 路由自建机房可控网络、性能敏感

封装有开销(额外包头、MTU 减小),路由接近原生性能但要求底层配合。 Calico 与 Cilium 都同时支持两种模式,可按环境切换。

2.3 Cilium 与 eBPF

eBPF 允许在内核中安全地运行沙箱程序,Cilium 用它替换了整套 iptables 数据路径:Service 负载均衡、NetworkPolicy(可精确到 HTTP 方法/路径的 L7 策略)、加密(WireGuard/IPsec)都在内核态完成,绕过 iptables 规则链的线性匹配开销,并配套 Hubble 提供流量级可观测。

3. Pod 网络:veth 与 Pause 容器

3.1 同节点 Pod 通信

Pod A(eth0)<== veth pair ==> 节点网桥/路由(cni0 等)<== veth pair ==> Pod B

每个 Pod 的 eth0 是一根「网线」的一端(veth pair),另一端插在节点上 (网桥或直接进路由表,名称随 CNI 而异)。同节点流量走二层/路由转发。

3.2 跨节点 Pod 通信

Pod A → veth → 节点1 封装/路由 → 底层网络 → 节点2 解封装/路由 → veth → Pod B

Overlay 模式下「封装/解封装」是 VXLAN 头的加卸;路由模式下只是查 一次 BGP 学来的路由表。MTU 是这类网络的经典故障点:Overlay 会 占用约 50 字节包头,若节点网卡 MTU 为 1500 而 Pod 网络未相应调小, 会出现「小包通、大包挂」的诡异现象。

3.3 Pause 容器(infra 容器)

每个 Pod 里有一个不可见的 Pause 容器,它是 Pod 网络命名空间的持有 者:业务容器加入 Pause 创建的网络栈(共享 IP 与端口空间)。业务容器 崩溃重启时,Pause 保持网络命名空间存活,IP 不变——这就是「容器重启 但 Pod IP 稳定」的原因。自 K8s 1.29 起,原生 Sidecar 容器(restartPolicy: Always 的 init 容器,1.33 GA)与业务容器同属一个网络栈,进一步丰富了 Pod 内的容器协作方式。

4. Service 网络:kube-proxy 的两种实现

4.1 工作原理

Client → ClusterIP:Port → (节点上的转发规则)→ 某个后端 Pod IP:Port

kube-proxy 监听 Service/Endpoints 变化,在每个节点上把「ClusterIP -> 后端 Pod」的映射写成内核转发规则。它不是代理进程——流量在内核态就 被转走了。

4.2 iptables 模式

# 每个 Service 一条跳转规则,后端选择用概率链实现随机负载均衡
-A KUBE-SERVICES -d 10.96.0.1/32 -j KUBE-SVC-XXX
-A KUBE-SVC-XXX -m statistic --probability 0.33 -j KUBE-SEP-POD1   # 1/3 去Pod1
-A KUBE-SVC-XXX -m statistic --probability 0.5  -j KUBE-SEP-POD2   # 剩余的1/2去Pod2
-A KUBE-SVC-XXX -j KUBE-SEP-POD3                                    # 其余去Pod3

缺点:规则线性匹配,Service 数量上千后规则更新慢、转发开销增长。 较新的 Kubernetes 版本引入了基于 nftables 的模式作为 iptables 的继任 (逐步成熟),大规模集群可关注。

4.3 IPVS 模式

IPVS 用内核哈希表存储规则,Service 多时性能优势明显,且支持真正的 调度算法:

调度算法描述
rr轮询
lc最少连接
wrr加权轮询
sh源地址哈希(会话保持)

选型经验:中小规模 iptables/nftables 足够;大几百个以上 Service 或需要 最少连接算法时用 IPVS。

5. Ingress:七层入口

5.1 架构

Internet → Ingress Controller(真正的反向代理)→ Service → Pod

Ingress 资源本身什么也不做,它只是路由规则;必须有 Ingress Controller(常驻的 Nginx/Traefik/Envoy 等)去消费这些规则并实际转发。 新装集群「Ingress 建了却不通」,九成是没装 Controller。

进阶:Ingress 的继任者 Gateway API 已于 2023 年发布 v1.0(GA), 角色分离(GatewayClass/Gateway/HTTPRoute)且支持更丰富的路由语义, 新项目值得优先评估(需控制器支持)。

5.2 配置示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: 'true'  # HTTP 强跳 HTTPS
spec:
  ingressClassName: nginx          # 指定由哪个 Controller 实现
  tls:
    - hosts: [example.com]
      secretName: tls-secret       # TLS 证书存于 Secret
  rules:
    - host: example.com
      http:
        paths:
          - path: /api
            pathType: Prefix       # 前缀匹配 /api 及其子路径
            backend:
              service:
                name: api-service
                port:
                  number: 8080
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80

5.3 Ingress Controller 对比

Controller特点
NGINX Ingress社区最广泛、注解生态丰富
Traefik自动发现、配置简单
Envoy(Gateway API)服务网格与新一代网关
KongAPI 网关功能(鉴权/限流插件)

6. NetworkPolicy:三层的「防火墙即代码」

6.1 概念

NetworkPolicy 用标签选择器控制 Pod 间流量(L3/L4)。核心心智模型是 白名单:一旦有策略选中某个 Pod,该 Pod 就进入「未明确允许即拒绝」 状态;没有任何策略时流量全部放行。

6.2 配置示例

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-policy
  namespace: production
spec:
  podSelector:                 # 策略作用对象:app=api 的 Pod
    matchLabels:
      app: api
  policyTypes: [Ingress, Egress]
  ingress:
    - from:
        - namespaceSelector:   # 允许来自 production 命名空间……
            matchLabels: { env: production }
        - podSelector:         # ……且带 app=web 标签的 Pod(取交集需写在同一项内)
            matchLabels: { app: web }
      ports:
        - port: 8080
          protocol: TCP
  egress:
    - to:
        - podSelector:
            matchLabels: { app: database }   # 只允许访问数据库
      ports:
        - port: 5432
          protocol: TCP

注意 from 数组内多个元素是「或」,同一元素内 namespaceSelector 与 podSelector 才是「与」——这是策略写得「比预期宽」的常见原因。

6.3 默认拒绝

# 空选择器 = 命名空间内所有 Pod;只有 policyTypes 无 rules = 全部拒绝
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
    - Ingress

零信任实践:每个命名空间先铺「默认拒绝(入+出)」,再按调用关系逐条 放行。DNS 出站(UDP 53 到 kube-system)是最常被漏掉的一条放行规则, 漏了表现为「服务名解析失败」。

前提:NetworkPolicy 需要 CNI 支持(Calico/Cilium/Antrea 均支持, Flannel 不支持)。装了策略但不生效,先确认 CNI。

小结

  • 初学者要点:网络模型三要求(Pod IP 直通无 NAT);Service IP 是虚拟 的、ping 不通 TCP 通;Ingress 资源必须配 Controller 才生效; NetworkPolicy 是白名单模型,默认拒绝 + 逐条放行;Flannel 不支持 NetworkPolicy。
  • 进阶注意:Overlay 网络的 MTU 问题表现为「小包通大包挂」;iptables 模式在大规模下有规则膨胀问题,可选 IPVS/nftables;Cilium 的 eBPF 数据面带来 L7 策略与流量可观测;namespaceSelector 与 podSelector 的与/或关系是策略放得过宽的常见原因;新项目可评估 Gateway API 取代 Ingress。