Horizontal Pod Autoscaling & Vertical Pod Autoscaling

ကျွန်တော်ဒီနေ့ ရေးမယ့်အကြောင်းအရာကတော့ kubernetes ပေါ်မှာရှိတဲ့ pod တွေကို autoscaling လုပ်နည်းပဲဖြစ်ပါတယ်။ ကျွန်တော်တို့ production အတွက် deployment တွေ လုပ်တဲ့အခါ pod template ထဲမှာ resources အ တွက် cpu နဲ့ memory တွေကို request ၊ limit ပမာဏတွေသတ်မှတ်ပေးပြီး resource quota တွေကိုကန့်သတ်ပေးထားပါတယ်။ အဲ့ဒီအခါမှသာ pod တစ်ခုထဲက node ရဲ့ cpu memory resource တွေကို သူတစ်ခုထဲအတွက် သုံးတာကို ကာကွယ်နိုင်ပါမယ်။ pod တွေ deployment တွေ create တဲ့အခါ quota မှာ request ဆိုတာက သတ်မှတ်ထားတဲ့ amount ကိုပေးနိုင်တဲ့ node အပေါ်မှာသာ pod တွေကို deploy လုပ်ပေးမှာဖြစ်ပြီး limit က အဲ့ amount အထိသာ pod အတွက် resource ကိုပေးသုံးမှာဖြစ်ပါတယ်။

Prequities

kubernetes cluster

Prepare A Kubernetes Cluster

autoscaling တွေစမ်းဖို့အတွက် kubernetes cluster တစ်ခု create ပေးရပါမယ်။ ကျွန်တော်ကတော့ aks cluster တစ်ခု create လုပ်လိုက်ပါမယ်။

az group create --name kube --location eastus
az aks create --name demo -g kube --location eastus --node-count 2
az aks get-credentials --name demo -g kube

ပြီးသွားရင်တော့ kubectl get nodes နဲ့ကြည့်လိုက်ပါမယ်။ node တွေ ready ဖြစ်နေရင် autoscaling အကြောင်းကို စစမ်းလို့ရပါပြီ။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get nodes 
NAME                                STATUS    ROLES     AGE       VERSION
aks-nodepool1-23943392-vmss000000   Ready     agent     100s      v1.19.11
aks-nodepool1-23943392-vmss000001   Ready     agent     99s       v1.19.11

Horizontal Pod Autoscaling

HPA ဆိုတာက pod တွေရဲ့ replicas အရေအတွက်ကို autoscale လုပ်ပေးတာဖြစ်ပါတယ်။ ကျွန်တော်တို့သတ်မှတ်ခဲ့တဲ့ resource quota ရဲ့ request cpu ၊ memory utilization တွေအပေါ်မူတည်ပြီး pods တွေကို scale in ၊ scale out လုပ်ပေးတာဖြစ်ပါတယ်။ အရင်ဆုံး pod တွေ nodes တွေရဲ့ resource utilization ကိုသိဖို့ဆို metric-server ကို deploy လုပ်ပေးရပါမယ်။ aks မှာတော့ default သွင်းထားပြီးသားဖြစ်ပါတယ်။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get pods --all-namespaces
NAMESPACE     NAME                                  READY     STATUS    RESTARTS   AGE
kube-system   azure-ip-masq-agent-7rhvx             1/1       Running   0          12m
kube-system   azure-ip-masq-agent-xjcsb             1/1       Running   0          12m
kube-system   coredns-76c97c8599-fgqfj              1/1       Running   0          12m
kube-system   coredns-76c97c8599-qr92j              1/1       Running   0          13m
kube-system   coredns-autoscaler-599949fd86-45twt   1/1       Running   0          13m
kube-system   kube-proxy-ljdnx                      1/1       Running   0          12m
kube-system   kube-proxy-wp6b7                      1/1       Running   0          12m
kube-system   metrics-server-77c8679d7d-vk8n8       1/1       Running   0          13m
kube-system   tunnelfront-544cd5b988-cshrh          1/1       Running   0          13m

