news 2026/8/20 21:12:49

【架构实战】Kubernetes网络模型深度解析:从Pod通信到Ingress网关实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【架构实战】Kubernetes网络模型深度解析:从Pod通信到Ingress网关实战

Kubernetes网络模型深度解析:从Pod通信到Ingress网关实战

一、为什么K8s网络让无数人头疼

上午聊完 Istio 服务网格,很多同学会问:Istio 的 Sidecar 拦截的是"服务间流量",那流量在进入服务网格之前,是怎么在 Kubernetes 集群里流动的?Pod 之间到底怎么通信?为什么 Service 的 IP 有时 ping 不通却能用?Ingress 和 Service 又是什么关系?

这一篇,我们把 Kubernetes 网络这条主线彻底捋清楚:从 Pod 的 IP 是怎么来的,到跨节点流量怎么走,再到外部流量怎么进来,最后附上实战排查手册。

1.1 传统网络与K8s网络的本质差异

在传统虚拟机/物理机架构里,网络模型非常简单:一台机器一个 IP,防火墙规则写在主机上,端口冲突自己管理。运维对网络有绝对的掌控感。

但 K8s 把这一切打碎了:

维度传统主机网络Kubernetes 网络
IP 分配固定、手工规划Pod IP 动态分配、随时漂移
通信主体主机 ↔ 主机Pod ↔ Pod、Pod ↔ Service
网络边界物理网卡/交换机虚拟网络命名空间 + veth
服务发现固定 IP + 端口Service + DNS,动态解析
安全控制防火墙规则NetworkPolicy(一层层策略)

核心矛盾:业务代码还在用"IP:端口"的思维写调用,但 Pod 的 IP 是"临时的"——扩容、故障迁移、滚动更新都会让 IP 变。K8s 网络要解决的第一件事,就是在 IP 随时变化的前提下,让通信依然可靠

1.2 K8s网络要解决的四个问题

  1. Pod 之间的通信:同节点 Pod、跨节点 Pod 怎么互通?
  2. Pod 与 Service 的通信:IP 会变的 Pod,怎么稳定地被访问?
  3. Service 与外部的通信:集群外部(比如数据库、第三方 API)怎么访问集群内服务?
  4. 南北向流量入口:用户的浏览器请求,怎么到达集群里的应用?

这四个问题,就是 K8s 网络的四个层次。下面一层一层拆。


二、K8s网络模型:一条必须遵守的"宪法"

K8s 对网络有一条硬性要求,称为CNI(Container Network Interface)规范,核心就三条:

  1. 每个 Pod 拥有独立的 IP(集群内唯一)
  2. Pod 之间可以直接通信,不需要 NAT(无论是否同节点)
  3. Pod 访问节点、节点访问 Pod,也不需要 NAT

为什么这三条如此重要?因为只有"IP 全网可达、不搞地址转换",才能让 Service、Ingress、Istio 这些上层组件基于一个统一、简单的地址空间做文章。任何 CNI 插件(Flannel、Calico、Cilium……)都必须满足这个模型。

2.1 网络命名空间与veth pair

先看最小单元:一个 Pod 的网络长什么样

┌─────────────────────────── Pod ───────────────────────────┐ │ ┌──────────────┐ ┌──────────────┐ │ │ │ 容器 A │ │ 容器 B │ │ │ │ (业务进程) │ │ (Sidecar) │ │ │ └──────┬───────┘ └──────┬───────┘ │ │ │ eth0 │ │ │ └────────┬─────────┘ │ │ ┌────┴─────┐ │ │ │ pause │ ← Pod 的"网络根容器" │ │ │ 容器 │ 持有 eth0 + IP │ │ └────┬─────┘ │ └──────────────────┼─────────────────────────────────────────┘ │ veth0(veth pair 的一端) ▼ ┌─────────────────────┐ │ cni0 网桥/隧道 │ ← 由 CNI 插件创建 └─────────────────────┘

关键点:Pod 里的所有容器共享一个网络命名空间——这个命名空间由 pause(沙箱)容器持有,业务容器(包括 Sidecar)都把自己的 eth0 挂进去。所以 Pod 内容器通过 localhost 就能互相访问(这也是 Istio Sidecar 能拦截流量的基础)。

而 Pod 的 eth0 另一端,是通过veth pair(虚拟网线)连到 CNI 插件创建的虚拟网络设备上。数据从容器 eth0 出来,就到了 CNI 插件的管辖范围。

