為了縮短云上節點從啟動狀態到Ready狀態的時間,建議您通過使用自定義鏡像預先安裝所需的軟件包的方式,可以顯著減少軟件包下載的時間,提升系統啟動的效率。本文介紹如何通過自定義鏡像的方式為注冊集群構建彈性節點池。
前提條件
已創建注冊集群,并已將本地數據中心自建Kubernetes集群通過私網方式接入注冊集群。具體操作,請參見創建注冊集群。
已配置本地數據中心的自建Kubernetes集群網絡與云上注冊集群使用的專有網絡VPC互通。具體操作,請參見入門概述。
已通過kubectl連接注冊集群。具體操作,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
操作步驟
本文以CentOS 7.9操作系統為例,通過二進制方式接入版本為1.28.3的Kubernetes集群,構建自定義鏡像以實現彈性節點池的搭建。
若您已創建好自定義鏡像,請直接跳轉至步驟三開始操作。
步驟一:創建云上節點池并擴容節點
選擇一個OSS bucket,使用以下內容創建文件join-ecs-node.sh并上傳。
echo "The node providerid is $ALIBABA_CLOUD_PROVIDER_ID" echo "The node name is $ALIBABA_CLOUD_NODE_NAME" echo "The node labels are $ALIBABA_CLOUD_LABELS" echo "The node taints are $ALIBABA_CLOUD_TAINTS"
獲取join-ecs-node.sh文件鏈接地址(可以使用簽名地址),并在集群中更改自定義腳本配置。
執行以下命令,編輯ack-agent-config。
kubectl edit cm ack-agent-config -n kube-system
修改addNodeScriptPath字段內容,更新后配置如下。
apiVersion: v1 data: addNodeScriptPath: https://kubelet-****.oss-cn-hangzhou-internal.aliyuncs.com/join-ecs-nodes.sh kind: ConfigMap metadata: name: ack-agent-config namespace: kube-system
創建云上節點池cloud-test,并將期望節點數設置為1。具體操作,請參見創建節點池并擴容。
重要由于新創建的節點沒有進行初始化(安裝節點軟件包等),創建完成后會顯示為Failed狀態。另外,后續需要登錄該節點進行節點初始化,請確保此節點可通過SSH登錄。
步驟二:配置節點狀態并導出自定義鏡像
登錄節點,使用以下命令查看節點信息。
cat /var/log/acs/init.log
預期輸出:
The node providerid is cn-zhangjiakou.i-xxxxx The node name is cn-zhangjiakou.192.168.66.xx The node labels are alibabacloud.com/nodepool-id=npf9fbxxxxxx,ack.aliyun.com=c22b1a2e122ff4fde85117de4xxxxxx,alibabacloud.com/instance-id=i-8vb7m7nt3dxxxxxxx,alibabacloud.com/external=true The node taints are
預期說明自定義腳本可以成功獲取阿里云節點信息,請記錄這些信息,稍后將其添加到kubelet的啟動參數中。
執行以下命令,配置基礎環境。
# 安裝工具包。 yum update -y && yum -y install wget psmisc vim net-tools nfs-utils telnet yum-utils device-mapper-persistent-data lvm2 git tar curl # 關閉防火墻。 systemctl disable --now firewalld # 關閉SELinux。 setenforce 0 sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config # 關閉交換分區。 sed -ri 's/.*swap.*/#&/' /etc/fstab swapoff -a && sysctl -w vm.swappiness=0 # 網絡配置。 systemctl disable --now NetworkManager systemctl start network && systemctl enable network # 時間同步。 ln -svf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime yum install ntpdate -y ntpdate ntp.aliyun.com # 配置ulimit。 ulimit -SHn 65535 cat >> /etc/security/limits.conf <<EOF * soft nofile 655360 * hard nofile 131072 * soft nproc 655350 * hard nproc 655350 * seft memlock unlimited * hard memlock unlimitedd EOF
說明完成上述環境配置后,請自行升級內核至4.18以上版本,并安裝ipvsadm。
安裝Containerd。
執行以下命令,下載網絡插件和Containerd軟件包。
wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz mkdir -p /etc/cni/net.d /opt/cni/bin #解壓cni二進制包 tar xf cni-plugins-linux-amd64-v*.tgz -C /opt/cni/bin/ wget https://github.com/containerd/containerd/releases/download/v1.7.8/containerd-1.7.8-linux-amd64.tar.gz tar -xzf cri-containerd-cni-*-linux-amd64.tar.gz -C /
執行以下命令,創建服務啟動配置。
cat > /etc/systemd/system/containerd.service <<EOF [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/local/bin/containerd Type=notify Delegate=yes KillMode=process Restart=always RestartSec=5 LimitNPROC=infinity LimitCORE=infinity LimitNOFILE=infinity TasksMax=infinity OOMScoreAdjust=-999 [Install] WantedBy=multi-user.target EOF
執行以下命令,配置Containerd所需模塊。
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF systemctl restart systemd-modules-load.service
執行以下命令,配置Containerd所需內核。
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF # 加載內核 sysctl --system
執行以下命令,創建Containerd配置文件。
mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml # 修改Containerd的配置文件 sed -i "s#SystemdCgroup\ \=\ false#SystemdCgroup\ \=\ true#g" /etc/containerd/config.toml cat /etc/containerd/config.toml | grep SystemdCgroup sed -i "s#registry.k8s.io#m.daocloud.io/registry.k8s.io#g" /etc/containerd/config.toml cat /etc/containerd/config.toml | grep sandbox_image sed -i "s#config_path\ \=\ \"\"#config_path\ \=\ \"/etc/containerd/certs.d\"#g" /etc/containerd/config.toml cat /etc/containerd/config.toml | grep certs.d # 配置加速器 mkdir /etc/containerd/certs.d/docker.io -pv cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF server = "https://docker.io" [host."https://hub-mirror.c.163.com"] capabilities = ["pull", "resolve"] EOF
執行以下命令,設置Contaienrd為開機自啟動。
systemctl daemon-reload # 用于重新加載systemd管理的單位文件。當你新增或修改了某個單位文件(如.service文件、.socket文件等),需要運行該命令來刷新systemd對該文件的配置。 systemctl enable --now containerd.service systemctl start containerd.service systemctl status containerd.service
執行以下命令,配置crictl命令。
wget https://mirrors.chenby.cn/https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.28.0/crictl-v1.28.0-linux-amd64.tar.gz tar xf crictl-v*-linux-amd64.tar.gz -C /usr/bin/ #生成配置文件 cat > /etc/crictl.yaml <<EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF #測試 systemctl restart containerd crictl info
安裝kubelet、kube-proxy。
獲取二進制文件。登錄Master節點,將二進制文件拷貝到該節點。
scp /usr/local/bin/kube{let,-proxy} $NODEIP:/usr/local/bin/
獲取證書,執行以下命令,在本機創建證書存儲目錄。
mkdir -p /etc/kubernetes/pki
登錄master節點,拷貝證書到該節點。
for FILE in pki/ca.pem pki/ca-key.pem pki/front-proxy-ca.pem bootstrap-kubelet.kubeconfig kube-proxy.kubeconfig; do scp /etc/kubernetes/$FILE $NODE:/etc/kubernetes/${FILE}; done
執行以下命令,配置kubelet Service。請將步驟二中獲取到的阿里云節點池相關變量填入。
mkdir -p /var/lib/kubelet /var/log/kubernetes /etc/systemd/system/kubelet.service.d /etc/kubernetes/manifests/ # 所有k8s節點配置kubelet service cat > /usr/lib/systemd/system/kubelet.service << EOF [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes After=network-online.target firewalld.service containerd.service Wants=network-online.target Requires=containerd.service [Service] ExecStart=/usr/local/bin/kubelet \\ --node-ip=${ALIBABA_CLOUD_NODE_NAME} \\ --hostname-override=${ALIBABA_CLOUD_NODE_NAME} \\ --node-labels=${ALIBABA_CLOUD_LABELS} \\ --provider-id=${ALIBABA_CLOUD_PROVIDER_ID} \\ --register-with-taints=${ALIBABA_CLOUD_TAINTS} \\ --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig \\ --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\ --config=/etc/kubernetes/kubelet-conf.yml \\ --container-runtime-endpoint=unix:///run/containerd/containerd.sock [Install] WantedBy=multi-user.target EOF
執行以下命令,創建kubelet啟動配置文件。
cat > /etc/kubernetes/kubelet-conf.yml <<EOF apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration address: 0.0.0.0 port: 10250 readOnlyPort: 10255 authentication: anonymous: enabled: false webhook: cacheTTL: 2m0s enabled: true x509: clientCAFile: /etc/kubernetes/pki/ca.pem authorization: mode: Webhook webhook: cacheAuthorizedTTL: 5m0s cacheUnauthorizedTTL: 30s cgroupDriver: systemd cgroupsPerQOS: true clusterDNS: - 10.96.0.10 clusterDomain: cluster.local containerLogMaxFiles: 5 containerLogMaxSize: 10Mi contentType: application/vnd.kubernetes.protobuf cpuCFSQuota: true cpuManagerPolicy: none cpuManagerReconcilePeriod: 10s enableControllerAttachDetach: true enableDebuggingHandlers: true enforceNodeAllocatable: - pods eventBurst: 10 eventRecordQPS: 5 evictionHard: imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% evictionPressureTransitionPeriod: 5m0s failSwapOn: true fileCheckFrequency: 20s hairpinMode: promiscuous-bridge healthzBindAddress: 127.0.0.1 healthzPort: 10248 httpCheckFrequency: 20s imageGCHighThresholdPercent: 85 imageGCLowThresholdPercent: 80 imageMinimumGCAge: 2m0s iptablesDropBit: 15 iptablesMasqueradeBit: 14 kubeAPIBurst: 10 kubeAPIQPS: 5 makeIPTablesUtilChains: true maxOpenFiles: 1000000 maxPods: 110 nodeStatusUpdateFrequency: 10s oomScoreAdj: -999 podPidsLimit: -1 registryBurst: 10 registryPullQPS: 5 resolvConf: /etc/resolv.conf rotateCertificates: true runtimeRequestTimeout: 2m0s serializeImagePulls: true staticPodPath: /etc/kubernetes/manifests streamingConnectionIdleTimeout: 4h0m0s syncFrequency: 1m0s volumeStatsAggPeriod: 1m0s EOF
執行以下命令,啟動kubelet。
systemctl daemon-reload # 用于重新加載systemd管理的單位文件。當你新增或修改了某個單位文件(如.service文件、.socket文件等),需要運行該命令來刷新systemd對該文件的配置。 systemctl enable --now kubelet.service systemctl start kubelet.service systemctl status kubelet.service
執行以下命令,查看集群信息。
kubectl get node
登錄master節點,獲取kube-proxy所需KubeConfig。
scp /etc/kubernetes/kube-proxy.kubeconfig $NODE:/etc/kubernetes/kube-proxy.kubeconfig
執行以下命令,添加kube-proxy Service配置。
cat > /usr/lib/systemd/system/kube-proxy.service << EOF [Unit] Description=Kubernetes Kube Proxy Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] ExecStart=/usr/local/bin/kube-proxy \\ --config=/etc/kubernetes/kube-proxy.yaml \\ --v=2 Restart=always RestartSec=10s [Install] WantedBy=multi-user.target EOF
執行以下命令,添加kube-proxy啟動配置。
cat > /etc/kubernetes/kube-proxy.yaml << EOF apiVersion: kubeproxy.config.k8s.io/v1alpha1 bindAddress: 0.0.0.0 clientConnection: acceptContentTypes: "" burst: 10 contentType: application/vnd.kubernetes.protobuf kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig qps: 5 clusterCIDR: 172.16.0.0/12,fc00:2222::/112 configSyncPeriod: 15m0s conntrack: max: null maxPerCore: 32768 min: 131072 tcpCloseWaitTimeout: 1h0m0s tcpEstablishedTimeout: 24h0m0s enableProfiling: false healthzBindAddress: 0.0.0.0:10256 hostnameOverride: "" iptables: masqueradeAll: false masqueradeBit: 14 minSyncPeriod: 0s syncPeriod: 30s ipvs: masqueradeAll: true minSyncPeriod: 5s scheduler: "rr" syncPeriod: 30s kind: KubeProxyConfiguration metricsBindAddress: 127.0.0.1:10249 mode: "ipvs" nodePortAddresses: null oomScoreAdj: -999 portRange: "" udpIdleTimeout: 250ms EOF
執行以下命令,啟動kube-proxy。
systemctl daemon-reload # 用于重新加載systemd管理的單位文件。當你新增或修改了某個單位文件(如.service文件、.socket文件等),需要運行該命令來刷新systemd對該文件的配置。 systemctl enable --now kube-proxy.service systemctl restart kube-proxy.service systemctl status kube-proxy.service
同步節點池狀態。
登錄容器服務管理控制臺,在左側導航欄選擇集群。
在集群列表頁面,單擊目標集群名稱,然后在左側導航欄,選擇 。
進入節點池頁面,單擊右側同步節點池,等待同步完成后,可以看到已無失敗信息,節點池顯示正常。
導出自定義鏡像。
登錄ECS管理控制臺。
在左側導航欄,選擇 。
單擊該實例ID,進入實例詳情頁簽,單擊創建自定義鏡像。
在左側導航欄,選擇 。
進入鏡像頁面,可看到創建的自定義鏡像,狀態為可用。
步驟三:使用自定義鏡像修改或創建云上節點池
如果您已經有自定義鏡像,且未執行步驟一、步驟二操作,需要使用自定義鏡像創建節點池。具體操作,請參見如何基于創建好的ECS實例創建自定義鏡像,并使用該鏡像創建節點?。
在集群列表頁面,單擊目標集群名稱,然后在左側導航欄,選擇 。
進入節點池頁面,找到對應節點池,右側單擊編輯,選擇高級選項頁簽,修改節點池鏡像為自定義鏡像。
可在節點池頁面看到操作系統已更新為自定義鏡像。
步驟四:修改節點初始化腳本并接收阿里云相關參數
需要清理自定義鏡像里面殘留的kubelet證書,見腳本第七行。
若為已有自定義節點池情況,需參考步驟一中配置好自定義腳本下載鏈接。
使用以下內容,構建或更新join-ecs-node.sh。由于自定義鏡像已經包含節點所需工具包、依賴包,所以自定義腳本只需接收并更新阿里云節點池參數即可。
echo "The node providerid is $ALIBABA_CLOUD_PROVIDER_ID" echo "The node name is $ALIBABA_CLOUD_NODE_NAME" echo "The node labels are $ALIBABA_CLOUD_LABELS" echo "The node taints are $ALIBABA_CLOUD_TAINTS" systemctl stop kubelet.service echo "Delete old kubelet pki" #需刪除老的節點證書 rm -rf /var/lib/kubelet/pki/* echo "Add kubelet service config" # 配置kubelet service cat > /usr/lib/systemd/system/kubelet.service << EOF [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes After=network-online.target firewalld.service containerd.service Wants=network-online.target Requires=containerd.service [Service] ExecStart=/usr/local/bin/kubelet \\ --node-ip=${ALIBABA_CLOUD_NODE_NAME} \\ --hostname-override=${ALIBABA_CLOUD_NODE_NAME} \\ --node-labels=${ALIBABA_CLOUD_LABELS} \\ --provider-id=${ALIBABA_CLOUD_PROVIDER_ID} \\ --register-with-taints=${ALIBABA_CLOUD_TAINTS} \\ --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.kubeconfig \\ --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\ --config=/etc/kubernetes/kubelet-conf.yml \\ --container-runtime-endpoint=unix:///run/containerd/containerd.sock [Install] WantedBy=multi-user.target EOF systemctl daemon-reload # 啟動Kubelet Service systemctl start kubelet.service
將腳本join-ecs-node.sh更新到OSS上。
步驟五:擴容節點池
在集群列表頁面,單擊目標集群名稱,然后在左側導航欄,選擇 。
進入節點池頁面,找到對應節點池,右側單擊
,增加一個新節點。看到兩個節點狀態正常,說明我們的彈性節點池構建完成。
可以為節點池配置彈性伸縮策略。具體操作,請參見配置自動彈性伸縮。