Calico 3.5+ 根据节点标签分配 IP 地址

关于 IP 地址的分配

Calico 能够进行配置,为不同拓扑指定 IP 地址池。例如可能希望某些机架、地区、或者区域能够从同一个 IP 池中获取地址。这对于降低路由数量或者配合防火墙策略的要求会很有帮助。

cni 插件配置参考中的 IP 地址管理章节中包含了三种分配 IP 地址的方式。Kubernetes 注解方式只能用于 Namespace 或者 Pod 一级。剩下的只有两个办法,CNI 配置或者是基于节点选择器的 IP 池,相对于 CNI 配置的方式来说,节点选择器方案省去了修改本地文件的麻烦。

在更高层次上,基于节点选择器的 IP 地址分配方法就是给节点设置标签,然后用节点选择器选择对应的 IP 地址池进行分配。后面的内容中将给出一个详细的例子,用这种方式来设置一种机架亲和方式的 IP 地址分配方案。

如果 Calico 无法根据上述顺序来决定一个 IP 地址池,或者在选定的地址池中找不到可用的 IP 地址,那么这一工作负载就不会分到 IP 地址,无法启动。为了防止这种情况的发生,我们建议所有节点至少有一个合适的地址池。

先决条件

这一功能需要 Calico 在 ETCD 模式下工作

示例:Kubernetes

本例中,我们会创建一个集群,其中包含四个节点,分布在两个机架上,每个机架各两台。示意如下:

1
2
3
4
5
6
7
8
9
10
11
       -------------------
| router |
-------------------
| |
--------------- ---------------
| rack-0 | | rack-1 |
--------------- ---------------
| kube-node-0 | | kube-node-2 |
- - - - - - - - - - - - - - - -
| kube-node-1 | | kube-node-3 |
- - - - - - - - - - - - - - - -

Pod IP 地址范围为 192.168.0.0/16,我们进行如下设计:保留 192.168.0.0/24rack-0, 192.168.1.0/24rack-1

要设置一个没有缺省地址池的的 Calico,首先运行 calicoctl get ippool -o wide,会看到已经创建了一个 192.168.0.0/16 的地址池:

1
2
NAME                  CIDR             NAT    IPIPMODE   DISABLED   SELECTOR
default-ipv4-ippool 192.168.0.0/16 true Always false all()

  1. 删除缺省地址池
    default-ipv4-ippool 地址池已经存在,并占据了整个 /16 块,因此必须删除:calicoctl delete ippools default-ipv4-ippool

  2. 给 Node 打标签。
    要给特定节点分配地址池,节点必须用标签进行标识:

    1
    2
    3
    4
    kubectl label nodes kube-node-0 rack=0
    kubectl label nodes kube-node-1 rack=0
    kubectl label nodes kube-node-2 rack=1
    kubectl label nodes kube-node-3 rack=1

为每个机架创建地址池

rack-0-ippool

1
2
3
4
5
6
7
8
9
10
11
calicoctl create -f -<<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: rack-0-ippool
spec:
cidr: 192.168.0.0/24
ipipMode: Always
natOutgoing: true
nodeSelector: rack == "0"
EOF

rack-1-ippool

1
2
3
4
5
6
7
8
9
10
11
calicoctl create -f -<<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: rack-1-ippool
spec:
cidr: 192.168.1.0/24
ipipMode: Always
natOutgoing: true
nodeSelector: rack == "1"
EOF

现在就创建了两个地址池,使用 calicoctl get ippool -o wide 进行查看:

1
2
3
NAME                  CIDR             NAT    IPIPMODE   DISABLED   SELECTOR
rack-1-ippool 192.168.0.0/24 true Always false rack == "0"
rack-2-ippool 192.168.1.0/24 true Always false rack == "1"

  1. 检查地址池的工作状态
    创建一个 Nginx 的 Deployment,其中包含五个副本,保证分配到每一个节点上。
    1
    kubectl run nginx --image nginx --replicas 5

检查新的 Pod 是否已经根据所在机架获得了应有的 IP 地址。

1
2
3
4
5
6
NAME                   READY   STATUS    RESTARTS   AGE    IP             NODE          NOMINATED NODE   READINESS GATES
nginx-5c7588df-prx4z 1/1 Running 0 6m3s 192.168.0.64 kube-node-0 <none> <none>
nginx-5c7588df-s7qw6 1/1 Running 0 6m7s 192.168.0.129 kube-node-1 <none> <none>
nginx-5c7588df-w7r7g 1/1 Running 0 6m3s 192.168.1.65 kube-node-2 <none> <none>
nginx-5c7588df-62lnf 1/1 Running 0 6m3s 192.168.1.1 kube-node-3 <none> <none>
nginx-5c7588df-pnsvv 1/1 Running 0 6m3s 192.168.1.64 kube-node-2 <none> <none>

可以看到,IP 地址的是根据节点(所在的机架)来选择了对应的地址池进行分配的。

参考地址

-------------本文结束感谢您的阅读-------------