[Kubernetes] HPA(Horizontal Pod Autoscaler)

이아영·2021년 5월 18일
0

Kubernetes

목록 보기
2/3

Hrizontal Pod Autoscaler는 지정한 메트릭을 관찰하여 부하 정도에 따라 Pod 개수를 자동으로 Scaling 한다.

이번 글에서는 CPU 사용률에 따라서 Pod의 개수가 자동으로 늘어났다 줄어들었다할 수 있도록 HPA를 세팅해 본다.

Metrics Server

HPAkubectl top 명령어를 사용하려면 클러스터에 metrics-server가 설치되어 있어야 한다.

다음 명령어를 통해 metrics-server를 설치한다.

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

설치 확인

$ kubectl get apiservices | grep metrics-server
v1beta1.metrics.k8s.io                 kube-system/metrics-server   True        3h23m

kubernetes-sigs/metrics-server


Pod 배포

이번 글에서 사용하는 api 코드의 일부이다.
cpu 부하를 주기위해 반복문을 사용했다.

app.get('/api/load-cpu', (req, res) => {
    let load = 0;
    for (let i = 0; i < 100000000; i++) {
        load += i;
    }
    res.json({load: load});
});

위 코드를 작성하고 도커 이미지를 만들어 ECR에 업로드하였다.
도커 이미지 : public.ecr.aws/p4g1u1f9/23724-k8s/api:13

Deployment에 도커 이미지를 지정하고 HPA 테스트를 위해 ServicenodePort 유형으로 생성해준다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-api
spec:
  selector:
    matchLabels:
      app: test-api
      tier: back
  template:
    metadata:
      labels:
        app: test-api
        tier: back
    spec:
      containers:
        - name: test-api
          image: public.ecr.aws/p4g1u1f9/23724-k8s/api:13
          ports:
          - containerPort: 8080
          resources:
            limits:
              cpu: 200m
              memory: 500Mi
            requests:
              cpu: 100m
              memory: 300Mi

---
apiVersion: v1
kind: Service
metadata:
  name: test-api
spec:
  type: NodePort
  selector:
    app: test-api
    tier: back
  ports:
    - port: 8080
      nodePort: 30000

Deployment.spec.replicas를 지정하지 않았기 때문에 기본으로 Pod 하나가 생성되었다.
아직은 api 호출을 하지 않았기 때문에 CPU0m이다.

$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-8f8fp   0m           29Mi

curl node-ip/nodePort 로 api 호출 테스트를 해보면 살짝 딜레이 후 response가 오는 것을 볼 수 있을 것이다.

$ curl 24.0.3.177:30000/api/load-cpu
{"load":4999999950000000}

이제 api를 무한으로 호출하는 쉘 스크립트를 작성한다. (load-cpu.sh)

#!/bin/bash

count=0

while :
do
	curl 24.0.3.177:30000/api/load-cpu > /dev/null 2>&1

	if [ `expr $count % 100` -eq 0 ]
	then
		echo $count
	fi
	((count++))
done

HPA

이제 HPA를 생성해보자.

명령어 또는 yaml을 정의하여 생성할 수 있는데 아래는 모두 cpu 사용량 50%를 기준으로 하여 Pod의 개수를 1부터 10 사이로 유지하는 Horizontal Pod Autoscaler를 의미한다.

  1. 명령어
$ kubectl autoscale deployment test-api --cpu-percent=50 --min=1 --max=10
  1. yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: test-api
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: test-api
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

명령어를 실행하거나 yaml 파일을 apply 해주면 HPA가 생성된다.

부하를 주기 전에 HPA를 조회해보면 기준 50%에 현재는 0%인 것을 볼 수 있다.

$ kubectl get hpa
NAME       REFERENCE             TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
test-api   Deployment/test-api   0%/50%    1         10        1          3m39s

위에서 작성한 load-cpu.sh을 실행시킨다.

$ ./load-cpu.sh &

얼마 지나지 않아 PodCPU 사용률을 조회해보면 201m으로 늘어나 있다.

$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-8f8fp   201m         29Mi

HPATARGETS를 보아도 알 수 있다.

$ kubectl get hpa
NAME       REFERENCE             TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
test-api   Deployment/test-api   201%/50%   1         10        1          4m27s

Pod를 조회해 보면 부하를 분산하기 위해 자동으로 3개의 Pod가 새로 생성되었다.

$ kubectl get po
NAME                        READY   STATUS    RESTARTS   AGE
test-api-7fc5955f97-4wcw8   1/1     Running   0          9s
test-api-7fc5955f97-8f8fp   1/1     Running   0          6m53s
test-api-7fc5955f97-8jbkr   1/1     Running   0          9s
test-api-7fc5955f97-qc4l4   1/1     Running   0          9s

실제로 CPU 사용률을 보면 여러 Pod들이 각각 부하를 분산하여 처리하는 것을 볼 수 있다.
(몇초 사이에 hr7cr이 추가로 생성되어 총 5개의 Pod가 됨)

$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-4wcw8   46m          28Mi
test-api-7fc5955f97-8f8fp   69m          29Mi
test-api-7fc5955f97-8jbkr   47m          28Mi
test-api-7fc5955f97-hr7cr   15m          29Mi
test-api-7fc5955f97-qc4l4   63m          29Mi
$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-4wcw8   74m          28Mi
test-api-7fc5955f97-8f8fp   0m           30Mi
test-api-7fc5955f97-8jbkr   34m          29Mi
test-api-7fc5955f97-hr7cr   39m          29Mi
test-api-7fc5955f97-qc4l4   19m          29Mi
$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-4wcw8   50m          29Mi
test-api-7fc5955f97-8f8fp   0m           29Mi
test-api-7fc5955f97-8jbkr   0m           29Mi
test-api-7fc5955f97-hr7cr   53m          29Mi
test-api-7fc5955f97-qc4l4   77m          29Mi
$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-4wcw8   57m          28Mi
test-api-7fc5955f97-8f8fp   33m          29Mi
test-api-7fc5955f97-8jbkr   36m          29Mi
test-api-7fc5955f97-hr7cr   39m          29Mi
test-api-7fc5955f97-qc4l4   73m          29Mi

이제 쉘 스크립트를 종료한다.

$ fg
./load-cpu.sh
^C

모든 PodCPU 사용률이 내려갔다.

$ kubectl top po
NAME                        CPU(cores)   MEMORY(bytes)
test-api-7fc5955f97-4wcw8   0m           29Mi
test-api-7fc5955f97-8f8fp   0m           29Mi
test-api-7fc5955f97-8jbkr   0m           29Mi
test-api-7fc5955f97-hr7cr   0m           29Mi
test-api-7fc5955f97-qc4l4   0m           29Mi

시간이 지나고 다시 Pod가 1개로 줄어들었다.

$ kubectl get po
NAME                        READY   STATUS    RESTARTS   AGE
test-api-7fc5955f97-8f8fp   1/1     Running   0          20m

참고

0개의 댓글