HPA ကို စမ်းဖို့ဆို autoscale လုပ်ချင်တဲ့ deployment ကို resource quota တွေသတ်မှတ်ပေးဖို့လိုပါတယ်။ ပထမဆုံးအနေနဲ့ demo ဆိုတော့ nginx deployment တစ်ခုနဲ့ပဲစမ်းကြည့်ကြမယ်။ ဘာ deployment မှမလုပ်ခင် nodes တွေရဲ့ cpu memory usage ပဲဖြစ်ပါတယ်။

thaunghtikeoo@thaunghtikeoo:~$ kubectl top nodes
NAME                                CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%   
aks-nodepool1-23943392-vmss000000   50m          2%        673Mi           14%       
aks-nodepool1-23943392-vmss000001   129m         6%        651Mi           14%      

nginx deployment တစ်ခုကို create ပါမယ်။ cpu 250m ကို request ထားပြီး 500m အထိ limit ပေးထားပါတယ်။ ပြီးရင် kubectl create နဲ့ deployment ကို create လိုက်ပါ။

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 250m
          limits:
            cpu: 500m  

ပြီးရင်တော့ default namespace မှာ nginx deployment တစ်ခု run နေတာကိုတွေ့ရမှာဖြစ်ပါတယ်။

haunghtikeoo@thaunghtikeoo:~$ kubectl get all 
NAME                        READY     STATUS    RESTARTS   AGE
pod/nginx-fdb6cfbc5-fwggl   1/1       Running   0          32s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   29m

NAME                    READY     UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1       1            1           33s

NAME                              DESIRED   CURRENT   READY     AGE
replicaset.apps/nginx-fdb6cfbc5   1         1         1         34s

အခုချိန်မှာ pod ရဲ့ cpu usage က 0% ဖြစ်နေပါတယ်။ ဒါဆိုအခု hpa ကိုစစမ်းကြည့်ပါမယ်။ အောက်က yaml file ကိုကြည့်ပါ။ request ထားတဲ့ 250m ရဲ့ 50% အထိ pod က cpu utilization တက်လာတဲ့အခါ pod ကို maximum 5 ခုအထိ scale out လုပ်မှာဖြစ်ပြီး cpu usage ပြန်ကျသွားရင်တော့ minimun 1 ခုအဖြစ်ပြန် scale in လုပ်လိုက်မှာဖြစ်ပါတယ်။

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: nginx
spec:
  maxReplicas: 5
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  targetCPUUtilizationPercentage: 50

kubectl apply နဲ့ create လိုက်ပါမယ်။ အခုချိန်မှာ cpu က သုညပဲဖြစ်နေပါသေးတယ်။ kubectl cmd နဲ့ လည်း hpa ကို အောက်ပါအတိုင်း create နိုင်ပါသေးတယ်။

kubectl autoscale deployment nginx --cpu-percent=50 --min=1 --max=5
thaunghtikeoo@thaunghtikeoo:~$ kubectl get hpa
NAME      REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
nginx     Deployment/nginx   0%/50%    1         5         1          2m44s

ကျွန်တော်တို့ nginx service ကို အပြင်ကခေါ်လို့ရအောင် loadbalancer အနေနဲ့ expose လိုက်ပါမယ်။

kubectl expose deploy nginx --type LoadBalancer --target-port 80 --port 80

thaunghtikeoo@thaunghtikeoo:~$ kubectl get svc
NAME         TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)        AGE
kubernetes   ClusterIP      10.0.0.1      <none>         443/TCP        40m
nginx        LoadBalancer   10.0.36.206   20.72.185.88   80:31934/TCP   7s

ပြီးသွားရင်တော့ cpu overload ဖြစ်အောင် test ဖို့အတွက် siege tool ကို install ပေးရပါမယ်။

apt update -y && apt install siege -y

ဒါဆိုရင်ကျွန်တော်တို့ nginx deployment က pods တွေကို cpu usage တက်လာအောင် အောက်ကအတိုင်းစမ်းပါမယ်။ nginx service url ကို 2 minute အထိ cpu တက်အောင်လုပ်လိုက်ပါမယ်။

siege -q -c 5 -t 2m 20.72.185.88

