Pod の Autoscaling について
Kubernetes で動いている Pod は基本的に spec.Replicas
で指定した個数に制限されます。それ以上もそれ以下もありません。なので急激なアクセス増加に対応できずに Pod が OOM(Out of Memory)
で Kill されてしまったり、逆にアクセスが少ない時間に無駄な Pod を動かすことになったりします。
そこで使うのが Horizontal Pod Autoscaler
です。 水平スケール
とも言います。これは水平方向へのスケールイン/アウトなので同じ性能の Pod が増減します。
実際に動きを見てみましょう。
YAML
今回は hpa-sample
というネームスペースで作業します。
apiVersion: v1
kind: Namespace
metadata:
name: hpa-sample
私が作成したわざと重い処理を行わせる PHP ベースのイメージを利用します。
spec.template.spec.containers[].resources
は必須です。
requests
と limits
を設定しておきます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hpa-deploy
namespace: hpa-sample
spec:
replicas: 1
selector:
matchLabels:
app: hpa-deploy
template:
metadata:
labels:
app: hpa-deploy
spec:
containers:
- name: hpa-deploy
image: iedred7584/hpa-sample
resources:
requests:
memory: 128Mi
cpu: 100m
limits:
memory: 128Mi
cpu: 500m
ports:
- containerPort: 80
Service も作成してアクセスできるようにします。
apiVersion: v1
kind: Service
metadata:
name: hpa-svc
namespace: hpa-sample
spec:
type: LoadBalancer
selector:
app: hpa-deploy
ports:
- port: 80
targetPort: 80
次の YAML が今回の肝の HorizontalPodAutoscaler
です。
対象の Deployment の指定や、 Pod の最小/最大個数の指定、 Pod がどの程度 CPU を使っていたら発火するかの条件を指定します。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: hpa-hpa
namespace: hpa-sample
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: hpa-deploy
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50
これらの YAML を食わせます。
$ kubectl apply -f .
namespace/hpa-sample created
deployment.apps/hpa-deploy created
service/hpa-svc created
horizontalpodautoscaler.autoscaling/hpa-hpa created
動作確認
まずは平常時の Pod 数を確認します。
$ kubectl get po -n hpa-sample -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hpa-deploy-7d5f8bbb54-ds9gl 1/1 Running 0 38s 10.46.0.3 worker005 <none> <none>
deployment.yml
の Replicas
を 1 にしたので Pod が1つだけ動いています。
では実際にスケールさせてみましょう。
まずは Service を確認します。
kubectl get svc -n hpa-sample -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
hpa-svc LoadBalancer 10.106.97.142 10.0.0.201 80:31129/TCP 4m14s app=hpa-deploy
service.yml
で type: LoadBalancer
にしたので EXTERNAL-IP
に書かれている IP アドレスにアクセスします。
$ curl 10.0.0.201
<br />
<b>Fatal error</b>: Maximum execution time of 30 seconds exceeded in <b>/var/www/html/index.php</b> on line <b>5</b><br />
わざと30秒の制限に到達するようにしているのでエラーが出ます。
高負荷状態を作り出したので自動でスケールされているはずです。確認してみましょう。
$ kubectl get po -n hpa-sample -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hpa-deploy-7d5f8bbb54-6fw9w 1/1 Running 0 70s 10.33.128.5 worker014 <none> <none>
hpa-deploy-7d5f8bbb54-7lp8r 1/1 Running 0 100s 10.36.0.3 worker013 <none> <none>
hpa-deploy-7d5f8bbb54-9dq25 1/1 Running 0 70s 10.32.0.4 worker010 <none> <none>
hpa-deploy-7d5f8bbb54-dbqcd 1/1 Running 0 85s 10.40.0.4 worker012 <none> <none>
hpa-deploy-7d5f8bbb54-ds9gl 1/1 Running 0 8m15s 10.46.0.3 worker005 <none> <none>
hpa-deploy-7d5f8bbb54-g2wlj 1/1 Running 0 85s 10.38.0.4 worker011 <none> <none>
hpa-deploy-7d5f8bbb54-gv4kh 1/1 Running 0 85s 10.43.128.4 worker007 <none> <none>
hpa-deploy-7d5f8bbb54-ml9gv 1/1 Running 0 100s 10.41.128.4 worker003 <none> <none>
hpa-deploy-7d5f8bbb54-nkhp4 1/1 Running 0 100s 10.34.0.3 worker006 <none> <none>
hpa-deploy-7d5f8bbb54-tskwj 1/1 Running 0 85s 10.38.128.2 worker004 <none> <none>
hpa.yml
で書いた最大数まで Pod がスケールアウトされました。
このまま放置していると負荷がない状態が続くため、自動でスケールインされます。
$ kubectl get po -n hpa-sample -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hpa-deploy-7d5f8bbb54-ds9gl 1/1 Running 0 13m 10.46.0.3 worker005 <none> <none>
しばらく放置すると最小個数の 1 になりました。
まとめ
このように簡単に自動スケールさせることができます。これを使うことで Pod が落ちることによる機会損失や、無駄な Pod の管理に悩まされることは減らせるかもしれません。