kakakakakku blog

Weekly Tech Blog : Keep on Learning 👍

Vertical Pod Autoscaler の Recommender で「推奨値」のみを算出する

Kubernetes で VPA (Vertical Pod Autoscaler) を使うと,Pod に設定する CPU / Memory リクエスト値をオートスケールできる.CPU / Memory リクエスト値 (spec.containers[].resources.requests) に対する「スケールアップ」「スケールダウン」とも言える.今回は VPA を試していく.なお,VPA コンポーネントは Kubernetes Autoscaler の GitHub リポジトリに含まれている.

github.com

準備 1 : Kubernetes クラスターを構築する 🐳

今回は kind を使って,Mac 上に検証用の Kubernetes クラスターを構築する.以下のように v1.19.1 を使う.

$ kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.19.1) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Thanks for using kind! 😊

$ kubectl get nodes
NAME                 STATUS   ROLES    AGE    VERSION
kind-control-plane   Ready    master   100s   v1.19.1

準備 2 : Metrics Server をインストールする 🐳

構築した Kubernetes クラスターに Metrics Server をインストールする.基本的には GitHub リポジトリに載っている kubectl apply コマンドを使って components.yaml を適用する.

$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

しかし,Mac 上で Metrics Server 動かすために metrics-server の Deployment に kubelet 関連のオプションを追加しておく必要がある.少なくとも今回の環境では修正する必要があった.components.yaml を以下のように修正する.

(中略)

spec:
  serviceAccountName: metrics-server
  volumes:
  # mount in tmp so we can safely use from-scratch images and/or read-only containers
  - name: tmp-dir
    emptyDir: {}
  containers:
  - name: metrics-server
    image: k8s.gcr.io/metrics-server-amd64:v0.3.6
    imagePullPolicy: IfNotPresent
    args:
      - --cert-dir=/tmp
      - --secure-port=4443
+     - --kubelet-insecure-tls
+     - --kubelet-preferred-address-types=InternalIP

(中略)

修正した components.yamlkubectl apply コマンドで適用して,最終的に kubectl top node コマンドが実行できるようになっていれば,metrics-server はうまくインストールできている.

$ kubectl apply -f components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

$ kubectl top node

github.com

準備 3 : VPA (Vertical Pod Autoscaler) をインストールする 🐳

Kubernetes Autoscaler の GitHub リポジトリに VPA (Vertical Pod Autoscaler) をインストールするスクリプトが含まれているため,リポジトリを git clone しておく.そして vertical-pod-autoscaler/hack/vpa-up.sh を実行する.

$ cd vertical-pod-autoscaler
$ ./hack/vpa-up.sh

すると,以下のように CRD (Custom Resources Definition)Service AccountDeployment を確認できるようになる.

$ kubectl get crds
NAME                                                  CREATED AT
verticalpodautoscalercheckpoints.autoscaling.k8s.io   2021-01-18T06:00:00Z
verticalpodautoscalers.autoscaling.k8s.io             2021-01-18T06:00:00Z

$ kubectl get serviceaccounts -n kube-system | egrep 'NAME|vpa'
NAME                                 SECRETS   AGE
vpa-admission-controller             1         10m
vpa-recommender                      1         10m
vpa-updater                          1         10m

$ kubectl get deployments -n kube-system | egrep 'NAME|vpa'
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
vpa-admission-controller   1/1     1            1           11m
vpa-recommender            1/1     1            1           11m
vpa-updater                1/1     1            1           11m

$ kubectl get pods -n kube-system | egrep 'NAME|vpa'
NAME                                         READY   STATUS    RESTARTS   AGE
vpa-admission-controller-664b5997b7-4x7gx    1/1     Running   0          12m
vpa-recommender-5b768c88-nwhg6               1/1     Running   0          12m
vpa-updater-c9ffff655-vs8wt                  1/1     Running   0          12m

VPA (Vertical Pod Autoscaler) コンポーネント 🐳

VPA (Vertical Pod Autoscaler) を試す前にコンポーネントを整理しておく.大きく3種類ある.コンポーネント名から推測すると Updater によって Pod が再作成されそうだけど,実際には Admission Controller と組み合わせて再作成される.

  • Recommender : リソース消費を監視して CPU / Memory リクエスト値の推奨値を算出する
  • Updater : Pod を強制終了して再作成できるようにする
  • Admission Controller : 推奨値を適用した Pod を再作成する

kubernetes.io

VPA (Vertical Pod Autoscaler) を試す 🐳

同じく Kubernetes Autoscaler の GitHub リポジトリに公開されている Vertical Pod Autoscaler のサンプル hamster.yaml を使う.以下のようにマニフェストを適用すると,VerticalPodAutoscalerDeployment(アプリケーション用)が作成される.

$ cd vertical-pod-autoscaler
$ kubectl apply -f examples/hamster.yaml
verticalpodautoscaler.autoscaling.k8s.io/hamster-vpa created
deployment.apps/hamster created

ポイントは VerticalPodAutoscaler で CPU / Memory リクエスト値の minAllowedmaxAllowed を設定している点で,具体的なマニフェストは以下に載せておく.そして Deployment にも CPU / Memory リクエスト値を設定している.

  • VerticalPodAutoscaler(オートスケールする範囲値)
    • CPU : 100m ~ 1 (1000m)
    • Memory : 50Mi ~ 500Mi
  • Deployment(基本値)
    • CPU : 100m
    • Memory : 50Mi
