Closed7

KubernetesのHorizontal Pod Autoscalerを試してみるよ

RyuSARyuSA

こちらの機能を使って動作検証をするぞ
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

つまるところ「PodのリソースがカツカツになったらPodをスケールしてくれるリソース」なので、アクセス数がじんわり増えて行ったりする場合に自動的にスケールしてくれるようになる
※ 一通り検証を終えた後でまとめて追記してます

RyuSARyuSA

まずはHPAの対象とするPodを作成する、今回はDeploymentで管理していく
Podのイメージはお手製のeasy-podを使う。あれだ、デバッグ用のコンテナイメージだ
https://github.com/RyuSA/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
RyuSARyuSA

次に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って何故だ?
ちょっと調べてみる

RyuSARyuSA

これかな……?
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-metrics-apis

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

セットアップ良い感じ、あとは負荷をかけていこう

RyuSARyuSA

負荷試験ツールはk6で試してみよう
https://k6.io/docs/

まずはテスト内容を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
    });
};

ひたすらappServiceにアクセスしてもらうだけの設定、これを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

これで動くはず

RyuSARyuSA

負荷試験開始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側のオートスケーラーも必要になってきたりするのかな?サービスリリース前にしっかり検証しておかないとだめっすね

RyuSARyuSA

ということで、とりあえずHPAの機能に触れることができたのでおしまい

このスクラップは2021/01/23にクローズされました