Kubernetes 容器网络模型和典型实现


导读:前文 Kubernetes 中的 ClusterIP、NodePort、LoadBalancer、Ingress 服务访问方式比较中总结了服务接入访问的主要方式 , 以及它们之间隐含关系 。 有了这些概念基础后 , K8s 应用开发和服务部署就容易很多了 , 但 Under the hood 服务访问究竟是如何实现的呢?这篇内容就 Kubernetes 的网络模型和典型的容器网络实现 , 特别是阿里云自己的容器网络插件(Terway)的方案做了一个较详细的总结 。
Pod 之间 Container-to-Container networking
Linux networking namespace 为进程通讯提供了一个逻辑网络栈 , 包括 network devices、routes、firewall rules 。 Network namespace(NS)管理实际是为其中的所有进程提供了一个独立的逻辑网络 Stack 。
缺省情况下 , Linux 将每个进程挂载在 Root NS 下 , 这些进程通过 eth0 通往外面的世界 。
Kubernetes 容器网络模型和典型实现
本文插图
在 Pod 世界里所有其中的容器共享一个 NS , 这些容器都有相同的 IP 和 Port 空间 , 通过 localhost 访问也是互通的 。 Shared storage 也是可以访问的 , 通过 SharedVolume 挂载到容器中 。 如下一个 NS per pod 图例:

Kubernetes 容器网络模型和典型实现
本文插图
同 Node 中 Pod-to-Pod networking
先看同一个 Node 下 Pod 之间的 networking 如何实现?答案是通过Virtual Ethernet Device (or veth pair)的两块 Virtual interfaces , 每块 veth 挂载在一个 NS 上 , 来实现跨 NS 的连接 。 比如 , 一块挂在 Root NS(host)上 , 另一块挂在 Pod NS 上 , 好比一根网线把两个在不同网络空间的 traffic 连接起来了 , 如图:
Kubernetes 容器网络模型和典型实现
本文插图
有了veth pair这条网线 , Pods 网络可以连通到 Root NS 了 , 但在 Root NS 上如何实现对来自不同 Pod 的 packet 通讯呢?答案是通过Linux Ethernet Bridge , 一个虚拟的 Layer2 网络设备来实现不同 network segments 之间的 Ethernet packet switching 。 不得不提这个 old-school 协议:ARP , 实现了 MAC 地址到 IP 地址的发现协议 。 Bridge 广播 ethframe 到所有连接的设备(除发送者外) , 收到 ARP 回复后将 packet forward 到对应 veth 设备上 。 如图:

Kubernetes 容器网络模型和典型实现
本文插图
跨 Node 之间 Pod-to-Pod networking
进入这部分之前 , 先提及 K8s 在其(Pod)networking 设计上的 3 个 fundamental requirements , 任何 networking 部分的实现都必须遵循这三个需求 。

  • 在不使用 NAT 下 , 所有 Pods 都能和其它任何 Pods 通讯
  • 在不使用 NAT 下 , 所有 Nodes 都能和所有 Pods 通讯
  • Pod 所看到自己的 IP 和其它 Pods 看到它的 IP 一定是相同的
简要来看 , K8s 网络模型要求 Pod IP 在整个网络中都能通达 。 具体实现方案有三方面:
  • Layer2(Switching)Solution
  • Layer3(Routing)Solution , 如,Calico, Terway
  • Overlay Solution , 如Flannel
这部分下文介绍 , 目前且认为 Pod IP 的网络通达性是确保的 。
在 Pod 获得 IP 之前 , kubelet 为每个 Node 分配一个 CIDR 地址段(Classless inter-domain routing) , 每个 Pod 在其中获取唯一 IP , CIDR 地址块的大小对应于每个 Node 的最大 Pod 数量(默认 110 个) 。 在 Pod IP 和跨 Node 网络层部署成功后 , 从源 Pod1 到目的 Pod4 的通讯如图:


推荐阅读