# `IPPool` `IPPool` 表示 Calico 期望从中给 Pod 分配 IP 的地址集合。通过 Kubespray 拉起 Calico 之后,会分别为 IPv4、IPv6 创建一个默认的地址池: `default-ipv4-ippool` 和 `default-ipv6-ippool`。 运行命令: ```shell calicoctl get ippools default-ipv4-ippool -o yaml ``` 输出为: ```yaml 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` 池 运行命令: ```shell cat << EOF | calicoctl apply -f - ``` 输出为: ```yaml 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 ```shell kubectl label nodes node1 type=test ``` - 在 `IPPool` 中配置 `nodeSelector` 运行命令: ```shell cat << EOF | calicoctl apply -f - ``` ```yaml apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: extra-ippool spec: cidr: 192.168.0.0/20 blockSize: 26 vxlanMode: Always natOutgoing: true nodeSelector: type=="test" EOF ``` 但此 `IPPool` 不会影响到该节点已经创建的 Pod,如果要更新其 Pod 从该 `IPPool` 分配地址,则需要 `recreate pod`。 进一步了解[高级的 selector 语法](https://projectcalico.docs.tigera.io/reference/resources/ippool)。 ### 租户过滤 可通过在 namespace 中打上特定的 annotation,使该 namespace 下的 Pod 会从此 label 对应的 `ippool` 分配 IP。 如果要为 namespace 添加 annotation,则编辑 namespace,在 annotation 中添加如下的 key-value 对: ```shell kubectl annotate namespace test-ns "cni.projectcalico.org/ipv4pools"='["extra-ippool"]' ``` 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` 中分配地址: ```shell kubectl annotate pod test-pod "cni.projectcalico.org/ipv4pools"='["extra-ippool"]' ``` ## 改变 `BlockSize` > 在安装 Calico 之前,应事先定义好 `blockSize`。因为安装之后,`BlockSize` 的值不能编辑。 因此,建议在安装前更改 IPPool block 的大小,以尽量减少对 Pod 连接的中断。 改变 `BlockSize` 步骤: 1. 创建临时的 `ippool` ```yaml apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: temporary-pool spec: cidr: 10.0.0.0/16 ipipMode: Always natOutgoing: true ``` !!! note 注意不要跟现有的 `ippool` 子网冲突。 2. 将 `default-ipv4-ippool` 设置为 `disable` ```shell calicoctl patch ippool default-ipv4-ippool -p '{"spec": {"disabled": true}}' ``` 其中,`default-ipv4-ippool` 为将要修改的 ippool 的名称。 3. 检查 `ippool` 的状态 运行命令: ```shell $ 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` 中分配地址。 4. 删除先前的所有 Pod !!! note 此步骤需要删除全部存在于 `default-ipv4-ippool` 下的 Pod,所以会造成 Pod 的连通性暂时中断,请在合适的时机进行此操作。 删除 default namespace 下的所有 Pod: ```shell kubectl delete po --all ``` 等待 Pod 重建完成,Pod 会使用 `temporary-pool` 的地址。 5. 删除 `default-ipv4-ippool` ```shell calicoctl delete ippool default-ipv4-ippool ``` 6. 重新创建 `default-ipv4-ippool` 并修改 `cidr` 或者 `blockSize` 运行命令: ```shell calicoctl create -f -<