ノードソフトウェアパッケージをあらかじめカスタムイメージにプリインストールすることで、新規 ECS インスタンスが手動設定なしで登録済みクラスターのノードプールに参加可能となり、ノードが Ready 状態に到達するまでの時間を短縮できます。
本ガイドでは、バイナリファイル経由で接続された Kubernetes 1.28.3 を搭載した CentOS 7.9 を使用します。すでにカスタムイメージをお持ちの場合は、「ステップ 3:カスタムイメージをノードプールに適用」へスキップしてください。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
-
セルフマネージドクラスターが接続された登録済みクラスターが存在すること。詳細については、「登録済みクラスターの作成」をご参照ください。
-
セルフマネージドクラスターのネットワークが、登録済みクラスターの VPC と接続されていること。詳細については、「VPC 接続のシナリオ別ネットワーキング」をご参照ください。
-
Object Storage Service (OSS) が有効化され、バケットが作成済みであること。詳細については、「OSS の有効化」および「バケットの作成」をご参照ください。
-
kubectl クライアントが登録済みクラスターに接続済みであること。詳細については、「クラスターの kubeconfig ファイルの取得および kubectl を用いたクラスターへの接続」をご参照ください。
制限事項
-
ステップ 1 で作成されるノードは、初期状態で 失敗 となります。これは正常な挙動です。ノードにはステップ 2 で手動設定を行うまでソフトウェアパッケージがインストールされていません。
-
ステップ 2 の手動設定には、ノードへの SSH アクセスが必要です。
-
デフォルトイメージからカスタムイメージへ切り替える場合、ノードがクラスターに参加できるようになる前に、イメージ内の残存 kubelet 証明書を削除する必要があります。この処理はステップ 4 で実行されます。
概要
本ワークフローは以下の 5 つのステップで構成されます。
-
クラウドノードプールの作成 — 構成対象の生の ECS インスタンスを 1 台追加します。
-
ノードの構成およびカスタムイメージのエクスポート — containerd、kubelet、kube-proxy をインストールし、カスタム ECS イメージを作成します。
-
カスタムイメージをノードプールに適用 — ノードプールを更新してカスタムイメージを使用するように設定します。
-
初期化スクリプトの更新 — Alibaba Cloud ノードパラメーターを動的に注入するようスクリプトを再書き込みします。
-
ノードプールのスケーリング — ノードを追加し、エラスティックノードプールが正しく動作することを検証します。
ステップ 1:クラウドノードプールの作成およびノードの追加
このステップでは、登録済みクラスターに未初期化のノードを 1 台追加します。このノードは、ステップ 2 で構築するカスタムイメージのテンプレートとして使用されます。
-
OSS バケット内に、以下の内容で
join-ecs-node.shというファイルを作成し、アップロードします。このスクリプトは、起動時に注入される Alibaba Cloud ノードパラメーターをログ出力し、イメージ構築前の値の検証を可能にします。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の URL(署名付き URL でも可)を取得し、クラスター内のカスタム構成スクリプトのリファレンスを更新します。-
ack-agent-configConfigMap を編集します。kubectl edit cm ack-agent-config -n kube-system -
addNodeScriptPathをスクリプトの URL に設定します。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
-
-
予期されるノード数 を
1に設定して、cloud-testという名前のクラウドノードプールを作成します。詳細については、「ノードプールの作成およびスケーリング」をご参照ください。重要新しいノードは 失敗 状態で表示されます。これは正常な挙動です。ノードにはまだ必要なソフトウェアパッケージが初期化されていないためです。続行する前に、SSH でノードにログインできることを確認してください。

