こんにちは! Azure テクニカル サポート チームの川畑です。
Kubernetes を利用するにあたり、負荷に応じてワークロードを動的に増減させるオートスケーリングの構成を取ることがあります。
この記事では、 Azure Kubernetes Service (AKS) を利用している環境を想定し、Pod およびノードのオートスケーリングの設定と動作についてご紹介します。
スケーリングとは?水平オートスケーラー (HPA)
スケーリングには、スケールアップ / スケールダウンとスケールアウト / スケール インの 2 種類があります。
スケールアップは、垂直スケールとも呼ばれ、1 台あたりのコンピュート リソースを増やすことでシステムの性能を上げる手段となります。
AKS では、AKS ノードとして利用している Azure 仮想マシンのサイズ (vCPU 数) を増やす、Pod に割り当てるリソース量を増やすなど、ノードや Podのコンピュート リソースを増やす方法が挙げられます。
次に、スケールアウトは、水平スケールとも呼ばれ、コンピュート リソースは変えず、ノードの数や Pod のレプリカ数を増やすことでシステムの性能を上げる手段となります。
これらのスケーリングの操作は、クラスターの利用者によって手動で実施される場合と、オートスケールの機能によって自動で実施される場合があります。
表でまとめると次のような形となります。
自動/手動 | 水平/垂直 | Pod/ノード | |
---|---|---|---|
水平オートスケーラー (HPA) | 自動 | 水平 | Pod |
クラスター オートスケーラー | 自動 | 水平 | ノード |
KEDA *1 | 自動 | 水平 | Pod |
垂直オートスケーラー (VPA) *1 | 自動 | 垂直 | Pod |
レプリカ数の定義変更 | 手動 | 水平 | Pod |
Azure CLI (az aks acale) / Azure Portal | 手動 | 水平 | ノード |
ノード プールのサイズ変更 *2 | 手動 | 垂直 | ノード |
*1 2022.12.24 時点ではプレビューの機能です。
*2 ドキュメントのタイトルは「変更」となっていますが、新しいサイズでノードプールを作成・削除する手順となります。
今回はこれらの方法のうち、自動でスケーリング可能な水平オートスケーラー (HPA) とクラスター オートスケーラーについて紹介します。
Pod のオートスケーリング (HPA)
AKS では、Pod のレプリカ数を負荷に応じてスケーリングする Pod の水平オートスケーラー (HPA) が使用できます。
HPA は、Kubernetes の標準 API リソースであり、AKS 固有の機能ではありません。
そのため、HPA の内容に関しましては、下記 Kubernetes 公式ドキュメントの内容に準拠します。
ご参考情報:Horizontal Pod Autoscalerウォークスルー | Kubernetes
https://kubernetes.io/ja/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
HPA では、ノード上のメトリクス情報を kubelet を経由して Kubernetes クラスター内に存在するメトリクス サーバーに収集します。
なお、このメトリクス サーバーは現時点でサポートされている AKS クラスターでは標準でデプロイされております。
1 | kubectl get pods -n kube-system -l k8s-app=metrics-server |
メトリクス サーバーは収集された情報より、Pod が使用している CPU やメモリ等のメトリクス情報に基づき Deployment、ReplicaSet または StatefulSet といったレプリケーション コントローラー内のPodのレプリカ数をスケーリングします。
これによって、負荷に応じて Pod のレプリカ数が増減します。
それでは、実際に AKS クラスターを利用して HPA の設定をします。
HPA の挙動を確認してみる
ここでは、AKS のチュートリアルで利用されているサンプル アプリケーション (azure-vote) を用いて確認します。
サンプル アプリケーションをローカル端末にクローンします。
1 | git clone https://github.com/Azure-Samples/azure-voting-app-redis.git |
上記コマンドによってクローンされたマニフェスト ファイルを確認し、コンテナーにリソース要求が設定されていることを確認します。
1 | less ./azure-voting-app-redis/azure-vote-all-in-one-redis.yaml |
azure-vote-front コンテナーでは、次のようにリソース要求が設定されていることが確認できます。
1 | containers: |
上記リソース要求を確認すると、コンテナーをデプロイするために必要なリソースは、250 ミリ CPU であり、制限は 500 ミリ CPU となっていることが確認できました。
HPA では、対象のレプリケーション コントローラー内の Pod に設定された、リソース要求に対する使用率の平均を計算します。
それでは、当該 Pod をデプロイします。
1 | kubectl apply -f ./azure-voting-app-redis/azure-vote-all-in-one-redis.yaml |
デプロイされた Pod を確認します。
1 | kubectl get pods |
azure-vote-front の Pod が作成されていることを確認できました。
それでは、ここから HPA の設定をします。
HPA の設定は、HorizontalPodAutoscaler リソースを用いて定義することが可能となり、kubectl autoscale コマンドもしくは、マニフェスト ファイルを用いて作成することが可能となります。
今回の検証では、Deplyoment “azure-vote-front” 内の全 Pod の平均 CPU 使用率が 50% を目標に、最小 3 台、最大 10 台まで Pod のレプリカ数を増減させるように設定します。
この設定を kubectl autoscale コマンドにて実施する場合は、下記コマンドとなります。
1 | kubectl autoscale deployment azure-vote-front --cpu-percent=50 --min=3 --max=10 |
この HPA によって Deplyoment “azure-vote-front” 内の Pod のレプリカ数は最小 3 台となるため、先ほど確認した Pod のレプリカ数は 1 台でしたが、3 台に増えていることが確認できます。
1 | kubectl get pods -l app=azure-vote-front |
想定どおり、Pod のレプリカ数が HPA の設定にしたがって Pod のレプリカ数が増えたことが確認できました。
次に、Pod に負荷をかけることで、HPA によって Pod のレプリカ数が増えることを確認します。
まずは、事前に現在の Pod の CPU 負荷状況を kubectl top pods コマンドを用いて確認します。
1 | kubectl top pods -l app=azure-vote-front |
現在の Pod の CPU 使用量が低い状況であることが確認できました。
次に、CPU に負荷をかけるために、今回は stress コマンドを用います。
1 | kubectl exec -it azure-vote-front-7589b695dd-d7psh -- stress -c 1 |
stress コマンドによって、Pod “azure-vote-front-7589b695dd-d7psh” の CPU に負荷をかけ始めました。再度 kubectl top pods コマンドを用いて CPU の負荷状況を確認します。
1 | kubectl top pods -l app=azure-vote-front |
先ほど 2 ミリ CPU 程度であったのに対して、312 ミリ CPU 程リソースを消費していることが確認できました。
ここで HPA の状況ならびに Pod の稼働状況を確認します。
1 | kubectl get hpa |
stress コマンドを用いて CPU の負荷をかけたことによって、Pod のレプリカ数が 3 から 4 に増えたことが確認できました。
最後に stress コマンドを停止し、増えた Pod が自動で削除されることも確認します。
1 | < - Control + Cキー によってプロセスを終了する |
再度 kubectl top pods コマンドを用いて CPU の負荷状況を確認します。
1 | kubectl top pods -l app=azure-vote-front |
Pod “azure-vote-front-7589b695dd-d7psh” の CPU 使用量が減少したことが確認できました。
その後、しばらくした後に、次のように Pod のレプリカ数が最小の 3 に戻ることが確認できます。
1 | kubectl get hpa |
このように HPA を利用することで、Pod の負荷状況に応じて Pod のレプリカ数を自動で増減可能なことを確認しました。
クラスター オートスケーラーについて
AKS では、ノードをオートスケールするための機能として、クラスター オートスケーラーが提供されています。
クラスター オートスケーラーを利用することで、新規 Pod がデプロイ可能な空きノードが不足し、Pending (割り当て不可) 状態となった際にノードである Azure 仮想マシンの数を自動で増減することが可能となります。
これによって、Pod のデプロイに必要なノード数のみ稼働させることで、コストの最適化などが期待されます。
重要
クラスター オートスケーラーは、CPU やメモリ等のリソースの使用率を監視し自動でスケールする機能ではありません。
新規 Pod がデプロイ可能な空きノードが不足し、Pending (割り当て不可) 状態となった際に自動でスケールアウトする機能となります。
警告
AKS のクラスター オートスケーラーを利用する場合、VMSS のオートスケール機能を有効にしないでください。
AKS では、VMSS などの IaaS リソースの API を用いて直接変更することはサポート外となります。
いずれの機能も有効にした場合は、 VMSS へ直接変更を加えたことにより、AKS クラスターがサポートされない状態になる恐れや、2 つのオートスケ
ールの処理が競合することで、ノードの増減が想定通りに動作しない可能性がございます。
ご参考情報:エージェント ノードのユーザー カスタマイズ
https://learn.microsoft.com/ja-jp/azure/aks/support-policies#user-customization-of-agent-nodes
ご参考情報: AKS クラスターの作成とクラスター オートスケーラーの有効化
そのため、適切にクラスター オートスケーラーを利用するためには、各 Pod に適切なリソース要求を設定することが重要となります。
それでは、実際に AKS クラスターを利用してクラスター オートスケーラーの挙動を確認します。
クラスター オートスケーラーの挙動を確認してみる
クラスター オートスケーラーの挙動を確認するにあたり、まずはユーザー ノードプールを追加します。
ここでは、ノード数が 1、仮想マシンのサイズが Standard_DS2_v2 (2vCPU, 7GiB) のノード プールを追加します。
1 | az aks nodepool add \ |
追加されたノードの情報を確認します。
1 | kubectl get nodes |
ノードが追加されていることを確認しました。
それでは、このノード プールにリソース要求を設定した Pod をデプロイするために、Deployments のマニフェスト ファイルを作成します。
1 | cat << EOF >> ca-test-pod.yaml |
上記定義によって、nodelabel キーにcatest を持つノードにのみ nginx Pod が配置されます。これによって、他のノードに Pod がデプロイされることを防げます。
それでは、このマニフェスト ファイルに従い、Deployment を作成します。
1 | kubectl apply -f ca-test-pod.yaml |
Pod “nginx-67d6486785-7rj7r” が Pending 状態であることが確認できました。 原因を確認します。
1 | kubectl describe pod nginx-67d6486785-7rj7r |
このメッセージは、クラスター内の全 4 台のノードのうち、1 ノードはメモリの空き容量が不足しており、他 3 ノードがセレクターを満たさず、Pod をスケジューリング可能なノードが見つからなかったことを示します。
これによって、ノード プール “usernp1” では、リソースの不足に伴い Pod が Pending となる状況となりました。
この状態で、ノード プール “usernp1” に対して、クラスター オートスケーラーを有効にします。
1 | az aks nodepool update \ |
クラスター オートスケーラーを有効化したので、ノードが追加されていることを確認します。
1 | kubectl get nodes |
期待どおりノード プール “usernp1” に新規ノード “usernp1-70474131-vmss000001”が作成され、Pod “nginx-67d6486785-7rj7r” がデプロイされていることが確認できました。
最後に Pod のレプリカ数を 1 に減らし、ノードが自動削除されることを確認します。
マニフェスト ファイルを修正し、Pod のレプリカ数を 1 に減らした後に、再度マニフェスト ファイルを適用します。
1 | kubectl apply -f ca-test-pod.yaml |
これによって、Pod のレプリカ数およびノードが減っていることを確認します。
1 | kubectl get pods -o wide |
このように クラスター オートスケーラーを利用することで、ノード上のリソース不足が原因で Pending となった Pod が発生した際にノード プール内のノードの数を自動で増え、リソースの使用率が低下した際にノードの数が自動で減ることが確認できました。
さいごに
この記事では、HPA とクラスター オートスケーラーによる Pod とノードのオートスケーリングのしくみについて、サンプル アプリケーションを例にご紹介しました。設定した条件に応じて、自動でスケールアウトされることが確認いただけたかと思います。
こういったオートスケールの設定を適切にお使いいただくことで、お客様のワークロードの可用性を高めることができるかと存じますので、ご参考にいただけますと幸いです。
本稿が皆様のお役に立ちましたら幸いです。
最後まで読んでいただきありがとうございました!
※本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。