Kubernetes中的Pod如何获取IP地址

大约翻译:本文由LinkedIn的SRE工程师撰写,详细介绍了Kubernetes中的“内在魔力”-更准确地说,是CRI,CNI和kube-apiserver的交互-当需要为下一个pod分配IP地址时会发生什么。Kubernetes网络模型



的基本要求之一是每个Pod必须具有自己的IP地址,集群中的其他Pod必须能够在该地址访问它。有许多网络“提​​供者”(法兰绒,印花棉布,运河等)可帮助实现此网络模型。



当我刚开始使用Kubernetes时,对我来说还不完全清楚Pod如何获得其IP地址。即使了解各个组件的功能,也很难想象它们可以一起工作。例如,我知道CNI插件的用途,但是我不知道如何调用它们。因此,我决定写这篇文章来分享我对各种网络组件以及它们如何在Kubernetes集群中一起工作的知识,这些知识使每个Pod都能获得自己的唯一IP地址。



Kubernetes中有多种组织网络的方式,就像容器有不同的运行时选项一样。这篇文章将使用Flannel将群集联网,并使用Containerd作为运行时我还假设您了解容器之间的网络是如何工作的,因此,仅出于上下文考虑,我仅简要介绍一下它。



一些基本概念



容器和网络一目了然



互联网上有许多出色的出版物,解释了容器如何通过网络相互通信。因此,我将仅对基本概念进行一般性概述,并将自己局限于一种方法,该方法涉及创建Linux桥接器和封装数据包。由于容器网络这一主题值得单独撰写,因此省略了详细信息。下面将提供一些特别有用的出版物的链接。



单个主机上的容器



在运行于同一主机上的容器之间建立IP地址通信的一种方法是创建Linux网桥。为此,在Kubernetes(和Docker 中创建了veth(虚拟以太网)虚拟设备veth设备的一端连接到容器的网络名称空间,另一端连接到主机网络上的Linux桥



同一主机上的所有容器的一端连接到网桥,通过它们可以使用IP地址相互通信。Linux网桥还具有IP地址,并充当从Pod到其他节点的出站流量的网关。







不同主机上的容器



数据包封装是不同主机上的容器可以使用IP地址相互通信的方式之一。在Flannel中vxlan技术负责此功能该功能将原始数据包“打包”为UDP数据包,然后将其发送到其目的地。



在Kubernetes集群中,Flannel创建一个vxlan设备并相应地扩展每个节点上的路由表。每个发往不同主机上的容器的数据包都会通过vxlan设备,并封装在UDP数据包中。在目标位置,提取嵌套的程序包并将其重定向到所需的容器。





注意:这只是容器之间联网的一种方式。



什么是CRI?



CRI(容器运行时界面)是允许kubelet使用不同容器运行时环境的插件。CRI API内置在各种运行时环境中,因此用户可以选择自己选择的运行时。



什么是CNI?



CNI项目用于组织Linux容器通用网络解决方案规范另外,它包括在设置Pod网络时负责各种功能的插件CNI插件是符合规范的可执行文件(我们将在下面讨论一些插件)。



子网划分主机以将IP地址分配给Pod



由于群集中的每个Pod必须具有IP地址,因此确保该地址唯一是很重要的。这是通过为每个主机分配一个唯一的子网来实现的,然后从该子网将IP地址分配给该主机上的Pod。



主机IPAM控制器



nodeipam作为参数传递给--controllers kube-controller-manager标志时,它将为CIDR群集中的每个节点分配一个单独的子网(podCIDR)(即,群集网络的IP地址范围)。由于这些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调度到节点会触发以下事件链:







帮助:容器式CRI插件体系结构



容器启动器和CNI插件之间的交互



每个网络提供商都有其自己的CNI插件。容器运行时会启动它,以便在启动时为Pod配置网络。对于容器式,容器式CRI插件负责启动CNI插件



而且,每个提供者都有自己的代理。它安装在所有Kubernetes节点上,并负责将Pod联网。该代理要么随CNI配置一起提供,要么在节点本身上创建。该配置可帮助CRI插件确定要调用的CNI插件。



CNI配置的位置可以自定义;默认情况下它位于中/etc/cni/net.d/<config-file>。群集管理员还负责在每个群集节点上安装CNI插件。它们的位置也可以自定义;默认目录为/opt/cni/bin



使用容器式时,可以[plugins.«io.containerd.grpc.v1.cri».cni]容器式配置文件中的一部分设置config和插件二进制文件的路径



由于我们将Flannel用作我们的网络提供商,因此让我们谈谈设置它的方法:



  • Flanneld(Flannel'a守护程序)通常与DaemonSetinstall-cni作为init-container一样安装在群集中
  • Install-cni在每个节点上创建一个CNI/etc/cni/net.d/10-flannel.conflist配置文件
  • Flanneld创建一个vxlan设备,从API服务器获取网络元数据,并监视pod进行更新。创建它们后,它将在整个群集中传播所有Pod的路由。
  • 这些路由允许Pod使用IP地址相互通信。


有关Flannel如何工作的更多信息,建议您使用本文结尾处的链接。



这是Containerd CRI插件和CNI插件之间的交互关系图:







如上所示,kubelet调用Containerd CRI插件来创建Pod,该Pod已经调用CNI插件来配置Pod网络。这样,网络提供商的CNI插件会调用其他基本的CNI插件来配置网络的各个方面。



CNI插件之间的交互



有各种各样的CNI插件旨在帮助在主机上的容器之间建立网络。本文将重点介绍其中三个。



绒布CNI插件



当使用Flannel作为网络提供者时,Containeded CRI组件使用CNI配置文件调用Flannel CNI插件/etc/cni/net.d/10-flannel.conflist



$ cat /etc/cni/net.d/10-flannel.conflist
{
  "name": "cni0",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
         "ipMasq": false,
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    }
  ]
}


