容器网段空间耗尽如何继续扩容(VPC网络模式)
注意:以下内容仅针对使用 “VPC Route”模式的集群
概述
一个集群中最大的节点数量由容器网段的大小和每个节点上最大 Pod 数量所决定,例如:
- 容器网段选择 172.16.0.0/16,每个节点最大 Pod 数量为 256,则一个集群中最多只能有 256 个节点;
- 容器网段选择 192.168.0.0/22,每个节点最大 Pod 数量为 128,则一个集群中最多只能有 8 个节点;
在某些情况下,由于用户创建的集群时,选择的容器网段过小或者每个节点上最大的容器数量过大,在后续对集群进行扩容时,节点数量超过了集群中最大的节点数量。由于 kube-controller-manager 无法为这些扩容的节点分配Pod 的网段,会导致节点状态 notReady。
注意:在 2021-3-11 之前,controller manager 采用二进制方式部署,按照老版本解决办法。2021-3-11 之后的新建的集群,controller manager 采用静态 Pod 方式部署,按照新版本解决办法。
master 二进制部署集群解决方法
在 2021-3-11 之前,controller manager 采用二进制方式部署。
此时只有容器网络 V1 架构,不排除个人手动升级到 V2 架构的情况。请自行确认当前使用的容器网络版本。对应的方法为检查集群中是否有 cce-cni-node-agent 对象,如果有该对象,则使用的容器网络版本是 v1。
$ kubectl -n kube-system get cm cce-cni-node-agent
NAME DATA AGE
cce-cni-node-agent 1 125d
第一步
修改集群中 master 节点上 cce-network-operator 的配置,需要修改的字段是 cluster-pool-ipv4-mask-size。由于修改目的是让集群中可以容纳更多节点,也就是让节点上最大的 Pod 数量变小,我们需要修改 cluster-pool-ipv4-mask-size 值使其变大。
如果是多副本的 master,需要逐一修改各 master 节点上的配置。
注意: 不能修改 cluster-pool-ipv4-mask-size 比当前值更小,否则会造成网段冲突导致网络不通
第二步
从集群中移出节点再加入,包括的方法有两种:
- 从 CCE 产品 console 界面上选择“移出节点”或“删除节点”, 之后再“移入节点”或“添加节点”。
- 执行
kubectl delete node <nodeName>
从 k8s 集群中删除节点。执行kubectl get pods --all-namespaces=true -o wide | grep <nodeName>
确保该节点上没有 Pod 之后,在节点上重启 kubelet 将节点重新加入到 k8s 集群。
注意:不论哪种方式将节点从集群中删除,都会导致移出的节点上的所有 Pod 漂移。对于承载了线上服务的节点,需要谨慎操作。
实际案例
问题场景
目前有一个集群的容器网段是 172.26.0.0/22,kube-controller-manager 配置中 --node-cidr-mask-size=24。也就是说,集群中最多容纳 4 个节点,每个节点上最大 Pod 数量是 256。
集群中已经有 4 个节点了,如果再扩容节点将会导致新扩容的节点不可用。
[root@instance-rhkiutp6-3 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
10.0.5.3 Ready <none> 119m v1.13.10
10.0.5.4 Ready <none> 117m v1.13.10
10.0.5.5 Ready <none> 20m v1.13.10
10.0.5.6 Ready <none> 118m v1.13.10
[root@instance-rhkiutp6-3 ~]# kubectl describe node | grep -i podcidr
PodCIDR: 172.26.2.0/24
PodCIDR: 172.26.1.0/24
PodCIDR: 172.26.3.0/24
PodCIDR: 172.26.0.0/24
修改步骤
第一步
在 master 上执行 vim /etc/systemd/system/kube-controller.service
查看 kube-controller-manager 配置:
[Unit]
Description=Kubernetes Controller Manager
After=network.target
After=kube-apiserver.service
[Service]
ExecStart=/opt/kube/bin/kube-controller-manager \
--allocate-node-cidrs=true \
--cloud-config=/etc/kubernetes/cloud.config \
--cluster-cidr=172.26.0.0/22 \
--node-cidr-mask-size=24 \ #修改这里
.......
--kubeconfig=/etc/kubernetes/controller-manager.conf \
--leader-elect=true \
--logtostderr=true \
--master=https://100.64.230.195:6443 \
--v=6
Restart=always
Type=simple
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
修改 --node-cidr-mask-size 值从 24 变更为 26。这样修改后,集群中最多可以容纳 16 个节点,每个节点上最大 Pod 数量则减少为 64。
依次在每个 master 节点修改配置后执行以下命令重启 kube-controller-manager。
systemctl daemon-reload
systemctl restart kube-controller.service
第二步
执行 kubectl delete node 10.0.5.4
,此时集群状态中已经没有 10.0.5.4 节点:
[root@instance-rhkiutp6-3 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
10.0.5.3 Ready <none> 132m v1.13.10
10.0.5.5 Ready <none> 33m v1.13.10
10.0.5.6 Ready <none> 132m v1.13.10
[root@instance-rhkiutp6-3 ~]# kubectl describe node | grep -i podcidr
PodCIDR: 172.26.2.0/24
PodCIDR: 172.26.3.0/24
PodCIDR: 172.26.0.0/24
执行 kubectl get pods --all-namespaces=true -o wide | grep <nodeName>
确保 10.0.5.4 上没有 Pod。
在 10.0.5.4 节点上执行 systemctl restart kubelet.service
重启 kubelet,此时集群状态中表明 10.0.5.4 节点又被加入并且容器网段变为了 172.26.1.0/26:
[root@instance-rhkiutp6-3 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
10.0.5.3 Ready <none> 138m v1.13.10
10.0.5.4 Ready <none> 3m55s v1.13.10
10.0.5.5 Ready <none> 40m v1.13.10
10.0.5.6 Ready <none> 138m v1.13.10
[root@instance-rhkiutp6-3 ~]# kubectl describe node | grep -i podcidr
PodCIDR: 172.26.2.0/24
PodCIDR: 172.26.1.0/26
PodCIDR: 172.26.3.0/24
PodCIDR: 172.26.0.0/24
每移入移出一个已有节点将会创造出 3 个节点的扩容空间。例如现在可以给集群继续扩容 3 台节点,分配的 PodCIDR 将会是 172.26.1.64/26
、 172.26.1.128/26
以及 172.26.1.192/26
。
用户继续执行以上步骤移入移出所有节点,以创造更多的扩容空间。
注意:PodCIDR 掩码不同的节点理论上可以存在于同一集群中,但还是建议用户将所有节点移入移出一遍,让节点拥有相同掩码的 PodCIDR。
master 采用静态Pod部署方式解决办法
在 2021-3-11 之后,controller manager 采用静态 Pod 方式部署,修改对应的配置文件即可完成 Pod 更新。
容器网络分为 V1 和 V2 架构。请自行确认当前使用的容器网络版本。对应的方法为检查集群中是否有 cce-cni-node-agent 对象,如果有该对象,则使用的容器网络版本是 v1。
$ kubectl -n kube-system get cm cce-cni-node-agent
NAME DATA AGE
cce-cni-node-agent 1 125d
第一步 修改配置
修改集群中 master 节点上 kube-controller-manager
的配置,需要修改的字段是 --node-cidr-mask-size。
由于修改目的是让集群中可以容纳更多节点,也就是让节点上最大的 Pod 数量变小,我们需要修改 --node-cidr-mask-size 值使其变大。
如果是多副本的 master,需要逐一修改各 master 节点上的配置。
| 注意: 不能修改 node-cidr-mask-size 比当前值更小,否则会造成网段冲突导致网络不通
第二步 修改网络组件
容器网络分 V1 和 V2 架构分别对应不同的修改方法。请自行确认当前使用的容器网络版本。对应的方法为检查集群中是否有 cce-cni-node-agent 对象,如果有该对象,则使用的容器网络版本是 v1。
$ kubectl -n kube-system get cm cce-cni-node-agent
NAME DATA AGE
cce-cni-node-agent 1 125d
对于容器网络 V1 架构,v1 直接用node spec里的podcidr,并不需要进行修改。
对于容器网络 V2 架构,需要修改 cce-network-v2-config,对应的字段是 cluster-pool-ipv4-mask-size。之后重启对应的组件 cce-network-operator
和 cce-network-agent
,以确保对应的配置生效。
第三步 重新移出移入节点
从集群中移出节点再加入,包括的方法有两种:
- 从 CCE 产品 console 界面上选择“移出节点”或“删除节点”, 之后再“移入节点”或“添加节点”。
- 执行
kubectl delete node <nodeName>
从 k8s 集群中删除节点。执行kubectl get pods --all-namespaces=true -o wide | grep <nodeName>
确保该节点上没有 Pod 之后,在节点上重启kubelet
将节点重新加入到 k8s 集群。 注意:不论哪种方式将节点从集群中删除,都会导致移出的节点上的所有 Pod 漂移。对于承载了线上服务的节点,需要谨慎操作。
实际案例
问题场景
目前有一个集群的容器网段是 172.16.0.0/24 ,kube-controller-manager
配置中 node-cidr-mask-size=24
。也就是说,集群中最多容纳 256 个节点,每个节点上最大 Pod 数量是 256。现在需要将可容纳节点个数提升到 1024 个。
[root@root ~]# kubectl get no
NAME STATUS ROLES AGE VERSION
192.168.1.4 Ready <none> 42m v1.24.4
192.168.1.5 Ready <none> 35m v1.24.4
root@root:~# kubectl describe node | grep -i podcidr
root@root:~# kubectl describe node | grep -i podcidr
PodCIDR: 10.0.1.0/24
PodCIDRs: 10.0.1.0/24
PodCIDR: 10.0.0.0/24
PodCIDRs: 10.0.0.0/24
修改步骤
第一步 修改配置
查看 cnode-cidr-mask-size 配置:
[root@root manifests]# kubectl get po kube-controller-manager-192.168.1.4 -n kube-system -o yaml | grep node-cidr-mask-size
- --node-cidr-mask-size=24
修改 cluster-pool-ipv4-mask-size 值从 24 变更为 26。这样修改后,集群中最多可以容纳 1024 个节点,每个节点上最大 Pod 数量则减少为 64。
修改 kube-controller-manager
参数 node-cidr-mask-size=26
:
vim /etc/kubernetes/manifests/kube-controller-manager.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
creationTimestamp: null
labels:
component: kube-controller-manager
tier: control-plane
name: kube-controller-manager
namespace: kube-system
spec:
containers:
- command:
- kube-controller-manager
- --cluster-cidr=172.16.0.0/16
- --feature-gates=MixedProtocolLBService=true
- --master=https://192.168.1.4:6443
- --node-cidr-mask-size=26
……
这里 kube-controller-manager
是通过静态方式部署的。对于静态Pod,kubelet 会监视定义文件的变化。当保存并关闭编辑器后,kubelet 将检测到文件已更改,并自动根据更新后的定义文件删除旧的 Pod 并启动新的 Pod 。
第二步 修改网络组件
这里使用的 V2 网络架构,需要修改 cce-network-v2-config
的 cluster-pool-ipv4-mask-size
字段。
kubectl edit cm cce-network-v2-config -n kube-system
apiVersion: v1
data:
cced: |
annotate-k8s-node: true
api-rate-limit:
bcecloud/apis/v1/AttachENI: rate-limit:5/1s,rate-burst:5,max-wait-duration:30s,parallel-requests:5,log:true
bcecloud/apis/v1/BatchAddPrivateIP: rate-limit:5/1s,rate-burst:10,max-wait-duration:15s,parallel-requests:5,log:true
bcecloud/apis/v1/BatchDeletePrivateIP: rate-limit:5/1s,rate-burst:10,max-wait-duration:15s,parallel-requests:5,log:true
bcecloud/apis/v1/CreateENI: rate-limit:5/1s,rate-burst:5,max-wait-duration:30s,parallel-requests:5,log:true
bcecloud/apis/v1/DescribeSubnet: rate-limit:5/1s,rate-burst:5,max-wait-duration:30s,parallel-requests:5
bcecloud/apis/v1/StatENI: rate-limit:10/1s,rate-burst:15,max-wait-duration:30s,parallel-requests:10
auto-create-network-resource-set-resource: true
bbcEndpoint: bbc.gz.baidubce.com
bccEndpoint: bcc.gz.baidubce.com
bce-cloud-access-key: ""
bce-cloud-country: cn
bce-cloud-host: cce-gateway.gz.baidubce.com
bce-cloud-region: gz
bce-cloud-secure-key: ""
bce-cloud-vpc-id: vpc-2f5wibbx4js7
cce-cluster-id: cce-clboj6fa
cce-endpoint-gc-interval: 30s
cluster-pool-ipv4-cidr:
- 172.16.0.0/16
cluster-pool-ipv4-mask-size: 26
重启对应的组件cce-network-operator
和 cce-network-agent
以确保对应的配置生效。
kubectl rollout restart deployment cce-network-operator -n kube-system
kubectl rollout restart daemonset cce-network-agent -n kube-system
第三步 重新移出移入节点
执行 kubectl delete
指令,删除对应的节点。
kubectl delete node 192.168.1.4
查看集群状态,确保此时集群状态中已经没有 192.168.1.4 节点:
[root@root ~]# kubectl get no
NAME STATUS ROLES AGE VERSION
192.168.1.5 Ready <none> 47m v1.24.4
root@root:~# kubectl describe node | grep -i podcidr
PodCIDR: 10.0.1.0/24
PodCIDRs: 10.0.1.0/24
确保 192.168.1.4 上没有 Pod。如果有 Pod 残留会导致重新加入 Node 后 Pod CIDR 不变。执行以下命令进行查看。
kubectl get pods --all-namespaces=true -o wide | grep <nodeName>
在 192.168.1.2节点上执行 systemctl restart kubelet.service
重启 kubelet,此时集群状态中表明 192.168.1.2 节点又被加入并且容器网段变为了 172.26.1.0/26:
[root@root ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
192.168.1.4 Ready <none> 11m v1.24.4
192.168.1.5 Ready <none> 102m v1.24.4
[root@root-3 ~]# kubectl describe node | grep -i podcidr
PodCIDR: 10.0.0.0/26
PodCIDRs: 10.0.0.0/26
PodCIDR: 10.0.1.0/24
PodCIDRs: 10.0.1.0/24
用户继续执行以上步骤移入移出所有节点,可以创造更多的扩容空间。
注意:PodCIDR 掩码不同的节点理论上可以存在于同一集群中,但还是建议用户将所有节点移入移出一遍,让节点拥有相同掩码的 PodCIDR。