2.2 三大主流CNI实现怎么选

CNI 插件数据面技术性能网络策略适用场景
FlannelVXLAN / Host-GW❌ 不支持小集群、快速上手、学习环境
CalicoBGP / IPIP✅ 完整生产主流,策略要求高
CiliumeBPF最高✅ 极强大规模、高吞吐、可观测性

选型建议

  • 学习/试验:Flannel,一条命令装完,原理简单。
  • 生产通用:Calico,网络策略成熟,社区大,坑少。
  • 性能极致/大规模:Cilium,eBPF 内核态转发,延迟低一个量级,还自带可观测性(Hubble),但内核版本要求较高(5.8+ 更佳)。

注意:网络策略(NetworkPolicy)不是 CNI 自带的,Flannel 就不支持。如果你需要"默认拒绝 + 白名单"的安全隔离,直接选 Calico 或 Cilium。


三、Pod间通信原理:从同节点到跨节点

3.1 同节点通信:网桥转发

两个 Pod 在同一个节点上时,通信路径非常短:

Pod A(10.244.1.2) ──veth──> cni0 网桥 ──veth──> Pod B(10.244.1.3)

数据包从 Pod A 的 eth0 出来,经 veth 到达节点的 cni0 网桥,网桥查 MAC 地址表直接转发给 Pod B 的 veth。全程不离开节点,性能损耗几乎为零

3.2 跨节点通信:隧道封装

Pod 在节点 1(10.244.1.0/24),要访问节点 2 的 Pod(10.244.2.0/24),两个网段不同,数据包怎么过去?

以 Flannel VXLAN 模式为例:

节点1 节点2 ┌──────────────────────────┐ UDP 8484 ┌──────────────────────────┐ │ Pod A 10.244.1.2 │ │ Pod B 10.244.2.3 │ │ │ │ │ ▲ │ │ ▼ │ │ │ │ │ cni0 网桥 │ │ cni0 网桥 │ │ │ │ │ │ │ │ ▼ │ │ │ │ │ flannel.1 (VTEP) │ │ flannel.1 (VTEP) │ │ │ │ │ │ │ │ ▼ 原始包 + VXLAN头 │ │ │ 解封装还原原始包 │ │ eth0 10.0.0.11 ──────────►│──────────────────│◄─ eth0 10.0.0.12 │ └──────────────────────────┘ 物理网络 └──────────────────────────┘

VXLAN 的做法是:把 Pod 的原始数据包整个"装进"一个 UDP 包里(外层目的地址是目标节点的物理 IP),通过物理网络传输,到达后再解封装还原。对底层网络完全无感——哪怕物理交换机不支持任何特殊协议也能跑

Calico 的 BGP 模式则不同:它把节点当作 BGP 路由器,直接广播"这些 Pod 网段在这个节点",数据包不封装、直接路由,性能更好,但要求物理网络允许(云厂商 VPC 通常需要配置路由表或 IPIP 模式)。


四、Service与kube-proxy:稳定访问的基石

Pod IP 会漂移,那业务怎么稳定访问?答案是Service

Service 是一个虚拟的"稳定入口":它有一个固定的虚拟 IP(ClusterIP),通过 Label Selector 动态关联一组 Pod。Pod 挂了、扩了、变了,Service 的 IP 不变。

4.1 Service三种类型

类型作用访问方式适用场景
ClusterIP集群内部虚拟 IP集群内访问服务间调用(默认)
NodePort每个节点开放一个端口节点IP:端口 外部访问测试、非云环境暴露
LoadBalancer云厂商 LB + NodePort负载均衡器 IP云上对外暴露

4.2 kube-proxy三种转发模式

kube-proxy 负责把访问 ClusterIP 的流量转发到后端 Pod,有三种实现:

模式原理性能特点
userspace用户态代理转发老古董,已弃用
iptables内核 Netfilter 规则链默认模式,规则多时延迟升高
IPVS内核 LVS 负载均衡规则少、支持多种调度算法

生产建议:直接开 IPVS。iptables 模式下,Service 数量一多(上千条规则),每条新连接都要遍历规则链,延迟明显;IPVS 基于哈希表,O(1) 查找,性能稳定。

4.3 ClusterIP转发链路拆解

访问my-service:8080(ClusterIP 10.96.0.10)时发生了什么:

客户端 Pod │ 访问 10.96.0.10:8080 ▼ PREROUTING ──> KUBE-SERVICES 链 │ 匹配 ClusterIP 10.96.0.10 ▼ KUBE-SVC-XXXX 链(负载均衡) │ 按权重跳转到后端 ▼ KUBE-SEP-YYYY(Endpoint:Pod A / Pod B / Pod C) │ DNAT 改写目的地址为 Pod IP ▼ 真实 Pod(10.244.1.2:8080)

这就是为什么 ClusterIP “ping 不通却能用”——ClusterIP 是 iptables/IPVS 里的一条虚拟规则,不是真实网卡地址,ICMP 没人应答;但 TCP 流量会被规则 DNAT 到真实 Pod,所以业务访问完全正常。


五、DNS与服务发现:让调用方不再硬编码IP

Service 解决了"稳定 IP",但代码里写死 ClusterIP 依然不优雅——换个环境 IP 就变了。K8s 的答案是DNS 服务发现(通常由 CoreDNS 提供)。

5.1 自动生成的DNS记录

K8s 会自动为每个 Service 生成 DNS 记录:

<service-name>.<namespace>.svc.cluster.local

比如 namespaceprod下的order-service,集群内任何 Pod 都可以直接:

curl http://order-service.prod.svc.cluster.local:8080/api/orders

同一 namespace 内还能简写:

curl http://order-service:8080/api/orders

5.2 服务发现实战示例

apiVersion:v1kind:Servicemetadata:name:order-servicenamespace:prodspec:selector:app:order-serviceports:-port:8080# Service 端口targetPort:8080# Pod 容器端口

配合 Deployment 的app: order-service标签,这套配置就完成了:DNS 解析 → Service → 后端 Pod的完整链路。代码里只需要写服务名,IP 的事全交给 K8s。


六、南北向流量:Ingress实战

Service 解决了集群内部和"节点级"的暴露,但生产环境的需求是:一个域名 + 80/443 端口,路由到多个服务。用 NodePort 一个个暴露端口显然不行(端口冲突、无法按域名分流)。这就轮到Ingress登场。

6.1 Ingress vs LoadBalancer

维度LoadBalancerIngress
层级L4(TCP/UDP)L7(HTTP/HTTPS)
按域名/路径路由
TLS 终结部分
成本每个服务一个 LB,贵一个 LB 入口,多个服务共用
典型场景数据库、gRPC、非 HTTPWeb 应用、API 网关

6.2 部署Nginx Ingress Controller

Ingress 本身只是一个 API 对象,真正干活的是Ingress Controller(社区主流是 ingress-nginx,底层是 Nginx + Lua):

# 以 Helm 方式部署 ingress-nginxhelm repoaddingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update helminstallingress-nginx ingress-nginx/ingress-nginx\--namespaceingress-nginx\--create-namespace\--setcontroller.service.type=LoadBalancer

部署后,所有 Ingress 规则由这个控制器监听并动态生成 Nginx 配置。

6.3 Ingress规则配置实战

假设有两个服务:blog-service(博客)和api-service(API),要求:

  • www.example.com→ blog-service
  • api.example.com→ api-service(带 TLS)
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:example-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target:/$2spec:rules:-host:www.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:blog-serviceport:number:80-host:api.example.comhttp:paths:-path:/v1(/|$)(.*)pathType:ImplementationSpecificbackend:service:name:api-serviceport:number:8080tls:-hosts:-api.example.comsecretName:api-tls-secret

请求链路全貌:

用户浏览器 │ https://api.example.com/v1/orders ▼ 云LB(LoadBalancer) ▼ Ingress Controller(Nginx,443/80) │ 按 Host=api.example.com + 路径 /v1/ 匹配规则 │ TLS 终结,rewrite 为 /orders ▼ api-service:8080(ClusterIP) ▼ kube-proxy → 真实 Pod

一句话总结 Ingress 的价值:把"域名、路径、TLS、灰度、限流"这些七层能力集中在一个入口统一管理,业务团队只管写 Ingress 规则,不用碰 LB。


七、网络安全:NetworkPolicy实战

K8s 网络默认"全通"——所有 Pod 之间都能互访。生产环境这显然不行:支付服务凭什么能被任意 Pod 调用?此时需要NetworkPolicy做精细化隔离。

7.1 默认拒绝一切入站

apiVersion:networking.k8s.io/v1kind:NetworkPolicymetadata:name:default-deny-ingressnamespace:prodspec:podSelector:{}# 匹配命名空间所有 PodpolicyTypes:-Ingress# 只管控入站