Flannel CNI插件与Flanneld结合使用。在启动时,Flanneld从API服务器提取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插件。



CNI插件桥



使用以下配置调用此插件:



{
  "name": "cni0",
  "type": "bridge",
  "mtu": 1450,
  "ipMasq": false,
  "isGateway": true,
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24"
  }
}


在第一个调用中,它使用创建一个Linux桥接«name»: «cni0»,该桥接在配置中指示。然后为每个吊舱创建一个veth对。一端连接到容器的网络名称空间,另一端连接到主机网络上的Linux桥。CNI Bridge插件将所有主机容器连接到主机网络上的Linux桥。



完成第ve对的配置后,Bridge插件将调用主机本地的CNI IPAM插件。可以在CNI配置中配置IPAM插件类型,CRI插件将其用于调用Flannel CNI插件。



主机本地IPAM CNI插件



网桥CNI使用以下配置调用主机本地IPAM CNI插件



{
  "name": "cni0",
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24",
    "dataDir": "/var/lib/cni/networks"
  }
}


主机本地IPAM插头IP ddress中号anagement - IP地址管理)返回的IP地址容器并将该选择IP的主机在部分指定目录中的子网dataDir- /var/lib/cni/networks/<network-name=cni0>/<ip>该文件包含分配了该IP地址的容器的ID。



调用本地主机IPAM插件时,它将返回以下数据:



{
  "ip4": {
    "ip": "10.244.4.2",
    "gateway": "10.244.4.3"
  },
  "dns": {}
}


概要



Kube-controller-manager将podCIDR分配给每个节点。每个节点的Pod从分配的podCIDR范围内的地址空间获取IP地址。由于节点的podCIDR不重叠,因此为所有pod分配了唯一的IP地址。



Kubernetes集群管理员配置并安装kubelet,容器启动器,网络提供商代理,并将CNI插件复制到每个节点。在启动期间,网络提供商的代理生成CNI配置。当为节点计划Pod时,kubelet会调用CRI插件来创建它。此外,如果使用containerd,则Containerd CRI插件将调用CNI配置中指定的CNI插件来配置Pod网络。这为Pod提供了IP地址。



我花了一些时间来理解所有这些交互的所有细微差别。我希望所获得的经验可以帮助您更好地了解Kubernetes的工作原理。如果我有任何问题,请通过Twitterhello@ronaknathani.com与我联系如果您想讨论本文的内容或其他内容,请随时联系。我很乐意与您交谈!



链接



容器与网络





法兰绒如何工作





CRI和CNI





译者的PS



另请参阅我们的博客:






All Articles