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/24FLANNEL_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:本文属于翻译,原文