ခဏကြာတော့ cpu load ဖြစ်လာပြီး hpa မှာ percent တွေတက်လာပြီး replicas တွေ scale out ဖြစ်လာပါပြီ။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get hpa
NAME      REFERENCE          TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
nginx     Deployment/nginx   110%/50%   1         5         4          2m14s

အသစ်ထွက်လာတဲ့ pods တွေကလည်းတစ်ခုပြီး တစ်ခု CPU usage တွေတက်လာပြီး နောက်ဆုံးမှာ maximum သတ်မှတ်ခဲ့တဲ့ 5 ခုအထိ တိုးသွားပါတယ်။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get pods
NAME                    READY     STATUS    RESTARTS   AGE
nginx-fdb6cfbc5-2dvxg   1/1       Running   0          6m55s
nginx-fdb6cfbc5-9cjn7   1/1       Running   0          16s
nginx-fdb6cfbc5-h8h85   1/1       Running   0          16s
nginx-fdb6cfbc5-lmfdw   1/1       Running   0          16s
nginx-fdb6cfbc5-8cvtq   1/1       Running   0          16s
thaunghtikeoo@thaunghtikeoo:~$ kubectl top pods
NAME                    CPU(cores)   MEMORY(bytes)   
nginx-fdb6cfbc5-2dvxg   178m           11Mi            
nginx-fdb6cfbc5-8cvtq   180m           9Mi             
nginx-fdb6cfbc5-9cjn7   177m           10Mi            
nginx-fdb6cfbc5-h8h85   169m           9Mi             
nginx-fdb6cfbc5-lmfdw   180m           10Mi      

၂ မိနစ်ပြည့်တဲ့အခါ siege ကအချိန်ပြည့်သွားပြီး cpu loading ကို ရပ်လိုက်ပါတယ်။ အောက်မှာကြည့်ကြည့်ပါ။

thaunghtikeoo@thaunghtikeoo:~$ kubectl top pods
NAME                    CPU(cores)   MEMORY(bytes)   
nginx-fdb6cfbc5-2dvxg   0m           11Mi            
nginx-fdb6cfbc5-8cvtq   0m           9Mi             
nginx-fdb6cfbc5-9cjn7   0m           10Mi            
nginx-fdb6cfbc5-h8h85   0m           9Mi             
nginx-fdb6cfbc5-lmfdw   0m           10Mi      

CPU usage တွေပြန်ကျသွားတော့ hpa က 0% ပြန်ဖြစ်သွားပြီး minimum သတ်မှတ်ခဲ့တဲ့ pod တစ်ခုကိုပဲ ထားခဲ့ပြီးကျန်တာအကုန် terminated လိုက်ပါတယ်။ ဒါကတော့ hpa (သို့) horizontal pod autoscaling အကြောင်းကိုကျွန်တော်နားလည်သလောက်ရေးလိုက်တာပါ။

Vertical Pod Autoscaler

vpa ဆိုတာက ကျွန်တော်တို့ရဲ့ pod တွေအတွက် resource quota တွေကို vpa ကနေ စဥ်းစားပေးတာဖြစ်ပြီး autoscale လုပ်ပေးသွားတာပါ။ vpa က hpa တုန်းကလို scale in ၊ scale out လုပ်တာမျိုးမဟုတ်ပဲ မှန်ကန်တဲ့ resource usage ကိုသူကိုယ်တိုင် ဆုံးဖြတ်ပြီး old pod တွေကို evict ပြီး new instance တွေကို create လုပ်ပေးတာပါ။ ဒါဆို vpa ကိုစမ်းဖို့ vpa ကို အရင် install လုပ်ပေးရပါမယ်။

git clone https://github.com/kubernetes/autoscaler.git
./autoscaler/vertical-pod-autoscaler/hack/vpa-up.sh

vpa install ပြီးရင် hpa တုန်းကလိုပဲ deployment တစ်ခု create လိုက်ပါမယ်။ cpu request က 100m ဖြစ်ပြီး memory request က 50Mi ဖြစ်ပါတယ်။ kubectl create နဲ့ create လိုက်ပါမယ်။

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-auto-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-auto-deployment
  template:
    metadata:
      labels:
        app: my-auto-deployment
    spec:
      containers:
      - name: my-container
        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 တစ်ခုရလာပါပြီ။ kubectl get နဲ့ တစ်ချက်ကြည့်ပါ။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get all
