在学习 Kubernetes 网络模型的过程中,了解各种网络组件的作用以及如何交互非常重要。本文就介绍了各种网络组件在 Kubernetes 集群中是如何交互的,以及如何帮助每个 Pod 都能获取 IP 地址。
Kubernetes 网络模型的核心要求之一是每个 Pod 都拥有自己的 IP 地址并可以使用该 IP 地址进行通信。本文将介绍各种网络组件在 Kubernetes 集群中是如何交互的,以及如何帮助每个 Pod 都获取 IP 地址。
在 Kubernetes 中有多种网络设置方法,以及 container runtime 的各种选项。本文将使用 calico 作为 network provider以及使用 containered 作为 container runtime。
在做介绍之前,先来了解下本文所接触到的接口
一、CRI/CNI接口
CRI(容器运行时接口)是一个插件接口,允许 kubelet 使用不同的 container runtimes。各种 container runtimes 都实现了 CRI API,这使用户可以在 Kubernetes 安装中使用他们想要的 container runtimes。常用分runtime主要有docker、containerd、kata、cri-o等
CNI(容器网络接口)项目包含一个为 Linux 容器提供基于通用插件网络解决方案的规则。它由各种插件组成,这些插件在配置 Pod 网络时执行不同的功能。CNI 插件是遵循 CNI 规范的可执行文件。常用的cni插件有flannel、calico以及kube-ovn。
在一个k8s环境中,安装完cni之后,可以在/opt/cni/bin/目录下看到实现当前cni的不同插件,如下:
[root@node1 ~]# ll /opt/cni/bin/
total 285392
-rwxr-xr-x 1 root root 3780654 Apr 9 2023 bandwidth
-rwxr-xr-x 1 root root 4536104 Feb 5 2021 bridge
-rwsr-xr-x 1 root root 58219864 Apr 9 2023 calico
-rwsr-xr-x 1 root root 58219864 Apr 9 2023 calico-ipam
-rwxr-xr-x 1 root root 10270090 Feb 5 2021 dhcp
-rwxr-xr-x 1 root root 4767801 Feb 5 2021 firewall
-rwxr-xr-x 1 root root 2474798 Apr 9 2023 flannel
-rwxr-xr-x 1 root root 4144106 Feb 5 2021 host-device
-rwxr-xr-x 1 root root 3241605 Apr 9 2023 host-local
-rwsr-xr-x 1 root root 58219864 Apr 9 2023 install
-rwxr-xr-x 1 root root 4288339 Feb 5 2021 ipvlan
-rwxr-xr-x 1 root root 3295519 Apr 9 2023 loopback
-rwxr-xr-x 1 root root 4367216 Feb 5 2021 macvlan
-rwxr-xr-x 1 root root 45946850 Oct 24 16:02 multus-shim
-rwxr-xr-x 1 root root 3679140 Apr 9 2023 portmap
-rwxr-xr-x 1 root root 4467317 Feb 5 2021 ptp
-rwxr-xr-x 1 root root 3701138 Feb 5 2021 sbr
-rwxr-xr-x 1 root root 3153330 Feb 5 2021 static
-rwxr-xr-x 1 root root 3379564 Apr 9 2023 tuning
-rwxr-xr-x 1 root root 4287972 Feb 5 2021 vlan
-rwxr-xr-x 1 root root 3759977 Feb 5 2021 vrf
后面我们会讲到上面一些插件的使用
二、IPAM
IPAM(IP Address Management)是一种用于管理IP地址和DHCP(Dynamic Host Configuration Protocol)的工具或系统。IPAM旨在简化和集中管理IP地址分配、子网划分和DHCP配置等任务。
IPAM是一种管理IP地址和DHCP的解决方案,它提供了对IP地址资源的集中管理、监控和控制。通常提供以下功能
-
IP地址分配和管理:IPAM允许管理员有效地分配和管理IP地址,包括静态和动态地址分配。管理员可以轻松跟踪每个IP地址的使用情况,避免地址冲突和资源浪费。
-
子网划分和管理:IPAM允许管理员创建和管理子网,包括对子网进行自动划分和重新划分的能力。管理员可以根据需要分配IP地址范围,确保网络的合理组织和资源利用。
-
DHCP配置和管理:IPAM可以与DHCP服务器集成,提供对DHCP配置的集中管理和控制。管理员可以轻松配置DHCP参数,如IP地址池、租约时间等,并监控DHCP服务器的状态和性能。
-
IP地址审计和跟踪:IPAM记录和跟踪每个IP地址的使用情况,包括分配给特定设备或用户的详细信息。这有助于审计IP地址的使用和追踪网络活动。
-
自动化和集成:IPAM可以自动执行一些常见的管理任务,如IP地址分配、子网划分和DHCP配置。此外,IPAM还可以与其他网络管理工具和系统进行集成,实现更高效的操作和协作。
IPAM有三种模式,host-local、dhcp、static -
host-local
host-local插件从address ranges 中分配IP,将分配的结果存在本地机器,所以这也是为什么叫做host-local。举例如下:
{
"ipam": {
"type": "host-local",
"ranges": [
[
{
"subnet": "10.10.0.0/16",
"rangeStart": "10.10.1.20",
"rangeEnd": "10.10.3.50", ###使用的ip范围
"gateway": "10.10.0.254"
},
{
"subnet": "172.16.5.0/24"
}
],
[
{
"subnet": "3ffe:ffff:0:01ff::/64",
"rangeStart": "3ffe:ffff:0:01ff::0010",
"rangeEnd": "3ffe:ffff:0:01ff::0020"
}
]
],
"routes": [ ##路由信息
{ "dst": "0.0.0.0/0" },
{ "dst": "192.168.0.0/16", "gw": "10.10.5.1" },
{ "dst": "3ffe:ffff:0:01ff::1/64" }
]
}
}################################
################################
但是在calico网络中,使用的不是host-local,而是calico自己开发的插件,calico-ipam.
在k8s集群安装好cni之后,可以在/etc/cni/net.d目录下看到默认配置文件10-calico.conflist,如下:
[root@node1 networks]# cat /etc/cni/net.d/10-calico.conflist
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico",
"log_level": "info",
"log_file_path": "/var/log/calico/cni/cni.log",
"datastore_type": "kubernetes",
"nodename": "node1",
"mtu": 0,
"ipam": {
"type": "calico-ipam" ####功能类似host-local
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "portmap",
"snat": true,
"capabilities": {"portMappings": true}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
}
]
}[root@node1 networks]###############################
##############################
如何能保证在环境中pod的ip地址不会重复
calico网络中,会把大的网络分成小的block,会为每个注册的节点都分配一段,node去标示一个名为PodCIDR的值,代表该Node可以使用的网段是什么,且分配的时候保证为每个pod分配不同的段。如下查看当前默认的ippool
[root@node1 ~]# calicoctl get ippool -o wide
NAME CIDR NAT IPIPMODE VXLANMODE DISABLED DISABLEBGPEXPORT SELECTOR
default-ipv4-ippool 10.233.64.0/18 true Always Never false false all()#####查看为每个节点分配的小的block,如下:
[root@node1 ~]# calicoctl ipam check
Checking IPAM for inconsistencies...Loading all IPAM blocks...
Found 3 IPAM blocks.
IPAM block 10.233.90.0/24 affinity=host:node1: ####可以看到为节点分配的CIDR
IPAM block 10.233.92.0/24 affinity=host:node3:
IPAM block 10.233.96.0/24 affinity=host:node2:
IPAM blocks record 28 allocations.Loading all IPAM pools...
10.233.64.0/18
Found 1 active IP pools.Loading all nodes.
Found 3 node tunnel IPs.Loading all workload endpoints.
Found 25 workload IPs.
Workloads and nodes are using 28 IPs.Looking for top (up to 20) nodes by allocations...
node3 has 12 allocations
node2 has 11 allocations
node1 has 5 allocations
Node with most allocations has 12; median is 11Scanning for IPs that are allocated but not actually in use...
Found 0 IPs that are allocated in IPAM but not actually in use.
Scanning for IPs that are in use by a workload or node but not allocated in IPAM...
Found 0 in-use IPs that are not in active IP pools.
Found 0 in-use IPs that are in active IP pools but have no corresponding IPAM allocation.Check complete; found 0 problems.
[root@node1 ~]#
####################################
查看节点的地址
[root@node1 ~]# kubectl describe node | grep -i cidr
PodCIDR: 10.233.64.0/24
PodCIDRs: 10.233.64.0/24
PodCIDR: 10.233.65.0/24
PodCIDRs: 10.233.65.0/24
PodCIDR: 10.233.66.0/24
PodCIDRs: 10.233.66.0/24 -
dhcp
社区的cni组件中就包含了dhcp这个ipam,但并没有提供一个可以参考的案例,大致逻辑是:
1:向dhcp申请ip时,dhcp会使用rpc访问本地的socket(/run/cni/dhcp.sock)申请一个ip的租约。然后将IP告知调用者。
2:向dhcp删除IP时,dhcp同样通过rpc请求,解除该IP的租约。 -
static
static功能主要是为pod固定ip地址,在社区其他的版本中,还可以通过whereabouts实现此功能。
三、kubelet、cri、cni调用
当在节点上调度 Pod 时,一启动 Pod 就会发生很多事情。这里我们仅关注与 Pod 配置网络有关的动态。一旦在节点上调度了 Pod,将配置网络并启动应用程序容器。流程图如下:
具体流程分析如下:
-
kubelet调用cri
1;当有pod被调度到当前节点时,kubelet 会根据系统使用的runtime来创建pod sandbox 以及网络命令空间
2:完成上述步骤后,下一步调用cni插件
默认在runtime的配置路径中,有定义cni的使用路径,如下:
[root@node2 ~]# cat /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.cn-beijing.aliyuncs.com/kubesphereio/pause:3.8"
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin" ###默认指定cni插件的路径
conf_dir = "/etc/cni/net.d" ###系统中cni配置文件路径
max_conf_num = 1
conf_template = "" -
cri调用cni
1:当请求到达之后,cni根据系统的配置决定使用哪种类型的plugin,默认配置路径在/etc/cni/net.d/路径下
[root@node1 ~]# cat /etc/cni/net.d/10-calico.conflist
{
"name": "k8s-pod-network",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "calico", ####可知使用的cni plugin为calico
"log_level": "info",
"log_file_path": "/var/log/calico/cni/cni.log",
"datastore_type": "kubernetes",
"nodename": "node1",
"mtu": 0,
"ipam": {
"type": "calico-ipam" ###ipam 为calico-ipam
},
"policy": {
"type": "k8s"
},
"kubernetes": {
"kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
}
},
{
"type": "portmap",
"snat": true,
"capabilities": {"portMappings": true}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
}
] -
cni调用各种plugin完成pod网络的初始化
1: 调用bridge plugin 创建虚拟网络设备。首先判断节点上是否存在网桥,如果没有则创建新的网桥(calico中为tunl0,flannel中为cni0)。
2:紧接着创建虚拟网络设备veth pair,将设备的一端加入到网络命名空间,另一端插入到网桥。
3:调用ipam(host-local)分配ip地址,根据calico为每个节点分配的cidr,分配可用的IP地址 -
cni返回ip给container runtime
1:runtime创建pause 容器,并将返回的ip地址加入到命令空间中。
总结:
Kube-controller-manager 为每个节点分配一个 podCIDR。从 podCIDR 中的子网值为节点上的 Pod 分配了 IP 地址。由于所有节点上的 podCIDR 是不相交的子网,因此它允许为每个 pod 分配唯一的IP地址。
Kubernetes 集群管理员可配置和安装 kubelet、container runtime、network provider,并在每个节点上分发 CNI 插件。Network provider agent 启动时,将生成 CNI 配置。在节点上调度 Pod 后,kubelet 会调用 CRI 插件来创建 Pod。在容器情况下,容器的 CRI 插件调用 CNI 配置中指定的 CNI 插件来配置 Pod 网络。所有这些都会影响 Pod 获取 IP地址。