# 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/