apiVersion: "autoscaling.k8s.io/v1"
kind: VerticalPodAutoscaler
metadata:
  name: hamster-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: hamster
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: 100m
          memory: 50Mi
        maxAllowed:
          cpu: 1
          memory: 500Mi
        controlledResources: ["cpu", "memory"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hamster
spec:
  selector:
    matchLabels:
      app: hamster
  replicas: 2
  template:
    metadata:
      labels:
        app: hamster
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534 # nobody
      containers:
        - name: hamster
          image: k8s.gcr.io/ubuntu-slim:0.1
          resources:
            requests:
              cpu: 100m
              memory: 50Mi
          command: ["/bin/sh"]
          args:
            - "-c"
            - "while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done"

実際に Deployment によって作成された Pod のリクエスト値を確認すると,以下のようになっていた.Deployment に設定したリクエスト値よりも大きくなっている.VPA (Vertical Pod Autoscaler) によって「スケールアップ」されたと言える.

$ kubectl describe pods hamster-96d4585b7-qcb7b
Name:         hamster-96d4585b7-qcb7b
Namespace:    default
(中略)
Containers:
  hamster:
    Requests:
      cpu:        511m
      memory:     262144k
(中略)

VerticalPodAutoscaler に updatePolicy を設定する 🐳

VPA (Vertical Pod Autoscaler) には大きく3種類の updatePolicy がある.

  • Auto (Recreate) : Pod の作成時にリソースリクエストを割り当てて後でまた更新する(デフォルト)
  • Initial : Pod の作成時のみにリソースリクエストを割り当てる
  • Off : 推奨値の算出だけを行う

既に動作確認をしたデフォルト設定は Auto だけど,例えば updatePolicyOff を設定すれば,Recommender を使って推奨値を計算するけど,実際に Pod には反映しないという活用もできる.さっそく試していく.まず,以下のように VerticalPodAutoscaler のマニフェストを修正して updatePolicy を設定する.

apiVersion: "autoscaling.k8s.io/v1"
kind: VerticalPodAutoscaler
metadata:
  name: hamster-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: hamster
+ updatePolicy:
+   updateMode: "Off"
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: 100m
          memory: 50Mi
        maxAllowed:
          cpu: 1
          memory: 500Mi
        controlledResources: ["cpu", "memory"]

マニフェストを適用してから Deployment を再起動する.

$ cd vertical-pod-autoscaler
$ kubectl apply -f examples/hamster.yaml
verticalpodautoscaler.autoscaling.k8s.io/hamster-vpa configured
deployment.apps/hamster unchanged

$ kubectl rollout restart deployment hamster
deployment.apps/hamster restarted

すると,今度は Deployment に設定したリクエスト値のままになった.

$ kubectl describe pods hamster-66959c47bf-q54g4
Name:         hamster-96d4585b7-qcb7b
Namespace:    default
(中略)
Containers:
  hamster:
    Requests:
      cpu:        100m
      memory:     50Mi
(中略)

そして Recommender による推奨値を確認するために kubectl describe vpa コマンドを実行すると,期待通りに Recommendation として推奨値が算出されている.CPU / Memory リクエスト値のチューニングに使えて便利!

$ kubectl describe vpa hamster-vpa
Name:         hamster-vpa
Namespace:    default
(中略)
Status:
  Conditions:
    Last Transition Time:  2021-01-18T07:00:00Z
    Status:                True
    Type:                  RecommendationProvided
  Recommendation:
    Container Recommendations:
      Container Name:  hamster
      Lower Bound:
        Cpu:     415m
        Memory:  262144k
      Target:
        Cpu:     511m
        Memory:  262144k
      Uncapped Target:
        Cpu:     511m
        Memory:  262144k
      Upper Bound:
        Cpu:     1
        Memory:  371500k

Updater と Admission Controller を停止する 🐳

VPA (Vertical Pod Autoscaler) コンポーネント は疎結合に実装されているため,推奨値を算出するだけなら Recommender 以外は起動しなくても使える.実際に以下のように UpdaterAdmission Controller を削除して,同様に動作確認をしたら,問題なく kubectl describe vpa コマンドで推奨値を確認できた.

$ kubectl delete deployments vpa-updater -n kube-system
deployment.apps "vpa-updater" deleted

$ kubectl delete deployments vpa-admission-controller -n kube-system
deployment.apps "vpa-admission-controller" deleted

$ kubectl get deployments -n kube-system | egrep 'NAME|vpa'
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
vpa-recommender   1/1     1            1           60m

まとめ 🐳

Kubernetes で VPA (Vertical Pod Autoscaler) を使うと,Pod に設定する CPU / Memory リクエスト値をオートスケールできる.VPA (Vertical Pod Autoscaler) コンポーネントは大きく3種類あり,役割を理解しておくと良いと思う.また updatePolicyOff を設定すると,Recommender を使って推奨値を計算するけど,実際に Pod には反映しないという活用もできる.

github.com

関連記事 🐳

Kubernetes クラスターを構築した kind に関しては以下の記事にまとめてある.

kakakakakku.hatenablog.com