オンプレミスの計算リソースが容量に達した場合、ACK One でノードプールを作成し、クラウドベースの Elastic Compute Service (ECS) ノードでスケールアウトできます。このトピックでは、これらの ECS ノードを登録済みクラスターにプロビジョニングするためのカスタムブートストラップスクリプトの作成およびデプロイ方法について説明します。
前提条件
開始する前に、以下の要件を満たしていることを確認してください。
外部 Kubernetes クラスターが接続された ACK One 登録済みクラスターがあること。詳細については、「ACK One 登録済みクラスターの作成」をご参照ください。
外部 Kubernetes クラスターのネットワークが、ACK One 登録済みクラスターの VPC に接続されていること。詳細については、「VPC 接続のシナリオ別ネットワーキング」をご参照ください。
外部 Kubernetes クラスターのプロキシ構成が、ACK One 登録済みクラスター(プライベートネットワークモード)にインポートされていること。詳細については、「外部 Kubernetes クラスターと ACK One 登録済みクラスターの関連付け」をご参照ください。
制限事項
このトピックのサンプルスクリプトは、パッケージマネージャとして YUM (Yellowdog Updater Modified) を使用するオペレーティングシステムのみをサポートしています。
サンプルスクリプトは通常の ECS ノードにのみ適用されます。GPU アクセラレーションノードの場合は、チケットを送信して、R&D チームからカスタマイズされたスクリプトを取得してください。
通常の ECS ノードとは異なり、GPU アクセラレーションノードにはドライバーおよびデバイスプラグインをインストールする必要があります。詳細については、「ノードの NVIDIA ドライバーを手動で更新する」をご参照ください。
概要
このプロセスは次の 3 つのステップで構成されています。
ノードスクリプトの準備 — 既存のカスタムスクリプトを調整するか、サンプルスクリプトから開始します。
スクリプトのアップロード — 登録済みクラスターからアクセス可能なファイルサーバにスクリプトをアップロードします。
スクリプトパスの登録 —
ack-agent-configConfigMap にスクリプトパスを登録し、ノードプールがスケールアウト時にスクリプトを取得できるようにします。
ステップ 1 での選択肢:
| 状況 | 操作 |
|---|---|
| 既存のブートストラップスクリプトがある | ステップ 1(A) を使用:必要な Alibaba Cloud 環境変数を追加します |
| ゼロから開始する | ステップ 1(B) を使用:サンプルスクリプトをダウンロードしてカスタマイズします |
ステップ 1(A):既存のスクリプトに Alibaba Cloud 環境変数を追加する
ノードプールは、ノードを正しく管理するために、登録済みクラスターから 4 つの環境変数を必要とします。これらの環境変数は、スケールアウト時に登録済みクラスターによって注入されます。
ALIBABA_CLOUD_PROVIDER_ID は登録済みクラスターの動作に必須です。スクリプトでこの変数を使用しない場合、クラスターは正常に動作しません。
4 つの環境変数は次のとおりです。
| 変数 | 必須 | 欠落時の影響 | 例 |
|---|---|---|---|
ALIBABA_CLOUD_PROVIDER_ID | はい | 登録済みクラスターが正常に動作しない | cn-shenzhen.i-wz92ewt14n9wx9mo*** |
ALIBABA_CLOUD_NODE_NAME | はい | ノードプール内のノードが異常な状態になる可能性がある | cn-shenzhen.192.168.1.*** |
ALIBABA_CLOUD_LABELS | はい | クラウドとオンプレミスノード間でのノードプール管理およびワークロードスケジューリングが失敗する可能性がある | alibabacloud.com/nodepool-id=np0e2031e952c4492bab32f512ce142*,ack.aliyun.com=cc3df6d939b0d4463b493b82d0d670*,alibabacloud.com/instance-id=i-wz960ockeekr3dok0***,alibabacloud.com/external=true,workload=cpu |
ALIBABA_CLOUD_TAINTS | はい | ノードプール構成で定義された Taint が有効にならない | workload=ack:NoSchedule |
ALIBABA_CLOUD_LABELSの中で、workload=cpuラベルは、ノードプール構成で定義するカスタムラベルです。その他のラベルはすべて自動的に追加されるシステムラベルです。
クラスターのインストール方法に基づいて、スクリプトに変数注入ブロックを追加します。
kubeadm を使用してクラスターを作成した場合
次のブロックをスクリプトに挿入します。メインのノード構成の後、kubelet の再起動前に行います。
####### Begin: Alibaba Cloud environment variable injection
# Configure node labels, taints, node name, and provider ID.
KUBELET_CONFIG_FILE="/etc/sysconfig/kubelet"
if [[ $ALIBABA_CLOUD_LABELS != "" ]];then
option="--node-labels"
if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_LABELS},@g" $KUBELET_CONFIG_FILE
elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_LABELS} @g" $KUBELET_CONFIG_FILE
else
sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_LABELS}\"" $KUBELET_CONFIG_FILE
fi
fi
if [[ $ALIBABA_CLOUD_TAINTS != "" ]];then
option="--register-with-taints"
if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_TAINTS},@g" $KUBELET_CONFIG_FILE
elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_TAINTS} @g" $KUBELET_CONFIG_FILE
else
sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_TAINTS}\"" $KUBELET_CONFIG_FILE
fi
fi
if [[ $ALIBABA_CLOUD_NODE_NAME != "" ]];then
option="--hostname-override"
if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_NODE_NAME},@g" $KUBELET_CONFIG_FILE
elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_NODE_NAME} @g" $KUBELET_CONFIG_FILE
else
sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_NODE_NAME}\"" $KUBELET_CONFIG_FILE
fi
fi
if [[ $ALIBABA_CLOUD_PROVIDER_ID != "" ]];then
option="--provider-id"
if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_PROVIDER_ID},@g" $KUBELET_CONFIG_FILE
elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_PROVIDER_ID} @g" $KUBELET_CONFIG_FILE
else
sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_PROVIDER_ID}\"" $KUBELET_CONFIG_FILE
fi
fi
####### End: Alibaba Cloud environment variable injectionこのブロックを追加したら、ステップ 2:スクリプトのアップロードに進んでください。
バイナリファイルを使用してクラスターをインストールした場合
クラスターを Kubernetes バイナリファイルを直接インストールしてセットアップした場合は、スクリプト内で kubelet の起動構成を変更します。kubelet.service ファイルは通常、/usr/lib/systemd/system/ にあります。
cat >/usr/lib/systemd/system/kubelet.service <<EOF
# Custom configurations are not shown.
...
[Service]
ExecStart=/data0/kubernetes/bin/kubelet \
# Add the following flags:
--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} \
....
--v=4
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOFこれらのフラグを追加したら、ステップ 2:スクリプトのアップロードに進んでください。
ステップ 1(B):サンプルスクリプトの使用
既存のブートストラップスクリプトがない場合は、以下のサンプルスクリプトのいずれかを出発点として使用します。サンプルは、最も一般的な 2 つのコンテナランタイム(Docker および containerd)に対応しています。
必要な値の収集
スクリプトに入力する前に、外部クラスターから 3 つの値を収集します。
ステップ 1:Kubernetes バージョンの取得
クラスターの Kubernetes バージョンに基づいて、適切なコマンドを実行します。
Kubernetes 1.18 以降の場合(control-plane ラベルを使用):
kubectl get no $(kubectl get nodes -l node-role.kubernetes.io/control-plane -o json | jq -r '.items[0].metadata.name') -o json | jq -r '.status.nodeInfo.kubeletVersion'Kubernetes 1.18 より前の場合(master ラベルを使用):
kubectl get no $(kubectl get nodes -l node-role.kubernetes.io/master -o json | jq -r '.items[0].metadata.name') -o json | jq -r '.status.nodeInfo.kubeletVersion'期待される出力:
v1.14.10これを KUBE_VERSION 値として記録します。
ステップ 2:コンテナランタイムおよびバージョンの取得
Kubernetes 1.18 以降の場合:
kubectl get no $(kubectl get nodes -l node-role.kubernetes.io/control-plane -o json | jq -r '.items[0].metadata.name') -o json | jq -r '.status.nodeInfo.containerRuntimeVersion'Kubernetes 1.18 より前の場合:
kubectl get no $(kubectl get nodes -l node-role.kubernetes.io/master -o json | jq -r '.items[0].metadata.name') -o json | jq -r '.status.nodeInfo.containerRuntimeVersion'期待される出力:
docker://18.6.3 # Docker runtime
containerd://1.4.3 # containerd runtimedocker:// または containerd:// のプレフィックスを除いたバージョン番号を RUNTIME_VERSION 値として記録します。
ステップ 3:kubeadm join コマンドの生成
--ttl 0 フラグは必須です。これがないと、ジョイントークンの有効期限が切れ、自動スケーリングが機能しなくなります。
kubeadm token create --ttl 0 --print-join-command期待される出力:
kubeadm join 192.168.8.XXX:6443 --token k8xsq8.4oo8va9wcqpb*** \
--discovery-token-ca-cert-hash sha256:cb5fc894ab965dfbc4c194e1065869268f8845c3ec40f78f9021dde24610d***このコマンド全体を KUBEADM_JOIN_CMD 値として記録します。
サンプルスクリプト:Docker
スクリプトの先頭にある 3 つのプレースホルダーを、収集した値に置き換えます。
<KUBE_VERSION>— Kubernetes バージョン(例:1.21.0)<RUNTIME_VERSION>— Docker バージョン(例:18.6.3)<KUBEADM_JOIN_CMD>— 完全なkubeadm join ...コマンド
サンプルスクリプト:containerd
スクリプトの先頭にある 3 つのプレースホルダーを、収集した値に置き換えます。
<KUBE_VERSION>— Kubernetes バージョン(例:1.21.0)<RUNTIME_VERSION>— containerd バージョン(例:1.4.3)<KUBEADM_JOIN_CMD>— 完全なkubeadm join ...コマンド
ステップ 2:スクリプトのアップロード
スクリプトを、登録済みクラスターから到達可能なファイルサーバにアップロードします。Object Storage Service (OSS) が一般的な選択肢です。
アップロード後の URL の例:
https://kubelet-****.oss-cn-hangzhou-internal.aliyuncs.com/join-ecs-nodes.shこの URL を記録してください。次のステップで必要になります。
ステップ 3:スクリプトパスの登録
ノードプールを作成する前に、このステップを完了してください。スクリプトパスが登録されていない場合、ノードプールはスケールアウト時にスクリプトを取得できず、操作が失敗します。
kube-system 名前空間の ack-agent-config ConfigMap 内の addNodeScriptPath フィールドを設定します。
kubectl edit cm ack-agent-config -n kube-systemアップロードしたスクリプトの URL で 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ファイルを保存して閉じます。これにより、登録済みクラスターはノードプールをスケールアウトする際に、このスクリプトを使用して ECS ノードをブートストラップします。