NAME                                     READY     STATUS    RESTARTS   AGE
pod/my-auto-deployment-9bf598bdb-jt2v6   1/1       Running   0          11s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   2m23s

NAME                                 READY     UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-auto-deployment   1/1       1            1           14s

NAME                                           DESIRED   CURRENT   READY     AGE
replicaset.apps/my-auto-deployment-9bf598bdb   1         1         1         14s

ပြီးရင် vpa တစ်ခုကို create ကြည့်ပါမယ်။ vpa က deployment အတွက် မှန်ကန်တဲ့ resource usage ကို recommend ပေးပြီး update mode ‘auto’ ပေးထားတဲ့အတွက် autoscale ဖြစ်သွားတာပါ။ vpa ကိုအောက်ကလို kubectl create နဲ့ create လိုက်ပါ။

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-vpa
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind:       Deployment
    name:       my-auto-deployment
  updatePolicy:
    updateMode: "Auto"

ခဏကြာတော့ vpa တစ်ခုထွက်လာပါပြီ။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get vpa
NAME      MODE      CPU       MEM       PROVIDED   AGE
my-vpa    Auto      587m      262144k   True       32s

kubectl describe နဲ့ ကြည့်တဲ့အခါ events မှာ vpa ကနေ deployment အတွက် recommend ပေးတဲ့ resource ကိုအခုလိုတွေ့ရမှာဖြစ်ပါတယ်။

Status:
  Conditions:
    Last Transition Time:  2021-07-15T17:03:14Z
    Status:                True
    Type:                  RecommendationProvided
  Recommendation:
    Container Recommendations:
      Container Name:  my-container
      Lower Bound:
        Cpu:     86m
        Memory:  262144k
      Target:
        Cpu:     587m
        Memory:  262144k
      Uncapped Target:
        Cpu:     587m
        Memory:  262144k
      Upper Bound:
        Cpu:     939787m
        Memory:  18411500k
Events:          <none>

lower bound က request ကိုပြောတာဖြစ်ပြီး upper က limit ကိုပြောတာပါ။ Target က pod ကောင်းမွန်စွာအလုပ်လုပ်နိုင်မယ့် ပမာဏကိုတွက်ချက်ပြီး ထုတ်ပေးလိုက်တာပါ။ အနည်းဆုံး cpu request က 587m ရှိရမှာပါ။ ကျွန်တော်အရင်က 100m ကိုသာ request ခဲ့ပါတယ်။ ဒါကြောင့် pod ကို terminated ပြီး Target resource နဲ့ pod အသစ်တစ်ခုအောက်ကလိုထွက်လာမှာပါ။ မိနစ် အနည်းငယ်ကြာတဲ့အခါ အရင်ရှိတဲ့ pod က terminate ဖြစ်ပြီး pod အသစ်တစ်ခု running ဖြစ်နေတာကိုတွေ့ရပါလိမ့်မယ်။

thaunghtikeoo@thaunghtikeoo:~$ kubectl get pods
NAME                                 READY     STATUS        RESTARTS   AGE
my-auto-deployment-9bf598bdb-kqp7n   1/1       Running       0          15s
my-auto-deployment-9bf598bdb-lxzhw   1/1       Terminating   0          3m10s

pod အသစ်ကို kubectl describe နဲ့ ကြည့်လိုက်ရင် cpu နဲ့ memory request ကိုအောက်ပါအတိုင်းပဲတွေ့ရမှာပါ။

    State:          Running
      Started:      Thu, 15 Jul 2021 23:35:14 +0630
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        587m
      memory:     262144k
    Environment:  <none>
    Mounts:

ဒါဆိုရင် vertical pod autoscaling အကြောင်းကလည်းဒီလောက်ပါပဲ။ deployment တွေအတွက်မှန်ကန်တဲ့ resource amount ကို vpa ကိုသုံးပြီး သတ်မှတ်ပေးနိုင်ပါတယ်။ အားလုံးကိုကျေးဇူးတင်ပါတယ်ခင်ဗျာ။

Thanks for reading …