这条策略一落地,prod命名空间所有 Pod 的入站流量全部被拒——任何新服务上线默认零暴露,必须显式加白名单。

7.2 只允许网关访问订单服务

apiVersion:networking.k8s.io/v1kind:NetworkPolicymetadata:name:allow-gateway-to-ordernamespace:prodspec:podSelector:matchLabels:app:order-servicepolicyTypes:-Ingressingress:-from:-podSelector:matchLabels:app:api-gatewayports:-protocol:TCPport:8080

效果:只有带app: api-gateway标签的 Pod 能访问 order-service 的 8080 端口,其他全部隔离。默认拒绝 + 显式放行是生产集群的标准姿势。

注意:NetworkPolicy 依赖 CNI 支持(Calico/Cilium 均可),Flannel 不生效,且策略要按命名空间维度规划好,否则排查起来非常痛苦。


八、网络排查实战手册

网络问题占了 K8s 排障的一半。按下面的顺序排查,能少走很多弯路。

8.1 Pod之间不通

# 1. 确认 Pod 状态和 IPkubectl get pod-owide-nprod# 2. 进入源 Pod 测试连通性kubectlexec-it<src-pod>-nprod --ping<dst-pod-ip># 3. 不通则查 CNI 状态kubectl get pods-nkube-system|grep-E"flannel|calico|cilium"kubectl logs-nkube-system<cni-pod># 4. 检查 NetworkPolicy 是否误拦kubectl get networkpolicy-A

常见原因:CNI 组件异常、NetworkPolicy 拦截、节点路由表缺失(Calico BGP 未建立)。

8.2 DNS解析失败

# 在 Pod 内测试 DNSkubectlexec-it<pod>--nslookuporder-service.prod.svc.cluster.local# 检查 CoreDNSkubectl get pods-nkube-system|grepcoredns kubectl logs-nkube-system<coredns-pod>--tail=50

常见原因:CoreDNS 副本数不足(建议≥2)、resolv.conf里的search域被覆盖(重点查dnsPolicy)、上游 DNS 不通。

8.3 Service访问不通

# 1. 检查 Endpoints 是否有后端kubectl get endpoints<service>-nprod# 如果 ENDPOINTS 为空 → selector 没匹配上 Pod,最经典的坑!# 2. 检查 kube-proxy 模式与状态kubectl get pods-nkube-system|grepkube-proxy# 3. 检查 iptables/IPVS 规则# IPVS 模式:ipvsadm-ln|grep<cluster-ip>

最常见的坑:Service 的selector标签和 Pod 标签不一致,导致 Endpoints 为空,Service 看起来存在但永远连不通。


九、总结

把 K8s 网络这条主线串起来:

  1. CNI 插件解决"Pod 怎么拿到 IP、怎么互通"——Flannel/Calico/Cilium 按需选型;
  2. Service + kube-proxy解决"Pod IP 漂移怎么稳定访问"——ClusterIP 是虚拟规则,生产开 IPVS;
  3. CoreDNS解决"代码不写死 IP"——服务名就是地址;
  4. Ingress解决"外部流量怎么按域名/路径进来"——七层统一入口;
  5. NetworkPolicy解决"谁能访问谁"——默认拒绝 + 白名单。

回到开头的问题:Istio 建立在 K8s 网络之上——K8s 网络保证"包能到",Istio 保证"流量怎么治理"。理解了这一层网络地基,再看服务网格、再看云原生架构,都会有豁然开朗的感觉。

下一篇可以聊聊Kubernetes 调度与资源管理,把 Pod 是怎么被"安放"到节点上的原理讲透,敬请期待。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/20 21:07:47

抖音视频解析器

链接&#xff1a;https://pan.quark.cn/s/fca46ad0e155有没有人和我一样&#xff0c;刷抖音刷到优质视频&#xff0c;想保存本地特别糟心官方自带保存强制自带水印&#xff0c;遮挡画面观感极差&#xff1b;还有一部分作品作者关闭下载权限&#xff0c;直接连保存按钮都没有&am…

作者头像 李华
网站建设 2026/8/20 20:56:16

自选基金助手新手指南:7天把基金实时监控工具用顺手

自选基金助手新手指南&#xff1a;7天把基金实时监控工具用顺手 【免费下载链接】funds 自选基金助手是一款Chrome扩展&#xff0c;用来快速获取关注基金的实时数据&#xff0c;查看自选基金的实时估值情况 项目地址: https://gitcode.com/gh_mirrors/fu/funds 开场&…

作者头像 李华