Kubernetes 网络模型的外围要求之一是每个 Pod 应该取得本人的 IP 地址,并且集群中的每个 Pod 应该可能应用该 IP 地址与其进行对话。有几种网络提供商(flannel, calico, canal 等)实现此网络模型。
当我开始应用 Kubernetes 时,我还不分明如何为每个 Pod 调配 IP 地址。我理解了各个组件如何独立工作,然而还不分明这些组件如何组合在一起。例如,我理解了什么是 CNI 插件,然而我不晓得它们是如何被调用的。因而,我想写这篇文章来分享我对各种网络组件的理解,以及如何将它们组合到 kubernetes 集群中,以便每个 Pod 都能接管 IP 地址。
在 kubernetes 中有多种设置网络的办法,以及容器运行时的各种选项。在这篇文章中,我将应用 Flannel 作为网络提供者,并应用 Containered 作为容器运行时。另外,我将假设您晓得容器网络的工作原理,并且仅在上下文中分享一个十分简短的概述。
一些背景概念
容器网络概述
有一些十分好的博客解释了容器网络的工作形式。就上下文而言,我将在这里通过波及 Linux 网桥网络和数据包封装的繁多办法在一个十分高级的概述中进行介绍。
同一主机上的容器
在同一主机上运行的容器能够通过其 IP 地址互相通信的办法之一是通过 linux bridge。在 kubernetes(和 docker)世界中,创立了 veth(虚构以太网)设施来实现此目标。此 veth 设施的一端插入容器网络名称空间,另一端连贯到主机网络上的 linux bridge。同一主机上的所有容器都将 veth 对的一端连贯到 linux 网桥,并且它们能够通过网桥应用其 IP 地址互相通信。linux 网桥也被调配了一个 IP 地址,它充当从目的地到不同节点的 Pod 流出流量的网关。
不同主机上的容器
在不同主机上运行的容器能够通过其 IP 地址互相通信的形式之一是应用数据包封装。Flannel 通过 vxlan 反对此性能,vxlan 将原始数据包包装在 UDP 数据包中并将其发送到指标。
在 kubernetes 集群中,Flannel 在每个节点上创立一个 vxlan 设施和一些路由表条目。每个发往不同主机上的容器的数据包都会通过 vxlan 设施,并封装在 UDP 数据包中。在指标地位,检索封装的数据包,而后将数据包路由到目的地的 pod。
留神:这只是能够配置容器之间的网络的办法之一。
什么是 CRI?
CRI(容器运行时接口)是一个插件接口,容许 kubelet 应用不同的容器运行时。各种容器运行时都实现了 CRI API,这使用户能够在 kubernetes 装置中应用他们抉择的容器运行时。
什么是 CNI?
CNI 我的项目蕴含一个标准,可为 Linux 容器提供基于通用插件的联网解决方案。它还由各种插件组成,这些插件在配置 Pod 网络时执行不同的性能。CNI 插件是遵循 CNI 标准的可执行文件,咱们将在上面的文章中探讨一些插件。
为节点调配 Pod IP 地址的子网
如果要求所有 Pod 具备 IP 地址,那么确保整个集群中的所有 Pod 具备惟一的 IP 地址十分重要。这是通过为每个节点调配一个惟一的子网来实现的,从该子网中为 Pod 调配了该节点上的 IP 地址。
Node IPAM Controller
将 nodeipam
作为选项传递给 kube-controller-manager
的--controllers
命令行标记时,它将为每个节点调配来自集群 CIDR(集群网络的 IP 范畴)的专用子网(podCIDR
)。因为这些 podCIDR
是不相交的子网,因而它容许为每个 Pod 调配一个惟一的 IP 地址。
当 Kubernetes 节点首次向集群注册时,会为其调配一个podCIDR
。要更改调配给集群中节点的podCIDR
,须要先登记节点,而后应用首先利用于 kubernetes 管制立体的任何配置更改来从新注册节点。能够应用以下命令列出节点的podCIDR
。
$ kubectl get no <nodeName> -o json | jq '.spec.podCIDR'
10.244.0.0/24
Kubelet,容器运行时和 CNI 插件 - 如何将它们全副组合在一起
当在节点上调度 Pod 时,启动 Pod 会产生很多事件。在本节中,我将仅着重与为 Pod 配置网络无关的交互。
一旦在节点上调度了 Pod,以下交互将导致配置网络并启动应用程序容器。
容器运行时与 CNI 插件之间的交互
每个网络提供商都有一个 CNI 插件,容器运行时会调用该插件,以在 Pod 启动时为其配置网络。应用容器化作为容器运行时,容器化 CRI 插件将调用 CNI 插件。每个网络提供商都在每个 kubernetes 节点上都装置了一个代理,以配置 pod 网络。装置了网络提供商代理后,它要么随 CNI 配置一起提供,要么在节点上创立一个,而后由 CRI 插件用来确定要调用哪个 CNI 插件。
CNI 配置文件的地位是可配置的,默认值为/etc/cni/net.d/<config-file>
。集群管理员须要在每个节点上交付 CNI 插件。CNI 插件的地位也是可配置的,默认值为/opt/cni/ bin
。
如果应用容器作为容器运行时,则能够在容器配置的 [plugins."io.containerd.grpc.v1.cri".cni]
局部下指定 CNI 配置和 CNI 插件二进制文件的门路。
因为咱们在这里将 Flannel 称为网络提供商,因而我将简要介绍 Flannel 的设置形式。Flanneld 是 Flannel 守护程序,通常作为守护程序安装在 kubernetes 集群上,并以 install-cni
作为初始化容器。install-cni
容器在每个节点上创立 CNI 配置文件 -/etc/cni/net.d/10-flannel.conflist
。Flanneld 创立一个 vxlan 设施,从 apiserver 获取网络元数据,并监督 pod 上的更新。创立 Pod 时,它将为整个集群中的所有 Pod 调配路由,这些路由容许 Pod 通过其 IP 地址相互连接。
容器式 CRI 插件和 CNI 插件之间的交互能够如下所示:
如上所述,kubelet 调用 Containered CRI 插件以创立容器,而 Containered CRI 插件调用 CNI 插件为容器配置网络。网络提供商 CNI 插件调用其余根本 CNI 插件来配置网络。CNI 插件之间的交互如下所述。
CNI 插件之间的交互
各种 CNI 插件可帮忙配置主机上容器之间的网络。对于这篇文章,咱们将参考 3 个插件。
Flannel CNI Plugin
当应用 Flannel 作为网络提供程序时,Containered CRI 插件应用 CNI 配置文件 /etc/cni/net.d/10-flannel.conflist
调用 Flannel CNI 插件。
$ cat /etc/cni/net.d/10-flannel.conflist
{
"name": "cni0",
"plugins": [
{
"type": "flannel",
"delegate": {
"ipMasq": false,
"hairpinMode": true,
"isDefaultGateway": true
}
}
]
}
Fannel CNI 插件与 Flanneld 联合应用。当 Flanneld 启动时,它会从 apiserver 中获取 podCIDR 和其余与网络相干的详细信息,并将它们存储在文件 -run/flannel/subnet.env
中。
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false
Flannel CNI 插件应用 /run/flannel/subnet.env
中的信息来配置和调用网桥 CNI 插件。
Bridge CNI Plugin
Flannel CNI 插件应用以下配置调用 Bridge CNI 插件:
{
"name": "cni0",
"type": "bridge",
"mtu": 1450,
"ipMasq": false,
"isGateway": true,
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24"
}
}
首次调用 Bridge CNI 插件时,它将应用配置文件中指定的 "name": "cni0"
创立一个 Linux 网桥。而后,它为每个 Pod 创立 veth 对 - 该对的一端在容器的网络名称空间中,另一端连贯到主机网络上的 linux 桥。应用 Bridge CNI 插件,主机上的所有容器都连贯到主机网络上的 linux 网桥。
配置完 veth 对后,Bridge 插件将调用主机本地 IPAM CNI 插件。能够在 CNI config 中配置要应用的 IPAM 插件,CRI 插件用于调用 Flannel CNI 插件。
Host-local IPAM CNI 插件
Bridge CNI 插件应用以下配置调用 Host-local IPAM CNI 插件:
{
"name": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24",
"dataDir": "/var/lib/cni/networks"
}
}
Host-local IPAM(IP 地址治理)插件从子网返回容器的 IP 地址,并将调配的 IP 本地存储在主机上的 dataDir-/var/lib/cni/networks/<network-name=cni0>/<ip>
。/var/lib /cni/networks/< 网络名称 =cni0>/<ip>
文件蕴含 IP 调配给的容器 ID。
调用时,Host-local IPAM 插件返回以下无效负载:
{
"ip4": {
"ip": "10.244.4.2",
"gateway": "10.244.4.3"
},
"dns": {}}
总结
Kube-controller-manager 为每个节点调配一个 podCIDR。从 podCIDR 中的子网值中为节点上的 Pod 调配 IP 地址。因为所有节点上的 podCIDR 是不相交的子网,因而它容许为每个 pod 调配惟一的 IP 地址。
Kubernetes 集群管理员可配置和装置 kubelet,容器运行时,网络提供商代理,并在每个节点上散发 CNI 插件。网络提供商代理启动时,将生成 CNI 配置。在节点上调度 Pod 后,kubelet 会调用 CRI 插件来创立 Pod。如果是 Containerd,则 Containered CRI 插件会调用 CNI 配置中指定的 CNI 插件来配置 Pod 网络。所有这些都会使 Pod 取得 IP 地址。
PS:本文属于翻译,原文