kubernets网络的故事
目录
核心总比喻:一个大城市(Kubernetes 集群)的邮政系统
2. Kubernetes 网络模型目标:给每户人家一个标准门牌号
方案A:Flannel - “建立城市邮政专线系统”(Overlay)
方案B:Calico (BGP) - “改造城市路牌系统”(Underlay)
方案A: Flannel VXLAN - “信件被装进一个更大的标准快递箱”
方案B: Calico BGP - “信件直接被寄出,但全城路牌已更新”
5. Service:小区的“公共收发室”和“114查号台”
核心总比喻:一个大城市(Kubernetes 集群)的邮政系统
- 城市 = 一个 Kubernetes 集群
- 小区/街道 = 一个节点(Node)
- 小区里的每户人家 = 一个 Pod
- 每户人家的门牌号 = Pod IP
- 小区的总门牌号 = Node IP
- 邮递员 = 各种网络组件
我们的目标是:让这座城市里的任何一户人家,都能高效、准确地把信(数据包)送给另一户人家,无论他们是否在同一个小区。
1. Docker 的默认网络:老式单位大院
- 原理:就像一个封闭的单位大院(一台宿主机)。所有住户(容器)都住在这个大院里,共享一个大门(同一个网络命名空间)。每户人家没有独立的门牌号,他们通过端口号来区分彼此,就像“叫门房老王转接302室的小张”。
- 通信:
- 院内通信:直接喊一嗓子或者走几步就到了(通过
localhost或内部网络)。 - 院外通信:必须统一从单位大门进出(通过端口映射
-p),非常麻烦,而且容易造成端口冲突。
- 院内通信:直接喊一嗓子或者走几步就到了(通过
- 问题:容器们没有独立的、可路由的IP地址,无法直接与“大院”外的世界沟通。
2. Kubernetes 网络模型目标:给每户人家一个标准门牌号
K8s 定了一个“城市宪法”:
每个 Pod 都必须拥有一个唯一的、可路由的 IP 地址(独立门牌号),并且任何 Pod 都可以用这个 IP 直接与任何其他 Pod 通信,无需进行网络地址转换(NAT)。
这就意味着,我们要把整个城市的所有“小区”(节点)和“住户”(Pod)都纳入一个统一的、巨大的“城市邮政系统”中。
3. 网络方案之争:如何实现这个“城市邮政系统”?
方案A:Flannel - “建立城市邮政专线系统”(Overlay)
Flannel 的做法是,在城市上空建立一个专用的邮政空中缆车系统(Overlay 网络)。
-
VXLAN 模式(智能缆车):
- 打包:当“小区A”的“住户Pod A”要寄信给“小区C”的“住户Pod B”时,小区A的邮局(Flannel)会把信(原始数据包)装进一个标准的缆车运输箱(VXLAN 封装)。箱子上写着“寄往小区C”(目标 Node IP)。
- 运输:缆车沿着专用线路(底层网络)直达小区C。城市的普通公路系统(底层网络)只负责运输这些标准缆车箱,根本不关心箱子里的信是写给谁的。
- 拆包:小区C的邮局拆开运输箱,取出原始的信件,根据信上的原始地址(Pod IP)准确投递到 Pod B 家中。
- 优点:与底层公路系统解耦,能在任何基础上运行。
- 缺点:打包/拆包(封装/解封装)有轻微性能开销。
-
UDP 模式(原始人力传递):非常低效。需要把信的内容念给一个邮差(
flanneld进程)听,邮差跑过去再口述给收件人。基本已被淘汰。
方案B:Calico (BGP) - “改造城市路牌系统”(Underlay)
Calico 的做法更硬核:它不去建空中缆车,而是去改造城市里每一个路口的路牌(节点的路由表)。
- 原理:Calico 的“路政管理员”(BGP Speaker)会跑到每个小区(节点),告诉它:“记住,除了本小区的住户,你还要认识其他所有小区的住户地址(Pod IP)。想去‘小区C的住户B’,直接往‘小区C’的方向走就行。”
- 通信:现在,Pod A 要给 Pod B 寄信,信被送到小区A的邮局。邮局一看路牌(路由表):“哦,地址是小区C的,直接往那边送。” 信件(原始数据包)就通过城市的普通公路系统(底层网络)直接、原封不动地送到了小区C,中间没有任何打包拆包的过程。
- 优点:性能极高,没有封装开销。
- 缺点:对“城市公路系统”(底层网络)有要求,节点之间必须能直接路由。
对比补充
核心差异:信件本身有没有被“重新包装”
让我们回到“Pod A 给 Pod B 寄信”这个场景。我们对比一下信件在离开“小区A”时的最终形态。
场景对比:信件的“出厂设置”
- 原始信件(Pod A 想寄出的数据包):
- 信封[外层]:收件人:Pod B的IP,寄件人:Pod A的IP
- 信封[内层]:HTTP请求内容(比如“GET /index.html”)
- 这封信的格式是标准邮政格式。
现在,我们看两种方案如何处理这封信。
方案A: Flannel VXLAN - “信件被装进一个更大的标准快递箱”
-
打包(封装):
- 小区A的邮局(Flannel)没有直接寄出原始信件。
- 它拿了一个更大、更厚的VXLAN标准快递箱。
- 它把整个原始信件(包括外层信封)原封不动地塞进这个快递箱里。
- 然后,它在这个新快递箱的外面,贴上一张新的快递单:
- 收件人:小区C的地址(目标 Node IP)
- 寄件人:小区A的地址(源 Node IP)
- 备注:内装Pod间信件(VXLAN头,包含VNI等)
**✅ 关键点:原始信件完好无损,但被套了一个新外壳。**
-
运输:
- 这个VXLAN大快递箱被扔进城市的普通物流车(底层网络)。
- 物流车司机(底层网络的路由器/交换机)只认大箱子外面的新快递单。他的任务就是把箱子从“小区A”运到“小区C”。他完全不知道、也不关心大箱子里面还套着一个小信封。
-
拆包(解封装):
- 箱子运到小区C后,邮局拆开VXLAN大快递箱,取出里面完好无损的原始信件。
- 然后根据原始信件上的收件人地址(Pod B IP),送达给Pod B。
总结:VXLAN是“套娃”运输。原始数据包被完整封装在一个新数据包里。底层网络运输的是“新箱子”。
方案B: Calico BGP - “信件直接被寄出,但全城路牌已更新”
-
无需打包:
- 小区A的邮局(Calico)直接寄出了原始信件,没有任何包装!
- 信件的形态和Pod A写的一模一样:
- 信封[外层]:收件人:Pod B的IP,寄件人:Pod A的IP
- 信封[内层]:HTTP请求内容
**✅ 关键点:信件就是原始形态,没有被套上任何新外壳。**
-
运输:
- 这封原始信件被扔进城市的普通物流车(底层网络)。
- 物流车司机(底层网络的路由器/交换机)拿起信一看收件地址是
Pod B IP(比如10.244.2.10)。 - 在Calico部署好后,司机手上已经有一张由BGP协议更新的、全城统一的路牌表。他查表发现:“地址
10.244.2.10?这个地址不属于任何传统小区,但路牌上写着,这个地址段(10.244.2.0/24)归‘小区C’管理。所以,把这封信送到小区C就行了。” - 于是,物流车将信件直接运往小区C。
-
送达:
- 信件到达小区C,邮局一看收件地址
10.244.2.10正是本小区的Pod B,直接送达。
- 信件到达小区C,邮局一看收件地址
总结:Calico BGP是“原信”运输。原始数据包直接被发送。底层网络之所以能识别Pod IP,是因为它的“路牌”(路由表)被BGP提前教育过了。
对比表格:一目了然
| 特性 | Calico (BGP) - “原信寄送” | Flannel (VXLAN) - “套箱寄送” |
|---|---|---|
| 数据包形态 | 原始IP包 收件人:Pod IP |
原始IP包被封装在UDP/VXLAN包内 收件人:Node IP(内部才是Pod IP) |
| 底层网络看到的是什么? | 它看到的是一个目的是 **10.244.2.10 (Pod IP)** 的包。它需要能理解这个IP。 |
它看到的是一个目的是 **192.168.1.12 (Node IP)** 的包。它完全不知道10.244.2.10的存在。 |
| 核心工作 | 扩散路由:让全世界(底层网络)都知道每个Pod IP该怎么走。 | 建立隧道:在Pod IP世界之上建立一个虚拟网络,对底层隐藏Pod IP。 |
| 网络模型 | Underlay(三层路由) | Overlay(二层隧道) |
| 性能 | 更高(无封装/解封装开销) | 稍低(有封装/解封装开销) |
| 要求 | 要求底层网络支持(节点间IP可达,且能学习路由) | 对底层网络几乎无要求,适应性极强 |
结论
4. CNI:邮政系统的“接口标准”
上面介绍的 Flannel 和 Calico 是两个不同的“邮政公司”。Kubernetes 怎么知道该聘请哪家公司呢?它需要一个标准合同。
- CNI (Container Network Interface) 就是这个标准合同。它规定了邮政公司(网络插件)必须实现哪些功能(比如:如何给新 Pod 分配 IP,如何清理网络接口等)。
- K8s 的“城管”(kubelet)只认这份标准合同。当一个新的 Pod(住户)建成时,kubelet 就拿着合同去找已安装的网络插件(如 Flannel)说:“嘿,来给这户新人家通网(分配IP、设置路由)!”
5. Service:小区的“公共收发室”和“114查号台”
现在,每户人家(Pod)都有了自己的门牌号(IP),但还有一个大问题:Pod 是短暂的,今天住这里,明天可能就搬走了(IP会变)。你怎么让外界稳定地找到一组提供相同服务的 Pod(比如一组前端实例)?
Service 就是这个问题的答案,它有两个核心作用:
-
稳定的“公共收发室”地址(VIP):
- Service 会有一个永远不会变的 IP 地址(ClusterIP),就像小区的“公共收发室”地址。
- 外界(或其他服务)想访问这组 Pod,不需要知道每个 Pod 的具体地址,只需要把信寄到“收发室”即可。
- “收发室管理员”(
kube-proxy)负责把来信负载均衡地转发给背后健康的 Pod。
-
“114查号台”(服务发现):
- Service 有一个域名,比如
my-frontend.default.svc.cluster.local。 - 城市里的其他住户(Pod)想联系前端服务,不需要记IP,只需要拨打“114”(CoreDNS)问:“帮我查一下
my-frontend的收发室地址是多少?” DNS 就会返回 Service 的 ClusterIP。
- Service 有一个域名,比如
实现“收发室”工作的“管理员” kube-proxy 有三种工作模式:
- userspace (旧式):管理员在邮局外面来回跑腿,效率低。(基本不用)
- iptables (标准):管理员在邮局里设置了一套自动分拣规则。来信符合什么特征(目标端口是80),就自动扔进哪个筐(对应的Pod)。性能好,但规则多了会慢。
- ipvs (高效):管理员用上了工业级自动分拣机。无论规则再多,分拣速度都极快,性能最佳。
6. Ingress:城市的“高速公路出入口管理局”
Service 解决了城市内部的通信问题。但外部世界(互联网)如何访问城市里的服务(比如一个官网)?
-
LoadBalancer (云服务商):相当于直接雇一个顶级物流公司。你告诉云厂商(如AWS、GCP):“把我这个Service暴露出去。”云商就会直接给你分配一个公网IP(就像给公司分配一个专属的“XXX大厦”地址),所有外部流量都通过这个IP进来。简单,但昂贵,每个Service都需要一个。
-
Ingress (更聪明的方式):相当于城市的“高速公路出入口管理局”。
- 你只需要一个公网IP(通过LoadBalancer或NodePort方式暴露一个入口)。
- Ingress Controller(如Nginx Ingress, Traefik)就是这个“管理局”,它根据HTTP请求的域名(如
a.com)和路径(如/api) 这些“高级信息”,像交警一样,把不同目的的车流(请求)智能地引导到城市内部对应的“小区收发室”(Service)去。 - 优点:一个入口管理所有基于HTTP/HTTPS的服务,成本低,功能强(支持SSL终止、路由等)。
更多推荐


所有评论(0)