セルフマネージドKubernetesクラスターがあり、実際のワークロードに基づいてクラスター内のノード数を動的に調整する場合は、Alibaba Cloud Auto Scalingと同時にcluster Autoscaler (CA) を使用して、効率的なリソース使用とサービスの安定性を確保できます。
このトピックでは、CAを手動でデプロイして、セルフマネージドKubernetesクラスターで自動ノードスケーリングを有効にする方法について説明します。 自己管理Kubernetesクラスターを登録済みのACK Oneクラスターに接続し、ACK Oneの自動スケーリング機能を使用してノードを自動的にスケーリングすることもできます。 ACK Oneの自動スケーリング機能を使用するには、次の手順を実行します。
ACK Oneの詳細については、「ACK Oneの概要」をご参照ください。
働き主義
CAは、クラスター内のノード数を自動的に調整するKubernetesのコンポーネントです。 CAはポッドのステータスを継続的に監視します。 CAがリソース不足のためにPending状態のポッドを検出した場合、CAはAuto Scalingをトリガーしてノード数を増やします。 このプロセスの動作を次の図に示します。
特定のノードのリソース使用量が常に事前定義済みのしきい値を下回ったことをCAが検出し、これらのノードのポッドを他のノードに移動できる場合、CAはポッドを代替ノードに追い出し、Auto Scalingをトリガーしてノード数を減らします。 このプロセスの動作を次の図に示します。
CAの詳細については、「クラスターオートスケーリング」をご参照ください。
準備
次の準備を完了していることを確認してください。
バージョンがV1.9.3以降のセルフマネージドKubernetesクラスターが作成されます。
重要このトピックでは、ECS (Elastic Compute Service) インスタンスを使用してKubernetesクラスターを作成します。 異なるクラウドサービスプロバイダーのデータセンターまたはインスタンスでオンプレミスマシンを使用する場合は、Alibaba cloud VPN GatewayまたはSmart Access Gatewayの公式ドキュメントを参照して、ネットワーク接続を確保してください。
RAM (Resource Access Management) ユーザーが作成されます。
CAがAlibaba Cloud Auto Scalingにアクセスしようとする場合、ユーザーIDとアクセス許可を確認するためにアクセス資格情報が必要です。 CA用のRAMユーザーを作成し、RAMユーザーにAuto Scalingアクセス権限を付与します。
RAMユーザーを作成し、RAMユーザーのAPIアクセスを有効にする方法については、「RAMユーザーの作成」をご参照ください。
RAMユーザーにカスタムポリシーをアタッチする方法については、「RAMユーザーへの権限の付与」をご参照ください。 このトピックでは、次のカスタムポリシーを使用します。
{ "Version": "1", "Statement": [ { "Action": [ "ess:Describe*", "ess:CreateScalingRule", "ess:ModifyScalingGroup", "ess:RemoveInstances", "ess:ExecuteScalingRule", "ess:ModifyScalingRule", "ess:DeleteScalingRule", "ess:DetachInstances", "ecs:DescribeInstanceTypes" ], "Resource": [ "*" ], "Effect": "Allow" } ] }AccessKey IDとAccessKeyシークレットで構成されるAccessKeyペアが作成されます。 後で使用するために、AccessKeyペアを保存する必要があります。 AccessKeyペアの作成方法の詳細については、「AccessKeyペアの作成」をご参照ください。
手順
(オプション) 手順1: クラスターAutoscalerイメージの作成
ソースコードを使用して、カスタムCluster Autoscalerイメージを作成できます。 次に、イメージを使用して、自己管理Kubernetesクラスターにクラスターオートスケーラーをデプロイできます。
または、この手順をスキップして、Alibaba Cloudが提供する次のcluster-autoscalerイメージess-cluster-autoscaler-registry.cn-hangzhou.cr.aliyuncs.com/ess-cluster-autoscaler/cluster-autoscaler:v1.7を使用することもできます。
GitHubからソースコードをダウンロードします。
mkdir -p $GOPATH/src/github.com/kubernetes cd $GOPATH/src/github.com/kubernetes git clone https://github.com/kubernetes/autoscaler.git cd autoscalerイメージを作成します。
# Compile the code. cd cluster-autoscaler && make build-arch-amd64 # Build an image. docker build -t cluster-autoscaler:v1.0 -f Dockerfile.amd64 . # Add tags. docker tag cluster-autoscaler:v1.0 Domain name of your image repository/cluster-autoscaler:v1.0 # Upload the image. docker push Domain name of your image repository/cluster-autoscaler:v1.0
手順2: スケーリンググループの作成と設定
スケーリンググループを作成します。
Auto Scalingコンソールにログインします。
上部のナビゲーションバーで、Auto Scalingを有効にしたリージョンを選択します。 左側のナビゲーションウィンドウで、[スケーリンググループ] をクリックします。 [スケーリンググループ] ページで、[作成] をクリックします。
[フォームで作成] タブで、プロンプトに従ってパラメーターを設定し、[作成] をクリックします。 スケーリンググループの作成方法の詳細については、「スケーリンググループの作成」をご参照ください。 この例で使用するパラメーター設定を次の表に示します。
パラメーター
パラメーター
Cron式
スケーリンググループ名
スケーリンググループの名前を入力します。
K8s-Node-Scaling-Group
データ型
[ECS] を選択します。 この値は、スケーリンググループにECSインスタンスが含まれることを示します。
ECS
インスタンス設定ソース
エラスティックコンテナインスタンスの自動作成に使用するテンプレートを指定しないでください。 スケーリンググループを作成したら、引き続きスケーリング設定を作成します。
スクラッチから作成
最小インスタンス数
この例では、このパラメーターは0に設定されています。 値0は、スケーリンググループの最初にECSインスタンスが含まれていないことを示します。
0
最大インスタンス数
この例では、このパラメーターは5に設定されています。 値5は、スケーリンググループに最大5つのECSインスタンスが含まれることを示します。
5
[VPC]
スケーリンググループ内のECSインスタンスに既存の仮想プライベートクラウド (VPC) を選択します。
vpcテスト****-001
vSwitch
異なるゾーンから複数のvSwitchを選択して、スケールアウト操作の成功率を向上させます。
vswテスト****
重要スケーリンググループを作成したら、後で使用するためにゾーンとスケーリンググループIDを記録します。
スケーリンググループのスケーリング設定を作成します。
作成したスケーリンググループを見つけ、[操作] 列の [詳細] をクリックして、スケーリンググループの詳細ページに移動します。
[インスタンス設定ソース] タブで、[スケーリング設定] をクリックします。 次に、[スケーリング設定の作成] をクリックして、[スケーリング設定の作成] ページに移動します。
スケーリング設定の作成方法の詳細については、「ECSタイプのスケーリング設定の作成」をご参照ください。 この例で使用するパラメーター設定を次の表に示します。
パラメーター | パラメーター | Cron式 |
スケーリング設定名 | スケーリング設定の名前を入力します。 | K8s-Scaling-Node-Config |
[課金方法] | ビジネス要件に基づいて課金方法を選択します。 | 従量課金 |
インスタンス設定モード | ビジネス要件に基づいてインスタンス設定モードを選択します。 | インスタンスタイプの指定 |
インスタンスタイプの選択 | ビジネス要件に基づいて1つ以上のインスタンスタイプを選択します。 警告 次のインスタンスファミリーのインスタンスタイプがサポートされています。
Armベースのエンタープライズレベルのコンピューティングインスタンスファミリーはサポートされていません。 インスタンスファミリーの詳細については、「インスタンスファミリーの概要」をご参照ください。 | ecs.g6a.large |
画像の選択 | ビジネス要件に基づいて画像を選択します。 | Alibaba Cloud Linux |
ネットワークとセキュリティグループを設定します。
セキュリティグループ: 既存のセキュリティグループを選択します。 セキュリティグループが自己管理Kubernetesクラスターへのアクセスを許可していることを確認します。
パブリックIPv4アドレスの割り当て: セルフマネージドKubernetesクラスターのAPI ServerコンポーネントがパブリックIPアドレスを使用している場合、このチェックボックスをオンにして、スケーリンググループ内のECSインスタンスのインターネットアクセスを有効にします。
警告さらに、API Serverコンポーネントのポート6443が有効になっていることを確認します。
セクションで、[インスタンスユーザーデータ] パラメーターを設定します。 [インスタンスユーザーデータ] テキストボックスに次のスクリプトを入力して、Kubernetesワーカーノードを初期化し、セルフマネージドKubernetesクラスターにワーカーノードを追加します。
重要<<YOUR_MASTER_NODE_IP>> をKubernetesマスターノードのIPアドレスに置き換えます。
#!/bin/bash # Disable the firewall. systemctl stop firewalld systemctl disable firewalld # Disable SELinux. sed -i 's/enforced /disabled/' /etc/selinux/config # Permanent setenforce 0 # Temporary # Disable swap. swapoff -a # Temporary sed -ri 's/.swap./#&/' /etc/fstab # Permanent # Pass the IPv4 bridged traffic to the iptables chain. cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system # Effective # Add a Kubernetes repository. cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF # General installation package yum install vim bash-completion net-tools gcc -y # Install Docker. wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo yum -y install docker-ce systemctl enable docker && systemctl start docker cat > /etc/docker/daemon.json << EOF { "exec-opts": ["native.cgroupdriver=systemd"] } EOF systemctl restart docker # Install kubeadm, kubectl, and kubelet. yum install -y kubelet-1.23.0 kubeadm-1.23.0 kubectl-1.23.0 # Start kubelet. systemctl enable kubelet && systemctl start kubelet # If kubelet fails to be started, you can run the journalctl -xeu kubelet command to troubleshoot the issue. # Add worker nodes to the cluster. regionId=$(sed -n 's/.*"region-id": "\(.*\)".*/\1/p' /run/cloud-init/instance-data.json) instanceId=$(sed -n 's/.*"instance_id": "\(.*\)".*/\1/p' /run/cloud-init/instance-data.json) privateIpv4=$(sed -n 's/.*"private-ipv4": "\(.*\)".*/\1/p' /run/cloud-init/instance-data.json) cat > kubeadm-config.yaml << EOF apiVersion: kubeadm.k8s.io/v1beta2 kind: JoinConfiguration discovery: bootstrapToken: token: "your-bootstrap-token" apiServerEndpoint: "<<YOUR_MASTER_NODE_IP>>:6443" caCertHashes: - "sha256:your-discovery-token-ca-cert-hash" nodeRegistration: name: "$regionId-$privateIpv4" kubeletExtraArgs: provider-id: "$regionId.$instanceId" EOF kubeadm join --config=kubeadm-config.yaml説明スケールアウトするワーカーノードの -- provider-idフィールドを指定します。 上記のスクリプトでは、-- provider-idフィールドが指定されています。
[作成] をクリックし、スケーリング設定を有効にします。
オプションです。 スケーリンググループでスケールアウトされたECSインスタンスが期待どおりにKubernetesクラスターに追加できるかどうかを確認します。
スケーリンググループ内のインスタンスの最小数を手動で1つ増やして、スケールアウトイベントをトリガーし、スケールアウトされたECSインスタンスが初期化され、期待どおりにセルフマネージドKubernetesクラスターに追加されているかどうかを確認できます。
手順3: クラスターAutoscalerコンポーネントを自己管理Kubernetesクラスターにデプロイする
このトピックの「準備」セクションで作成したAccessKey IDとAccessKeyシークレットをBase64形式でエンコードします。
echo $AccessKey-ID | tr -d '\n' | base64 echo $AccessKey-Secret | tr -d '\n' | base64 echo $RegionId | tr -d '\n' | base64deploy-ca.yamlという名前のファイルを作成します。 ビジネス要件に基づいて関連フィールドを変更します。 次に、自己管理Kubernetesクラスターのkube-system名前空間にファイルをデプロイします。 このトピックでは、次のdeploy-ca.yamlファイルを使用します。
重要次の操作を実行して、secretファイルのaccess-key-id、access-key-Secret、およびregion-idの設定を更新し、展開ファイルのcontainersフィールドの下のコマンドセクションのスケーリンググループIDを更新します。
<<YOUR_ACCESS_KEY_ID>> をBase64-encoded AccessKey IDに置き換えます。
<<YOUR_ACCESS_KEY_SECRET>> をBase64-encoded AccessKey secretに置き換えます。
<<YOUR_REGION_ID>> をBase64-encodedリージョンIDに置き換えます。 リージョンIDの取得方法については、「リージョン」をご参照ください。
<<YOUR_ESS_SCALING_GROUP_ID>> を、作成したスケーリンググループのIDに置き換えます。
<<KUBERNETES_SERVICE_HOST>> を自己管理KubernetesクラスターのAPI ServerコンポーネントのIPアドレスに置き換えます。
--- apiVersion: v1 kind: Secret metadata: name: cloud-config type: Opaque data: access-key-id: <<YOUR_ACCESS_KEY_ID>> access-key-secret: <<YOUR_ACCESS_KEY_SECRET>> region-id: <<YOUR_REGION_ID>> --- apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler name: cluster-autoscaler namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-autoscaler labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler rules: - apiGroups: [""] resources: ["events","endpoints"] verbs: ["create", "patch"] - apiGroups: [""] resources: ["pods/eviction"] verbs: ["create"] - apiGroups: [""] resources: ["pods/status"] verbs: ["update"] - apiGroups: [""] resources: ["endpoints"] resourceNames: ["cluster-autoscaler"] verbs: ["get","update"] - apiGroups: [""] resources: ["nodes"] verbs: ["watch","list","get","update"] - apiGroups: [""] resources: ["namespaces","pods","services","replicationcontrollers","persistentvolumeclaims","persistentvolumes"] verbs: ["watch","list","get"] - apiGroups: ["extensions"] resources: ["replicasets","daemonsets"] verbs: ["watch","list","get"] - apiGroups: ["policy"] resources: ["poddisruptionbudgets"] verbs: ["watch","list"] - apiGroups: ["apps"] resources: ["statefulsets", "replicasets", "daemonsets"] verbs: ["watch","list","get"] - apiGroups: ["batch"] resources: ["jobs"] verbs: ["watch","list","get"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"] verbs: ["watch","list","get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: cluster-autoscaler namespace: kube-system labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["create","list","watch"] - apiGroups: [""] resources: ["configmaps"] resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"] verbs: ["delete","get","update","watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cluster-autoscaler labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-autoscaler subjects: - kind: ServiceAccount name: cluster-autoscaler namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: cluster-autoscaler namespace: kube-system labels: k8s-addon: cluster-autoscaler.addons.k8s.io k8s-app: cluster-autoscaler roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: cluster-autoscaler subjects: - kind: ServiceAccount name: cluster-autoscaler namespace: kube-system --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cluster-autoscaler name: cluster-autoscaler namespace: kube-system spec: replicas: 1 selector: matchLabels: app: cluster-autoscaler template: metadata: labels: app: cluster-autoscaler spec: dnsPolicy: "None" dnsConfig: nameservers: - 100.100.2.136 - 100.100.2.138 options: - name: timeout value: "1" - name: attempts value: "3" priorityClassName: system-cluster-critical serviceAccountName: cluster-autoscaler containers: - command: - ./cluster-autoscaler - '--v=2' - '--logtostderr=true' - '--stderrthreshold=info' - '--cloud-provider=alicloud' - '--expander=least-waste' - '--scan-interval=60s' - '--scale-down-enabled=true' - '--scale-down-delay-after-add=10m' - '--scale-down-delay-after-failure=1m' - '--scale-down-unready-time=2m' - '--ok-total-unready-count=1000' - '--max-empty-bulk-delete=50' - '--leader-elect=false' - '--max-node-provision-time=5m' - '--scale-up-from-zero=true' - '--daemonset-eviction-for-empty-nodes=false' - '--daemonset-eviction-for-occupied-nodes=false' - '--max-graceful-termination-sec=14400' - '--skip-nodes-with-system-pods=true' - '--skip-nodes-with-local-storage=false' - '--min-replica-count=0' - '--scale-down-unneeded-time=10m' - '--scale-down-utilization-threshold=0.3' - '--scale-down-gpu-utilization-threshold=0.3' - '--nodes=0:100:<<YOUR_ESS_SCALING_GROUP_ID>>' image: >- ess-cluster-autoscaler-registry.cn-hangzhou.cr.aliyuncs.com/ess-cluster-autoscaler/cluster-autoscaler:v1.7 imagePullPolicy: Always name: cluster-autoscaler resources: requests: cpu: 100m memory: 300Mi securityContext: allowPrivilegeEscalation: true capabilities: add: - SYS_ADMIN drop: - ALL env: - name: ACCESS_KEY_ID valueFrom: secretKeyRef: name: cloud-config key: access-key-id - name: ACCESS_KEY_SECRET valueFrom: secretKeyRef: name: cloud-config key: access-key-secret - name: REGION_ID valueFrom: secretKeyRef: name: cloud-config key: region-id - name: KUBERNETES_SERVICE_HOST value: "<<KUBERNETES_SERVICE_HOST>>" - name: KUBERNETES_SERVICE_PORT value: "6443" - name: KUBERNETES_SERVICE_PORT_HTTPS value: "6443"説明-- scale-down-enabledパラメーターを設定して、自動スケールインを有効にすることができます。 自動スケールインを有効にすると、CAはクラスターのステータスを定期的に監視し、リソース使用量が50% を超えないノードを特定します。-- scale-down-utilization-thresholdパラメーターを設定して、リソース使用量のしきい値を指定できます。デフォルトでは、CAはkube-system名前空間のポッドを終了しません。
-- skip-nodes-with-system-podsパラメーターをfalseに設定して、デフォルト設定を上書きできます。デフォルトでは、CAはスケールイン操作を完了するのに約10分かかります。
スケールダウン遅延パラメーターを設定して、カスタム待機期間を指定できます。 たとえば、-- scale-down-delayパラメーターを5 mに設定した場合、待機時間は5分になります。deploy-ca.yamlファイルを複数のスケーリンググループに適用する場合は、
-- expanderパラメーターをrandom、most-pod、またはleast-wasteに設定できます。random: スケールアウトイベント中にスケーリンググループをランダムに選択します。most-pods: スケールアウトイベント中にポッド数が最も多いスケーリンググループを選択します。least-waste: スケールアウトイベント中にCPUまたはメモリリソースを使用するスケーリンググループを選択します。 複数のスケーリンググループが使用するCPUまたはメモリリソースが最も少ない場合、このパラメーターは自動的にランダムにリセットされます。
次のコマンドを実行して、CAを自己管理Kubernetesクラスターにデプロイします。
kubectl apply -f deploy-ca.yaml -n kube-system
(オプション) 機能の確認
リソース不足のためにKubernetesクラスターにPending状態のポッドがある場合、CAはAuto Scalingをトリガーしてノードをスケールアウトします。 ノードのリソース使用量が常に定義済みのしきい値を下回った場合、CAはAuto Scalingをトリガーしてノードをスケールインします。
nginx-demo.yamlという名前の単純なファイルをデプロイして、自動スケールアウト機能を検証します。 この例では, 次のnginx-demo.yamlファイルを使用します。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-demo spec: selector: matchLabels: app: nginx-demo replicas: 2 template: metadata: labels: app: nginx-demo spec: containers: - name: nginx image: ess-cluster-autoscaler-registry.cn-hangzhou.cr.aliyuncs.com/ess-cluster-autoscaler/nginx-demo:v1.0 ports: - containerPort: 80 name: http - containerPort: 443 name: https resources: requests: memory: 1Gi cpu: 1 limits: memory: 1Gi cpu: '1'次のコマンドを実行して、nginx-demo.yamlファイルをデプロイします。
kubectl apply -f nginx-demo.yamlリソース不足のためにPending状態のポッドが存在するかどうかを確認するために、レプリカの数を増やします。 次のコマンドを実行して、レプリカの数を増やします。
kubectl scale deployment nginx-demo --replicas=5スケーリンググループにスケールアウトプロセスがあるかどうかを確認するために、約1分待ちます。
スケーリンググループでスケールアウトプロセスが完了したら、3分間待って、Kubernetesクラスターに新しいノードが追加されているかどうかを確認します。 次のコマンドを実行して、Kubernetesクラスター内のすべてのノードを表示し、クラスターに新しいノードが追加されているかどうかを確認します。
kubectl get nodes
自動スケールイン機能を確認するには、nginx-demoレプリカの数を減らして、ノードのリソース使用量を事前定義済みのしきい値未満に減らします。 次に、スケーリンググループにスケールインプロセスがあるかどうかを確認します。