10 | 容器网络:CNI、Service 与 Ingress

📅 2026/7/15 13:58:31 👁️ 阅读次数 📝 编程学习
10 | 容器网络:CNI、Service 与 Ingress

系列专栏《深入剖析 Kubernetes》· 基于张磊极客时间专栏思想整理 · 适合 CSDN 发布

10 | 容器网络:CNI、Service 与 Ingress

K8s 网络是整个体系里最容易被"劝退"的一块,但抓住主线就清晰了:每个 Pod 一个独立 IP,所有 Pod 扁平互通,Service 解决服务发现与负载均衡,Ingress 解决七层路由。本文从模型到组件逐层拆解。

一、容器网络模型:每个 Pod 独立 IP、扁平互通

K8s 对网络有一条硬性约定(“网络模型”):

  1. 任意 Pod 可以不经 NAT 直接访问任意其他 Pod(无论是否在同节点)。
  2. 任意节点可以不经 NAT 访问其上的任意 Pod。
  3. Pod 看到的"自己 IP"和别人看到的"它 IP"一致。

实现方式是:每个 Pod 拥有独立网络命名空间(netns)和独立 IP,同一个 Pod 内多个容器共享这个 netns(通过pause容器兜底),所以容器内用localhost即可互访。节点上通常有一个虚拟网桥(如 cni0),Pod 的 veth 一端在 Pod 内、一端插在网桥上,从而实现同节点 Pod 二层互通;跨节点则交给 CNI 插件打通路由。

+----------------------------------+ +----------------------------------+ | Node A (10.0.0.11) | | Node B (10.0.0.12) | | | | | | +---------+ +---------+ | | +---------+ +---------+ | | | Pod-1 | | Pod-2 | | | | Pod-3 | | Pod-4 | | | | 10.244 | | 10.244 | | | | 10.244 | | 10.244 | | | +----+----+ +----+----+ | | +----+----+ +----+----+ | | | | | | | | | | +--+--+ +--+--+ | | +--+--+ +--+--+ | | |veth | |veth | | | |veth | |veth | | | +--+--+ +--+--+ | | +--+--+ +--+--+ | | | | | | | | | | +--+--------------+--+ | | +--+--------------+--+ | | | cni0 网桥 | | | | cni0 网桥 | | | +--------+---------+ | | +--------+---------+ | +--------------+-------------------+--------+--------------+-------------------+ | 跨节点路由/Overlay (CNI 负责) | +--------------------------------------------+

二、CNI 接口与常见插件

CNI(Container Network Interface)是 K8s 定义的一套网络插件标准接口:kubelet 在创建 Pod 时调用插件的ADD给它配 IP、建 veth;删除时调用DEL。只要实现这套接口,任何网络方案都能接入 K8s——这就是"可插拔网络"。

两个主流插件对比:

插件模式原理优点缺点
FlannelVXLAN跨节点封装 UDP 隧道,Overlay 网络简单、易部署有封包开销
Flannelhost-gw靠节点路由表直连,无封装性能接近原生要求节点二层互通
CalicoBGP节点间用 BGP 协议同步路由高性能、策略丰富(NetworkPolicy)配置较复杂

取舍经验:同机房二层互通、追求性能 → host-gw 或 Calico BGP(无封装);跨网段/云上多子网 → Flannel VXLAN 或 Calico IPIP(Overlay 封装)。Calico 还额外支持网络策略(NetworkPolicy),能做 Pod 间访问控制,这是 Flannel 不具备的。

三、K8s Service:稳定的访问入口

Pod 会漂移、会重启、IP 会变,所以永远不要直接拿 Pod IP 当服务地址。Service 就是给一组 Pod 一个稳定的虚拟 IP(ClusterIP)和 DNS 名,并做负载均衡。

