はじめに
こんにちは!
本記事は「本気で学ぶKubernetes」シリーズの第15回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。
このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!
今回はKubernetesのメトリクスを活用しながら負荷に応じて自動的にPod数を増減させる「HPA」について学んでいきたいと思います。
この記事は人間がKubernetesの公式ドキュメントを読み漁りながら書いていますのでご安心ください!
HPAとは
Horizontal Pod Autoscaler (以降HPA) は、CPU使用率やメモリ使用率などのメトリクスに基づいてDeploymentやStatefulSetのPod数を自動的に調整する機能です。
メトリクスベースで動作させることができるため、「CPU」や「メモリ」、「カスタムメトリクス」を監視して閾値を超えたら自動的にスケールすることが可能です。
似たような機能としてにVertical Pod Autoscaler(VPN) という機能もありますががこちらはPodのリソース量を増減する垂直スケーリングを行います。
出典: Kubernetes公式ドキュメント - Horizontal Pod Autoscaling
HPAはメトリクスを監視する必要がある都合、Metrics Serverといったアドオンを起動してAPIで収集できるようにしておきます。
Metrics Server自体は、KubernetesクラスタからCPU・メモリのメトリクスを収集しており、ユーザーもkubectl topコマンドでリアルタイムにリソース使用状況を確認できるようになります。
HPAで水平スケーリングを行ってみる
minikubeでMetrics Serverを有効化します。
# minikubeを起動していない方は実行
minikube start
# Metrics Serverアドオンを有効化
minikube addons enable metrics-server
# ...省略...
# 🌟 'metrics-server' アドオンが有効です
# 確認
kubectl get pods -n kube-system | grep metrics-server
# metrics-server-xxxxxxxxxx-xxxxx 1/1 Running 0 30s
数分待ってから、Metrics Serverが動作していることを確認します。
kubectl top nodes
# NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
# minikube 250m 12% 1200Mi 30%
上記が前述したMetrics Serverによってリアルタイムにリソース使用状況を確認するコマンドです。
DeploymentとServiceの作成
Resource Requestsを設定したDeploymentを作成します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
replicas: 1
selector:
matchLabels:
app: php-apache
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example
ports:
- containerPort: 80
resources:
requests:
cpu: 200m # HPAの計算に必要
limits:
cpu: 500m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
selector:
app: php-apache
ports:
- port: 80
targetPort: 80
上記のマニフェストでは、registry.k8s.io/hpa-exampleというKubernetes公式が出しているテスト用イメージを使用しています。
Resource Requestsでcpu: 200mを設定しています。
デプロイしてみましょう。
kubectl apply -f php-apache-deployment.yaml
# deployment.apps/php-apache created
# service/php-apache created
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# php-apache-xxxxxxxxxx-xxxxx 1/1 Running 0 10s
HPAの作成
以下のコマンドでCPU使用率50%を目標にしたHPAを作成します。
kubectl autoscale deployment php-apache \
--cpu-percent=50 \
--min=1 \
--max=10
# horizontalpodautoscaler.autoscaling/php-apache autoscaled
作成したHPAを確認してみます。
kubectl get hpa
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# php-apache-hpa Deployment/php-apache 0%/50% 1 10 1 10s
TARGETSが0%/50%となっており、現在のCPU使用率が0%目標が50%であることがわかります。
また最小Podが1、最大が10となっていますので負荷がかかると最大10こまでPodがスケーリングされます。
負荷をかけてスケールアウトを確認する
別のターミナルで負荷をかけてみます。
以下のコマンドは、0.01秒ごとにphp-apacheにHTTPリクエストを送り続けます。
# 負荷生成用のPodを起動
kubectl run -it --rm load-generator \
--image=busybox \
--restart=Never \
-- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
元のターミナルでHPAの状態を監視してみます。
kubectl get hpa --watch
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# php-apache Deployment/php-apache cpu: 0%/50% 1 10 1 2m35s
# php-apache Deployment/php-apache cpu: 197%/50% 1 10 1 2m45s
# php-apache Deployment/php-apache cpu: 197%/50% 1 10 4 3m
# php-apache Deployment/php-apache cpu: 84%/50% 1 10 4 3m45s
CPU使用率が197%まで上昇し、HPAが自動的にPod数を4個に増やしていることがわかります。
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# php-apache-xxxxxxxxxx-aaaaa 1/1 Running 0 2m
# php-apache-xxxxxxxxxx-bbbbb 1/1 Running 0 30s
# php-apache-xxxxxxxxxx-ccccc 1/1 Running 0 30s
# php-apache-xxxxxxxxxx-ddddd 1/1 Running 0 30s
実際にPod数を確認してみると、4つのPodが起動しているのでHPAが正常に機能していることを確認できました。
スケールインの確認
負荷生成用のPodを停止してみると、数分後にPod数が自動的に減ります。
kubectl get hpa --watch
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# php-apache Deployment/php-apache cpu: 84%/50% 1 10 4 3m45s
# php-apache. Deployment/php-apache cpu: 0%/50% 1 10 1 10m
CPU使用率が0%に下がり、最終的には数分後にPod数が1個に戻りました。
スケールインはスケールアウトよりも慎重に行われるため、スケールアウト時よりも時間がかかります。これは急激なトラフィック変動に対して安全にリソースを調整していくためのようです。
出典: Kubernetes公式ドキュメント - Horizontal Pod Autoscaler Walkthrough
HPAの詳細設定
HPAのスケーリング動作は以下のようにYAML形式で宣言して適用することもできます。
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # スケールイン前に5分待つ
policies:
- type: Percent
value: 50
periodSeconds: 15 # 15秒ごとに最大50%まで削減
scaleUp:
stabilizationWindowSeconds: 0 # スケールアウトは即座に
policies:
- type: Percent
value: 100
periodSeconds: 15 # 15秒ごとに最大100%まで増加
先ほどはCPUベースでスケーリングを行いましたが、それ以外にメモリでもスケーリングすることができます。
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
またPrometheusなどと連携してカスタムメトリクス(HTTPリクエスト数など)でスケーリングしていくことも可能です。
これは非機能要件に応じて適切に運用していきましょう!
クリーンアップ
# HPAを削除
kubectl delete hpa php-apache-hpa
# horizontalpodautoscaler.autoscaling "php-apache-hpa" deleted
# DeploymentとServiceを削除
kubectl delete -f php-apache-deployment.yaml
# deployment.apps "php-apache" deleted
# service "php-apache" deleted
まとめと次回予告
HPAは負荷に応じてPod数を自動調整する機能で、Metrics ServerがメトリクスをHPAに提供しCPU使用率やメモリ使用率を監視してスケーリングしています。
Webアプリケーションのトラフィックの変動に対応したり、バッチ処理などのキュー長に応じたスケーリングに使えます。
また、セールや広告掲載など一過性のもの、時間帯によるアクセス変動(昼間と夜間)にも自動で対応させることも可能になります。
次回は、NamespaceやLabelなどでリソースを整理していく方法についてまとめられればと思います。
それでは、また次回!