為了縮短雲上節點從啟動狀態到Ready狀態的時間,建議您通過使用自訂鏡像預先安裝所需的軟體包的方式,可以顯著減少軟體包下載的時間,提升系統啟動的效率。本文介紹如何通過自訂鏡像的方式為註冊叢集構建彈性節點池。
前提條件
已建立註冊叢集,並已將本機資料中心自建Kubernetes叢集通過私網方式接入註冊叢集。具體操作,請參見建立註冊叢集。
已配置本機資料中心的自建Kubernetes叢集網路與雲上註冊叢集使用的Virtual Private Cloud互連。具體操作,請參見入門概述。
已開通阿里雲Object Storage Service服務,且Bucket已建立。具體操作,請參見開通OSS服務和建立儲存空間。
已通過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
同步節點池狀態。
登入Container 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上。
步驟五:擴容節點池
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇 。
進入節點池頁面,找到對應節點池,右側單擊
,增加一個新節點。看到兩個節點狀態正常,說明我們的彈性節點池構建完成。
可以為節點池配置Auto Scaling策略。具體操作,請參見配置自動Auto Scaling。