三种主要类型:

  • ClusterIP(默认):集群内部虚拟 IP,仅在集群内可达。
  • NodePort:在每个节点上开一个固定端口(30000-32767),外部节点IP:NodePort可访问。
  • LoadBalancer:向云厂商申请一个外部负载均衡器,把流量引入集群(云环境常用)。
kube-proxy 维护转发规则 | Client Pod v | +----------+ | 访问 | Service | | clusterIP | ClusterIP| |------------| 10.96.x | | +----+----+ | | 负载均衡 (iptables/ipvs) | +-------+-------+ | | | | v v v v Pod-1 Pod-2 Pod-3 Pod-4 (Endpoint 集合)

kube-proxy是怎么把 Service IP 转到 Pod 的?两种模式:

  • iptables 模式:kube-proxy 监听 Service/Endpoint 变化,生成一堆 iptables 规则做 DNAT 转发。简单稳定,但规则多时(成千上万 Service)线性匹配有性能瓶颈。
  • ipvs 模式:基于内核 LVS,用哈希表做转发,支持更多调度算法(rr/wrr/lc…),大规模下性能远优于 iptables。生产推荐 ipvs。

可用kubectl get endpoints <svc>查看 Service 背后实际 Pod 列表(Endpoints 对象)。

四、CoreDNS:服务发现

Pod 之间怎么"通过名字找到 Service"?靠CoreDNS。它作为集群内置 DNS(通常是个 Deployment + ClusterIP Service),把<service>.<namespace>.svc.cluster.local解析成 ClusterIP。K8s 会把 CoreDNS 的地址通过kubelet --cluster-dns注入每个 Pod 的/etc/resolv.conf,于是你在容器里nslookup mysql.default就能直接发现服务,无需硬编码 IP。

五、Ingress:七层路由入口

Service(包括 NodePort/LoadBalancer)是四层(L4,IP+端口)转发,无法根据域名/路径分流。要"把api.example.com转给服务 A、web.example.com/path转给服务 B",就要Ingress(七层 / L7 路由)

Ingress 本身只是"路由规则"对象,真正干活的是Ingress Controller(比如 nginx-ingress),它常以 DaemonSet/Deployment 部署,对外暴露一个 LoadBalancer 或 hostNetwork 端口,读取 Ingress 规则并生成 nginx 配置。

浏览器 | v Ingress Controller (nginx, 对外 80/443) | 根据域名/路径路由 +-----------------------------+ | Host: api.example.com |---> Service api-svc ---> Pod | Host: web.example.com |---> Service web-svc ---> Pod | Path: /blog |---> Service blog-svc --> Pod +-----------------------------+

示例 Ingress(nginx-ingress):

apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:example-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/# 路径重写spec:ingressClassName:nginxrules:-host:api.example.com# 按域名分流http:paths:-path:/v1pathType:Prefixbackend:service:name:api-svcport:number:80-host:web.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:web-svcport:number:80

参数解释:

  • ingressClassName:指定用哪个 Ingress Controller(集群可能装多个)。
  • host:基于 HTTP Host 头做虚拟主机路由,实现"一个入口多站点"。
  • pathType: Prefix:前缀匹配;另有Exact(精确)、ImplementationSpecific
  • rewrite-target:把请求路径重写后再转发给后端,常用于路径前缀剥离。

小结 / 核心要点

  1. K8s 网络模型:每 Pod 独立 IP、扁平互通、无 NAT,由 CNI 插件落地。
  2. CNI 是网络插件标准接口;Flannel(VXLAN/host-gw)简单、Calico(BGP)高性能且支持 NetworkPolicy。
  3. Service 提供稳定 ClusterIP + 负载均衡,类型有 ClusterIP/NodePort/LoadBalancer;kube-proxy 用 iptables(小规模)或 ipvs(大规模推荐)做转发。
  4. CoreDNS 实现"服务名 → ClusterIP"的服务发现,是集群内互相访问的基石。
  5. Ingress 在 Service 之上做七层(域名/路径)路由,由 Ingress Controller 实际执行,是集群统一对外入口。