IPPool
¶
IPPool
表示 Calico 期望从中给 Pod 分配 IP 的地址集合。通过 Kubespray 拉起 Calico 之后,会分别为 IPv4、IPv6 创建一个默认的地址池:
default-ipv4-ippool
和 default-ipv6-ippool
。
运行命令:
输出为:
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
annotations:
projectcalico.org/metadata: '{"uid":"637e72f1-d4ff-433c-92c5-cafe3aef5753","creationTimestamp":"2022-05-12T14:34:03Z"}'
creationTimestamp: "2022-05-12T14:34:03Z"
generation: 1
name: default-ipv4-pool
resourceVersion: "689"
uid: c94af437-5a37-46c8-b521-641724b86ff8
spec:
allowedUses:
- Workload
- Tunnel
blockSize: 26
cidr: 10.244.0.0/18
ipipMode: Never
natOutgoing: true
nodeSelector: all()
vxlanMode: Always
BlockSize
¶
在 Calico IPAM 中,IPPool
被细分为 Block,这些 Block 与集群中的特定节点相关联。
集群中的每个节点可以有一个或多个与之相关的 Block。当集群中的节点或 Pod 的数量增加或减少时,Calico 会根据需要自动创建和销毁 Block。
Block 的存在使 Calico 可以有效地聚合分配给同一节点上的 Pod 地址,这将会减少路由表的大小。 默认情况下,Calico 将会从节点相关的 Block 中分配 IP,并在必要时创建新的 Block。 Calico 也支持从与该节点不相关的 Block 中分配IP 地址。默认情况下,Calico 创建的 Block 可容纳 64 个地址(掩码为 /26),该地址数量支持自定义设置。
Note
在集群节点数量较多且 IPPool Cidr
不足的情况,我们往往需要根据集群规模提前规划好 IPPool
和 BlockSize
的大小。
否则可能会出现某些节点无法分配到 Block
的情况。
-
BlockSize
默认为 26,即每个 block 拥有 2^(32-26) = 64 个地址。可由calico node env
:CALICO_IPV4POOL_BLOCK_SIZE
控制 (IPv4: 20-32;IPv6:116-128)。 -
Calico 要求
BlockSize
必须大于或者等于IPPool
的 CIDR 的掩码,但在实际环境中应确保每个节点至少有一个 Block。 所以 Block 的个数应该大于等于节点的个数. 即 2^(BLOCK_SIZE-IPPool_MASK
) >= NUM(nodes)。
指定多个默认池¶
随着集群的扩张或 Pod 数量的增加,默认地址池的地址数量可能不足。
这会导致 Pod 可能无 IP 可用或者某些节点没有可分配的 Block。
我们可以通过修改 Calico 的配置文件,使其在 IP 地址不够的时候,选择其他的 IPPool
。
创建新的 IPPool
池¶
运行命令:
输出为:
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: extra-ippool
spec:
cidr: 192.168.0.0/20
blockSize: 26
vxlanMode: Always
natOutgoing: true
EOF
其中,
-
cidr
:可由实际环境决定 IP 地址范围 -
blockSize
:默认为 26,根据实际集群规模决定。缩小blockSize
意味着每个 Block 中的地址变多,但 Block 总的数量会减少。 这适用于节点数不多但每节点上 Pod 比较多的场景。增大blockSize
意味着每个 Block 中的地址变少,但 Block 总的数量会增加。 这适用于节点数较多的场景。但总的来说,只要IPPool
的 CIDR 足够大,可不调整blockSize
(保持默认即可)。 -
vxlanMode
:采用vxlan
模式用于跨子网通信 -
natOutgoing
:跨IPPool
通信是否需要snat
IPPool
细粒度控制¶
默认情况下,IPPool
是集群全局共享的。但是。也可以将 IPPool
指定分配给特定的节点、租户、Pod。
节点过滤¶
在 IPPool
中根据 nodeSelector
字段去匹配特定的节点,只有特定节点才可以从此 IPPool
中去分配 IP。
-
给节点打上 label
-
在
IPPool
中配置nodeSelector
运行命令:
但此 IPPool
不会影响到该节点已经创建的 Pod,如果要更新其 Pod 从该 IPPool
分配地址,则需要 recreate pod
。
进一步了解高级的 selector 语法。
租户过滤¶
可通过在 namespace 中打上特定的 annotation,使该 namespace 下的 Pod 会从此 label 对应的 ippool
分配 IP。
如果要为 namespace 添加 annotation,则编辑 namespace,在 annotation 中添加如下的 key-value 对:
value 为 ippool
的 name 列表。如果是 ipv6,那么 key 为:cni.projectcalico.org/ipv6pools
。
Note
此操作只能保证此 namespace 下的 Pod 会从 extra-ippools
中分配 IP。
但其他 namespace 的 Pod 仍然可以从 extra-ippools
分配 IP。
Pod 过滤¶
可通过在 Pod 的 Annotation 中指定 ippool
,使 Pod 从该 ippool
中分配地址:
改变 BlockSize
¶
在安装 Calico 之前,应事先定义好
blockSize
。因为安装之后,BlockSize
的值不能编辑。 因此,建议在安装前更改 IPPool block 的大小,以尽量减少对 Pod 连接的中断。
改变 BlockSize
步骤:
-
创建临时的
ippool
apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: temporary-pool spec: cidr: 10.0.0.0/16 ipipMode: Always natOutgoing: true
Note
注意不要跟现有的
ippool
子网冲突。 -
将
default-ipv4-ippool
设置为disable
其中,
default-ipv4-ippool
为将要修改的 ippool 的名称。 -
检查
ippool
的状态运行命令:
$ calicoctl get ippool -o wide NAME CIDR NAT IPIPMODE DISABLED default-ipv4-ippool 192.168.0.0/16 true Always true temporary-pool 10.0.0.0/16 true Always false
default-ipv4-ippool
已DISABLED
,新创建的 Pod 不会从此ippool
中分配地址。 -
删除先前的所有 Pod
Note
此步骤需要删除全部存在于
default-ipv4-ippool
下的 Pod,所以会造成 Pod 的连通性暂时中断,请在合适的时机进行此操作。删除 default namespace 下的所有 Pod:
等待 Pod 重建完成,Pod 会使用
temporary-pool
的地址。 -
删除
default-ipv4-ippool
-
重新创建
default-ipv4-ippool
并修改cidr
或者blockSize
运行命令:
apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: default-ipv4-ippool spec: blockSize: 27 # change blockSize from 26 to 27 cidr: 192.0.0.0/16 ipipMode: Always natOutgoing: true EOF
Note
可根据实际情况修改
cidr
和blockSize
。 -
DISABLE
temporary-pool
-
重新创建所有 Pod
删除 default namespace 下的所有 Pod:
等待 Pod 重建完成,Pod 会使用
default-ipv4-ippool
的地址。 -
删除 temporary-pool
迁移 IPPool
¶
原有地址池的 IP 地址不足,需要迁移到新的 IPPOOL
中。
Note
如果在创建和验证新的 IP 池之前删除旧的 IP 池,现有 Pod 的连接将会受到影响。当 Pod 被删除时,业务会可能中断。
迁移 IPPool
步骤:
- 创建新的
ippool
Note
建议新 IPPool
处于 Kubernetes 集群的 CIDR 中。如果从 Kubernetes 集群 CIDR 外部分配 Pod IP,某些流量可能会不必要地应用 NAT,导致意外行为。
-
Disable 旧
ippool
-
重新创建旧 IP 池下的所有 Pod
目的是让所有 Pod 从新的
IPPool
中分配地址 -
验证
新启动 Pod,观察是否从新池中分配 IP 并测试连通性
-
删除旧
ippool
Q&A¶
-
不同的
IPPool
是否支持子网重叠?不支持,在创建
ippool
时,Calico 会校验ippool
的cidr
是否与已存在的ippool
存在子网重叠的情况。 -
IPPool
创建后BlockSize
是否还能修改?不能修改。
ippool
创建之后,已经根据 CIDR 和BlockSize
创建好集群所有的block
,手动修改BlockSize
是没有效果的。