-10 +

K8S Network

之前一直做 kubernetes 网络相关的工作,为了系统的学习 kubernetes 网络相关知识。 将之前的工作做一个记录,方便作者自己查找。

定义问题

网络是 kubernetes 系统中核心的一个子模块,总体上提出下面 4 个核心需要解决的问题。

  1. 容器 <–> 容器 之间的通信:这个通过 Pods 的设计和 localhost 来解决,默认解决。
  2. Pod <–> Pod 之间的通信:通过 CNI 插件来解决。
  3. Pod <–> Service 之间的通信:这个通过 services 来解决。
  4. External <–> Service 之间的通信:这个通过 services 来解决。

其中

几点要求

为了解决上述提出的 4 个问题,总体上提出下面三个要求:

  1. 所有 pods 间的通信不通过 NAT。
  2. 所有 pods 和 nodes 之间的通信不通过 NAT(反之亦然)。
  3. pod 自身看到的 IP 和其他 pods 看到的 IP 是一致的。

目的和动机

提出上诉 3 个总的要求的动机和目的是什么呢?

CNI

主要目标

CNI 插件的目标和有官方文档 描述,下面是对其总结,CNI 插件需要完成以下两个主要的工作:

  1. 连通性:确保每个 pod 有默认的 eth0 设备,并且 host 上的 root namespace 可以直达到 pod。
  2. 可达性:确保从其他节点可以到达 pod,并且没有 NAT。

连通性是比较容易理解的,每一个 pod 必须有一个 NIC 来和外部网络通信。解决的是 Pod 和 host 上的网络问题。 在 Node 上的一些本地进程需要能从 root network namespace 到达 PodIP(如:执行 health 和 readiness 检查), 因此需要 root NS 的连通性。

连通性 解决的集群内 Pod 的通信问题,以下是 CNI 插件为 连通性 可以使用的技术:

可达性 在另外一面上,可以需要做以下一系列事情:

次要目标

除了上述描述的目标,我们可能还需要做下面的事情:

上述功能可以通过一个整体的插件来实现,也可以通过插件链来实现, 多个插件的执行是通过配置文件在容器运行时顺序执行。

IaaS

当前基本是 cloud 的环境,这个是趋势,因为云环境下提供了很多 kubernetes 需要的资源 VMs, L4 load-balancers 和 persistent storage (for PersistentVolumes)。 并且在网络这个子模块中,云环境下提供了基于 SDN 的可编程方式。

calico

calico CNI 创建到 veth 设备另外一端是没有 IP 地址的,
为了提供 Pod --> node 方向上的连通性,每一个 veth 对,需要设置 `proxy_arp` 参数,
这个使得 Pod 请求 root NS 的 ARP 请求都能够响应(假定 node 都有一个默认的路由指向自己)

下图演示了,使用 BGP-based 配置,使用了集群外的 route-reflector,IP 和 MAC 填充过程如下:

flannel

这个插件假定存在一个方式来交换相关信息(e.g. VXLAN MAC),
以前这个要求独立的数据库来存储(托管的 etcd),这种方式被认为是一个大的缺点。
现在最新的版本使用 Kubernetes API 来存储这个信息在 Node API object 中。

IP 和 MAC 填充过程如下:

cilium

注意在 root namespace 侧的 veth 一端是没有 IP 地址的,网络的连通性是通过 eBPF 转发到这个设备上的。

如下图所示,我们使用 VXLAN-based 配置,网络拓扑如下:

参考

关于我

85 后程序员, 比较熟悉 Java,JVM,Golang 相关技术栈, 关注 Liunx kernel,目前痴迷于分布式系统的设计和实践。 研究包括但不限于 Docker Kubernetes eBPF 等相关技术。

Blog

Code

Life

Archive