---
# System prepended metadata

title: Kubernetes VPA(Vertical Pod Autoscaler)
tags: [K8S]

---

# Kubernetes VPA(Vertical Pod Autoscaler)

* 可以縮小過度資源請求的 pod，也可以根據使用情況隨時提升資源不足的 pod。
* 根據 pod 目前的資源使用情況和過去的資源使用情況，計算可能的未來資源使用量。
* HPA 是水平擴充，而 VPA 是垂直擴充。
* VPA 無法與 HPA 同時使用。
* VPA 不會刪除沒有在副本數控管的 pod。
* VPA 需要透過 Metrics Server 來監控 pod 的資源使用量。
* VPA 是 Kubernetes 中一項強大的功能，可以幫助用戶更有效地利用集群資源，提高應用的性能和可靠性。


## 實作
* 安裝 vpa
```
$ helm repo add cowboysysop https://cowboysysop.github.io/charts/

$ helm -n kube-system install vertical-pod-autoscaler cowboysysop/vertical-pod-autoscaler
```

* VPA pod 檢查
```
$ kubectl -n kube-system get pod -l app.kubernetes.io/name=vertical-pod-autoscaler
NAME                                                            READY   STATUS    RESTARTS   AGE
vertical-pod-autoscaler-admission-controller-65c49ccbbf-g4lpd   1/1     Running   0          35s
vertical-pod-autoscaler-recommender-7f56cbf565-b88qh            1/1     Running   0          35s
vertical-pod-autoscaler-updater-559fff9df-z5fhp                 1/1     Running   0          35s
```


* 建立測試用 deploy，資源要求 CPU `100m`，記憶體 `50Mi`
```
$ vim deploy.yaml
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: registry.k8s.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"
            
```
```
$ kubectl apply -f deploy.yaml

$ kubectl top pod
NAME                       CPU(cores)   MEMORY(bytes)
hamster-59cc68d575-j96f6   493m         0Mi
hamster-59cc68d575-wsxgb   504m         0Mi
```
* 建立 VPA 
```
$ vim vpa.yaml
apiVersion: "autoscaling.k8s.io/v1"
kind: VerticalPodAutoscaler
metadata:
  name: hamster-vpa
spec:
  # recommenders field can be unset when using the default recommender.
  # When using an alternative recommender, the alternative recommender's name
  # can be specified as the following in a list.
  # recommenders: 
  #   - name: 'alternative'
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: hamster
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: 100m
          memory: 50Mi
        maxAllowed:
          cpu: 1
          memory: 500Mi
        controlledResources: ["cpu", "memory"]
        
```
* 原本的 pod 經過資源調整後，pod 會被砍掉重建
```
$ kubectl apply -f vpa.yaml
verticalpodautoscaler.autoscaling.k8s.io/hamster-vpa created

$ kubectl get vpa
NAME          MODE   CPU    MEM       PROVIDED   AGE
hamster-vpa   Auto   587m   262144k   True       18s

$ kubectl get po
NAME                       READY   STATUS        RESTARTS   AGE
hamster-59cc68d575-j96f6   1/1     Terminating   0          4m2s
hamster-59cc68d575-ndb54   1/1     Running       0          18s
hamster-59cc68d575-nf8zs   1/1     Running       0          78s

$ kubectl top po
NAME                       CPU(cores)   MEMORY(bytes)
hamster-59cc68d575-ndb54   499m         0Mi
hamster-59cc68d575-nf8zs   499m         0Mi
```

* 經過 VPA 的修改，CPU 被改成 `587m`，記憶改成 `262144k`
```
$ kubectl get pod hamster-59cc68d575-ndb54 -o yaml
......
spec:
  containers:
  - args:
    - -c
    - while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done
    command:
    - /bin/sh
    image: registry.k8s.io/ubuntu-slim:0.1
    imagePullPolicy: IfNotPresent
    name: hamster
    resources:
      requests:
        cpu: 587m
        memory: 262144k
.......
```
* 環境復原
```
$ kubectl delete -f deploy.yaml
$ kubectl delete -f vpa.yaml
```

## 驗證資源如果一開始開太高，是否會自動下修
* 設定資源 CPU `1000m`，記憶體 `1000Mi`
```
$ vim deploy2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hamster
spec:
  selector:
    matchLabels:
      app: hamster
  replicas: 2
  template:
    metadata:
      labels:
        app: hamster
    spec:
      containers:
        - name: hamster
          image: nginx
          resources:
            requests:
              cpu: 1000m
              memory: 1000Mi
```
```
$ kubectl apply2 -f deploy.yaml
deployment.apps/hamster created

$ kubectl top pod
NAME                       CPU(cores)   MEMORY(bytes)
hamster-68877945fb-794hx   0m           4Mi
hamster-68877945fb-rhdq8   0m           5Mi
```

```
$ vim vpa2.yaml
apiVersion: "autoscaling.k8s.io/v1"
kind: VerticalPodAutoscaler
metadata:
  name: hamster-vpa
spec:
  # recommenders field can be unset when using the default recommender.
  # When using an alternative recommender, the alternative recommender's name
  # can be specified as the following in a list.
  # recommenders: 
  #   - name: 'alternative'
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: hamster
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: 10m
          memory: 50Mi
        maxAllowed:
          cpu: 200m
          memory: 100Mi
        controlledResources: ["cpu", "memory"]
        
$ kubectl apply -f vpa2.yaml
```

```
$ kubectl get vpa
NAME          MODE   CPU    MEM     PROVIDED   AGE
hamster-vpa   Auto   200m   100Mi   True       78s

$ kubectl get po
NAME                       READY   STATUS    RESTARTS   AGE
hamster-68877945fb-mkhzh   1/1     Running   0          54s
hamster-68877945fb-ncfmx   1/1     Running   0          8s
```
* 已修改為 CPU `200m`，記憶體 `100Mi`
```
$ kubectl get po hamster-68877945fb-mkhzh -o yaml
......
spec:
  containers:
  - image: nginx
    imagePullPolicy: Always
    name: hamster
    resources:
      requests:
        cpu: 200m
        memory: 100Mi
.....
```
* 環境復原
```
$ kubectl delete -f deploy2.yaml
$ kubectl delete -f vpa2.yaml
```

## 參考連結
https://medium.com/@seifeddinerajhi/kubernetes-autoscaling-achieving-scalability-and-efficiency-e0230cf6013

https://www.lixueduan.com/posts/kubernetes/12-vpa/