KubernetesのHorizontal Pod Autoscalerを試してみるよ
こちらの機能を使って動作検証をするぞ
つまるところ「PodのリソースがカツカツになったらPodをスケールしてくれるリソース」なので、アクセス数がじんわり増えて行ったりする場合に自動的にスケールしてくれるようになる
※ 一通り検証を終えた後でまとめて追記してます
まずはHPAの対象とするPodを作成する、今回はDeploymentで管理していく
Podのイメージはお手製のeasy-podを使う。あれだ、デバッグ用のコンテナイメージだ
Deploymentのマニフェストはこんな感じ、HPAでメモリの使用率が要求されるので一応CPU使用率も設定した
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: app
name: app
spec:
replicas: 1
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- image: ryusa/easy-pod
name: easy-pod
ports:
- containerPort: 8080
resources:
limits:
cpu: 50m
これでDeploymentを作成する
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl create -f deployment.yaml
deployment.apps/app created
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
app-84777f57dd-pxrck 0/1 ContainerCreating 0 5s
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl expose deployment app
service/app exposed
次にHPAをデプロイする、先のDeploymentのコンテナリソースのCPU使用率は50%を超えるようだったら増やしてくれるはず……はず
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 50
これをデプロイ!
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl create -f hpa.yaml
horizontalpodautoscaler.autoscaling/app-hpa created
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
app-hpa Deployment/app <unknown>/50% 1 5 0 6s
おん??unknownって何故だ?
ちょっと調べてみる
これかな……?
metrics-server
が提供するmetrics.k8s.io
APIが必要らしい、そういえばこのクラスタにデプロイしていなかったな……
ということでHelmでエイヤってデプロイ
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" already exists with the same configuration, skipping
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "k8ssandra" chart repository
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ helm install metrics-server bitnami/metrics-server -n kube-system --set apiService.create=true --set extraArgs.kubelet-insecure-tls=true
W0123 18:10:28.810818 26447 warnings.go:67] apiregistration.k8s.io/v1beta1 APIService is deprecated in v1.19+, unavailable in v1.22+; use apiregistration.k8s.io/v1 APIService
W0123 18:10:29.079371 26447 warnings.go:67] apiregistration.k8s.io/v1beta1 APIService is deprecated in v1.19+, unavailable in v1.22+; use apiregistration.k8s.io/v1 APIService
NAME: metrics-server
...
めっちゃWARN出てわろた
Docker Desktop for MacのKubernetesなので、tlsの検証設定をオフにしておいた
これで動作どうだろう?
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
app-hpa Deployment/app 1%/50% 1 5 1 14m
セットアップ良い感じ、あとは負荷をかけていこう
負荷試験ツールはk6で試してみよう
まずはテスト内容をjsで書いておく
import { check } from "k6";
import http from "k6/http";
export default function () {
let res = http.get("http://app:8080/pod/ipaddr");
check(res, {
"is status 200": (r) => r.status === 200
});
};
ひたすらapp
Serviceにアクセスしてもらうだけの設定、これをconfigmapに落とし込んでPodに食べてもらいましょうか
apiVersion: v1
kind: Pod
metadata:
labels:
run: k6
name: k6
spec:
containers:
- image: loadimpact/k6
name: k6
args:
- "run"
- "--vus"
- "10"
- "--duration"
- "5m"
- "/home/k6/mnt/code.js"
resources:
limits:
cpu: "1"
memory: "256m"
volumeMounts:
- name: code
mountPath: /home/k6/mnt
volumes:
- name: code
configMap:
name: "code.js"
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl create configmap code.js --from-file ./code.js
configmap/code.js created
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl create -f k6.yaml
pod/k6 created
これで動くはず
負荷試験開始30秒程度でこんな感じに
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl top pod app-84777f57dd-kfmrm
NAME CPU(cores) MEMORY(bytes)
app-84777f57dd-kfmrm 459m 58Mi
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl get pods -w
NAME READY STATUS RESTARTS AGE
app-84777f57dd-pxrck 1/1 Running 0 28m
k6 1/1 Running 0 59s
app-84777f57dd-kfmrm 0/1 Pending 0 0s
app-84777f57dd-kfmrm 0/1 Pending 0 0s
app-84777f57dd-kfmrm 0/1 ContainerCreating 0 0s
app-84777f57dd-kfmrm 1/1 Running 0 6s
おぉ〜、良い感じにスケールしていってる!
……と思ったらこれ以上Podがスケールしなくなった、なぜ?
ryusa at Medusa in ~/develop/github.com/ryusa/temp
$ kubectl describe pod app-84777f57dd-spxnw
Name: app-84777f57dd-spxnw
Namespace: default
Priority: 0
Node: <none>
Annotations: <none>
Status: Pending
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 2m2s 0/1 nodes are available: 1 Insufficient cpu.
Warning FailedScheduling 2m2s 0/1 nodes are available: 1 Insufficient cpu.
あっ、ノード側のCPUが足りなくなってしまったか……そうかそりゃこうなるよね
となるとNode側のオートスケーラーも必要になってきたりするのかな?サービスリリース前にしっかり検証しておかないとだめっすね
ということで、とりあえずHPAの機能に触れることができたのでおしまい