ステップ 2:ノードの構成およびカスタムイメージのエクスポート
失敗状態のノードにログインし、すべての必須コンポーネントをインストールします。これらのコンポーネントはカスタムイメージに組み込まれるため、今後のノードは事前構成済みの状態で起動します。
2.1 ノードパラメーターの検証
-
ノードに SSH 経由でログインし、初期化ログを確認します。
cat /var/log/acs/init.log期待される出力:
ノードのプロバイダー ID は cn-zhangjiakou.i-xxxxx ノード名は cn-zhangjiakou.192.168.66.xx ノードラベルは alibabacloud.com/nodepool-id=npf9fbxxxxxx,ack.aliyun.com=c22b1a2e122ff4fde85117de4xxxxxx,alibabacloud.com/instance-id=i-8vb7m7nt3dxxxxxxx,alibabacloud.com/external=true ノードの Taint はALIBABA_CLOUD_PROVIDER_ID、ALIBABA_CLOUD_NODE_NAME、ALIBABA_CLOUD_LABELS、およびALIBABA_CLOUD_TAINTSの値を記録します。これらは、ステップ 2.3 の kubelet の起動パラメーターで必要になります。
2.2 基盤環境の構成
以下のコマンドを実行して基盤環境を構成します。この操作では、以下の処理が実行されます。
-
必須システムパッケージのインストール
-
ファイアウォール、SELinux、スワップ領域の無効化(Kubernetes で必須)
-
ネットワーク管理および時刻同期の構成
-
システムファイルディスクリプタ制限の設定
# ツールパッケージをインストールします。
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 をインストールしてください。
2.3 containerd のインストール
このセクションのすべてのコマンドは、コンテナランタイムとして containerd を構成するものであり、カーネルモジュールおよび CNI ネットワーキングを含みます。
-
CNI プラグインと 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 / -
containerd systemd サービスファイルを作成します:
cat > /etc/systemd/system/containerd.service <<EOF [Unit] Description=containerd コンテナランタイム 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 -
containerd を有効化して起動します:
# サービスファイルを追加した後、systemdユニットファイルを再読み込みします systemctl daemon-reload 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
2.4 kubelet および kube-proxy のインストール
このセクションのすべてのコマンドは、マスターノードからコピーしたバイナリファイルを用いて kubelet および kube-proxy をインストールし、両コンポーネントを起動時に自動実行するよう構成するものです。
-
マスターノード から kubelet と kube-proxy のバイナリをコピーします:
scp /usr/local/bin/kube{let,-proxy} $NODEIP:/usr/local/bin/ -
証明書ディレクトリを作成し、マスターノードから証明書をコピーします:
mkdir -p /etc/kubernetes/pkifor 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 サービスを設定します。ステップ 2.1 で記録したノードプールのパラメーターで、環境変数の値を置き換えます。
mkdir -p /var/lib/kubelet /var/log/kubernetes /etc/systemd/system/kubelet.service.d /etc/kubernetes/manifests/ # すべての Kubernetes ノードで kubelet サービスを設定します 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 の有効化と起動:
# サービスファイルを追加した後に、systemdユニットファイルを再読み込みします systemctl daemon-reload systemctl enable --now kubelet.service systemctl start kubelet.service systemctl status kubelet.service -
ノードがクラスターに参加したことを確認します:
kubectl get node -
マスターノードから kube-proxy kubeconfig をコピーします:
scp /etc/kubernetes/kube-proxy.kubeconfig $NODE:/etc/kubernetes/kube-proxy.kubeconfig -
kube-proxy サービスファイルを作成します。
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 を有効化して起動します:
# サービスファイルを追加した後、systemd ユニットファイルを再読み込みします systemctl daemon-reload systemctl enable --now kube-proxy.service systemctl restart kube-proxy.service systemctl status kube-proxy.service
2.5 ノードプールのステータス同期およびイメージのエクスポート
ステップ 3:カスタムイメージをノードプールに適用
すでにカスタムイメージを所有しており、手順 1 および手順 2 をスキップした場合は、まずそのカスタムイメージを使用して新しいノードプールを作成します。詳細については、「ノードプールの作成と管理」をご参照ください。
-
ACK コンソールで、クラスター に移動し、クラスター名をクリックして、ノード > ノードプール に進みます。
-
該当のノードプールを見つけ、編集 をクリックし、操作 列の 詳細オプション を展開して、カスタムイメージ の横にあるドロップダウンメニューからご自身のカスタムイメージを選択します。

-
ノードプール ページの オペレーティングシステム 列に カスタムイメージ が表示されていることを確認します。

ステップ 4:初期化スクリプトの更新
カスタムイメージには既にすべての必須ソフトウェアパッケージが含まれています。初期化スクリプトを更新することで、カスタムイメージから起動した新規ノードは、Alibaba Cloud ノードパラメーターを受信・適用するだけで済み、再インストールは不要になります。
-
カスタムイメージ内の残存 kubelet 証明書を削除します(下記スクリプトの 7 行目)。これを実行しないと、新規ノードは新規証明書を生成できず、クラスターへの参加に失敗します。
-
既存のカスタムノードプールをお使いの場合は、ステップ 1 で示した通り、
ack-agent-config内のaddNodeScriptPathの URL を更新してください。
-
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 サービスを設定 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 サービスを開始 systemctl start kubelet.service -
更新された
join-ecs-node.shを OSS にアップロードし、以前のバージョンを上書きします。
ステップ 5:ノードプールのスケーリング
-
ACK コンソールで、クラスター に移動し、クラスター名をクリックして、ノード > ノードプール に進みます。
-
該当のノードプールを見つけ、その他 > スケーリング をクリックし、操作 列から新規ノードを追加します。

-
両方のノードが Ready 状態であることを確認します:
kubectl get nodes両方のノードが Ready 状態である場合、エラスティックノードプールが正常に作成されたことを確認できます。
次のステップ
-
ノードプールに自動スケーリングポリシーを構成します。詳細については、「自動スケーリングの構成」をご参照ください。

