クラウド事業推進部の石倉です。
今回はKubernetesのスケーリングで利用されるPodのスケーリングをするHorizontal Pod AutoscalerとノードのスケーリングをするCluster Autoscalerについて手を動かしながら確認してみたのでハンズオンのような形で紹介します。
Horizontal Pod Autoscalerについて
まずはHorizontal Pod Autoscaler(以降HPA)についてです。
HPAはPodのスケーリングです。Deployment(Podを管理するリソース)などのターゲットに対してPodのCPU使用率などの理想値を設定し、理想値と現在値から計算してPodをスケーリングさせます。
何台にスケーリングさせるかの計算ロジックなどについてはドキュメントに載っています。
それでは早速手を動かしていきたいと思います。今回はAWSのEKS環境で確認していきます。
準備
まずはEKS環境を用意します。
eksctlというツールがあるので今回はそれを利用します。(eksctlのインストール手順はこちらのドキュメントを参考にしてください)
CloudShellなどから実行していきます。
eksctl create cluster --name ishikura-demo --region ap-northeast-1 --node-type t3.medium --nodes 1
これだけで必要なEKSノードやVPCなどのネットワークまわりが一緒に作成されます。(裏ではCloudFormationが動いています)
どんなオプションがあるかはeksctl create cluster --help
で確認できます。
今回は東京リージョンに「ishikura-demo」という名前のEKSクラスターで、t3.mediumのノードを1つ作成します。
ちなみにデフォルトだとm5.largeのノードが2つ作成されます。
HPAを試してみる
以下のマニフェストファイルをkubectl apply -f {ファイル名}
で適用します。
apiVersion: apps/v1 kind: Deployment metadata: name: php-apache spec: selector: matchLabels: run: php-apache template: metadata: labels: run: php-apache spec: containers: - name: php-apache image: registry.k8s.io/hpa-example ports: - containerPort: 80 resources: limits: cpu: 500m requests: cpu: 200m --- apiVersion: v1 kind: Service metadata: name: php-apache labels: run: php-apache spec: ports: - port: 80 selector: run: php-apache --- apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: php-apache namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 50
内容としては、
・php-apacheアプリケーションを立てる(重い処理をした後にOK!と返すもの)
・アプリケーションを立てるには最低限200ミリコアを必要とする
・理想値をCPU使用率50%とし、1~10の範囲でPodをスケーリングさせるHPA設定
という感じです。
apply後はkubectl get node,pod,hpa
などで状態を確認しましょう。(この時点ではまだ負荷がないのでHPAのCPU使用率表示箇所は0%になっているかと思います)
$ kubectl get node,pod,hpa NAME STATUS ROLES AGE VERSION node/ip-192-168-62-4.ap-northeast-1.compute.internal Ready <none> 4m23s v1.32.3-eks-473151a NAME READY STATUS RESTARTS AGE pod/php-apache-6487c65df8-7x24s 1/1 Running 0 83s NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/php-apache Deployment/php-apache cpu: 0%/50% 1 10 1 83s
準備ができたら負荷をかけてみます。watchコマンドなどで継続的に確認しておくと流れが見やすいと思います。 (負荷コマンドは別ターミナルから実行してください)
## watchコマンドで継続的に見る watch kubectl get node,pod,hpa ## 負荷をかける kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
するとHPAのCPU使用率表示箇所の数値が上がり、php-apacheアプリケーションのPodが増えるのが見えると思います。
NAME STATUS ROLES AGE VERSION node/ip-192-168-62-4.ap-northeast-1.compute.internal Ready <none> 9m19s v1.32.3-eks-473151a NAME READY STATUS RESTARTS AGE pod/load-generator 1/1 Running 0 3m54s pod/php-apache-6487c65df8-7x24s 1/1 Running 0 6m19s pod/php-apache-6487c65df8-jppgt 1/1 Running 0 3m3s pod/php-apache-6487c65df8-jv7lq 1/1 Running 0 3m18s pod/php-apache-6487c65df8-kg7s6 0/1 Pending 0 2m33s pod/php-apache-6487c65df8-pntx6 1/1 Running 0 3m18s pod/php-apache-6487c65df8-s6nb8 1/1 Running 0 2m48s pod/php-apache-6487c65df8-sz9jf 0/1 Pending 0 2m48s pod/php-apache-6487c65df8-w27xj 1/1 Running 0 3m18s pod/php-apache-6487c65df8-xnnrj 0/1 Pending 0 2m33s NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/php-apache Deployment/php-apache cpu: 63%/50% 1 10 9 6m19s
ここではCPU使用率が63%となり、アプリケーションのPodが9台に増えています。
ですが、CPU使用率はまだ理想値を上回っている状態です。また、PendingのままとなっているアプリケーションのPodがありますね。
kubectl describe pod {Pod名}
でPendingのままになっているアプリケーションのPodの状態を見てみます。
$ kubectl describe pod {Pending状態のPod名} ... ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 4m1s default-scheduler 0/1 nodes are available: 1 Insufficient cpu. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.
今回はマニフェストファイルでphp-apacheアプリケーションのcpuのrequests値を200にしているため、アプリケーションのPodを立てるにはノードの空き容量に200ミリコア残っている必要があります。
ですがもうノードに空き容量が残っていないため、HPAによってPodを増やしたくても立てることができなくなっているという状態です。
実際にEKSコンソールからノードの状態を見ると利用可能なCPUが残っていないことが見てとれます。
ここで登場するのがCluster Autoscalerです。
もう、1つのノードではこれ以上Podを立てられないのでノード自体を増やしましょう。
次に行く前に負荷コマンドは停止しておいてください。
Cluster Autoscalerについて
Cluster Autoscalerはノードのスケーリングです。
Pending状態のPodを検知してノードのスケーリングをしてくれます。
AWS環境の場合はAutoScalingグループを操作してスケーリングさせています。
HPAでPodを増やそうとしたものの、ノード自体のリソース上限に達してしまいPodを新しく立てられなくなった場合にノード自体を増やすことでPodを立てられるようになります。
準備
Cluster Autoscalerを使うにあたりドキュメントに記載されている以下の2つを対応します。
・ノードのIAMロールへのIAMポリシーの付与
・マニフェストファイルの用意
ノードのIAMロールはEKSコンソールから確認できるので、そのIAMロールにドキュメントに記載されている内容のIAMポリシーを付与しておきます。
マニフェストファイルについてはドキュメントで用意されているファイルの以下の2箇所を直して作成します。
- 149行目のバージョンをEKSのKubernetesのバージョンに合わせます。 ドキュメントの例はv1.26ですが、今回はv1.32ですので直します。 バージョン履歴はこちらに載っています。
- 165行目のクラスター名を直します。
変更箇所の149~165行目はこんな感じです。
148 containers: 149 - image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.32.1 ## 変更箇所 150 name: cluster-autoscaler 151 resources: 152 limits: 153 cpu: 100m 154 memory: 600Mi 155 requests: 156 cpu: 100m 157 memory: 600Mi 158 command: 159 - ./cluster-autoscaler 160 - --v=4 161 - --stderrthreshold=info 162 - --cloud-provider=aws 163 - --skip-nodes-with-local-storage=false 164 - --expander=least-waste 165 - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/ishikura-demo ## 変更箇所
Cluster Autoscalerを試してみる
準備したCluster Autoscalerのマニフェストファイルをapplyします。
kubectl apply -f {Cluster Autoscalerのマニフェストファイル}
ノードをスケーリングさせるために最大数を3に変更しておきます。
それでは再び負荷をかけてみます。
## watchコマンドで継続的に見る watch kubectl get node,pod,hpa ## 負荷をかける kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
先ほどと同じようにPending状態のphp-apacheアプリケーションのPodが発生しますがそれを検知してノードのスケーリングがされます。
NAME STATUS ROLES AGE VERSION node/ip-192-168-62-4.ap-northeast-1.compute.internal Ready <none> 119m v1.32.3-eks-473151a node/ip-192-168-86-234.ap-northeast-1.compute.internal Ready <none> 3m36s v1.32.3-eks-473151a NAME READY STATUS RESTARTS AGE pod/load-generator 1/1 Running 0 5m32s pod/php-apache-6487c65df8-6q7bc 1/1 Running 0 5m5s pod/php-apache-6487c65df8-cvb2k 1/1 Running 0 5m5s pod/php-apache-6487c65df8-jx2z7 1/1 Running 0 24m pod/php-apache-6487c65df8-sf4g4 1/1 Running 0 4m50s pod/php-apache-6487c65df8-w58fj 1/1 Running 0 5m5s pod/php-apache-6487c65df8-x68sh 1/1 Running 0 109s pod/php-apache-6487c65df8-xbw6f 1/1 Running 0 4m5s pod/php-apache-6487c65df8-xfkdf 1/1 Running 0 4m5s pod/php-apache-6487c65df8-xnhq5 1/1 Running 0 109s NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/php-apache Deployment/php-apache cpu: 41%/50% 1 10 9 116m
ここでは最終的にノードが2つに増え、アプリケーションのPodも全てRunningとなりCPU使用率が41%となりました。
Cluster AutoscalerのおかげでPending状態のPodを検知しノードを増やして無事Podを増設できました。
負荷を止めると次第にPodとノードが削除されるのが確認できると思います。
最後に
簡単な動作確認ではありますが、Horizontal Pod AutoscalerとCluster Autoscalerについてどなたかのイメージの手助けになれば幸いです。
参考
Amazon EKS – eksctl の使用を開始する - アマゾン EKS
Horizontal Pod Autoscalerウォークスルー | Kubernetes
autoscaler/cluster-autoscaler/cloudprovider/aws/README.md at master · kubernetes/autoscaler · GitHub