Post

Horizontal Pod Autoscaling 구성, 원리

공식문서 - https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/

Kubernetes의 Horizontal Pod Autoscaler (HPA)는 클러스터에서 실행 중인 애플리케이션의 스케일링을 자동화하는 메커니즘입니다. HPA는 CPU 사용률, 메모리 사용률 등 다양한 메트릭을 기반으로 필요에 따라 Pod의 수를 자동으로 조정합니다. 이를 통해 애플리케이션의 부하를 효과적으로 관리하고 리소스를 최적화할 수 있습니다.

작동 원리

Kubernetes에서 HPA는 특정 시간마다 Metrics Server를 통해 매트릭을 확인하고 Pods를 Auto Scaling합니다.

metrics.k8s.io 또는 custom.metrics.k8s.io 또는 external.metrics.k8s.io

실행 주기는 kube-controller-manager의 –horizontal-pod-autoscaler-sync-period 파라미터에 의해 설정됩니다. (기본 주기 = 15초)

시나리오

nginx 이미지를 사용해 1개의 Pods를 동작시키는 Deployment를 생성한다.
해당 Deployment의 Pods의 개수를 리소스 사용량에 따라 최소 1개, 최대 5개로 Auto Scaling 되도록 설정 후 테스트

1. Metrics Server 동작 확인

1
2
3
4
5
6
root@Zest ~# kubectl get pods -n kube-system
NAME                                      READY   STATUS    RESTARTS     AGE
calico-kube-controllers-796fb75cc-lr82z   1/1     Running   2 (9d ago)   9d
calico-node-z98m9                         1/1     Running   2 (9d ago)   9d
coredns-5986966c54-8hzs4                  1/1     Running   2 (9d ago)   9d
metrics-server-7c5c4b56bd-pb6t9           1/1     Running   0            12m

2. 테스트용 어플리케이션 배포

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hpa-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      run: nginx-hpa-deployment
  template:
    metadata:
      labels:
        run: nginx-hpa-deployment
    spec:
      containers:
      - name: nginx-hpa
        image: nginx
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"
          limits:
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-hpa-service
  labels:
    run: nginx-hpa-deployment
spec:
  ports:
  - port: 80
  selector:
    run: nginx-hpa-deployment

배포 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
root@Zest ~/Code/k8s-study/HPA(main)# kubectl apply -f pod-definition.yaml 
deployment.apps/nginx-hpa-deployment created
service/nginx-hpa-service created
root@Zest ~/Code/k8s-study/HPA(main)# kubectl get pods
NAME                                    READY   STATUS    RESTARTS   AGE
nginx-hpa-deployment-5754bc4859-9bc2v   1/1     Running   0          5s
root@Zest ~/Code/k8s-study/HPA(main)# kubectl get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes          ClusterIP   10.152.183.1     <none>        443/TCP   9d
nginx-hpa-service   ClusterIP   10.152.183.214   <none>        80/TCP    9s
root@Zest ~/Code/k8s-study/HPA(main)# kubectl get endpoints nginx-hpa-service 
NAME                ENDPOINTS        AGE
nginx-hpa-service   10.1.84.228:80   102s

3. HPA 생성

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-hpa-deployment
  minReplicas: 1
  maxReplicas: 5
  targetCPUUtilizationPercentage: 40

HPA 확인

1
2
3
4
5
6
7
root@Zest ~/Code/k8s-study/HPA(main)# kubectl apply -f hpa-definition.yaml 
horizontalpodautoscaler.autoscaling/nginx-hpa created

root@Zest ~/Code/k8s-study/HPA(main)# kubectl kubectl get hpa
root@Zest ~/Code/k8s-study/HPA(main)# kubectl get hpa
NAME        REFERENCE                         TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa   Deployment/nginx-hpa-deployment   cpu: 0%/40%   1         5         1          32s

4. 부하 발생

1
2
3
root@Zest ~# kubectl kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://nginx-hpa-service; done

Auto Scaling 확인 (Scale-up)

1
2
3
4
5
6
7
8
9
root@ip-10-0-0-241:~# kubectl get hpa
kNAME        REFERENCE                         TARGETS        MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa   Deployment/nginx-hpa-deployment   cpu: 42%/40%   1         5         3          10m
root@ip-10-0-0-241:~# kubectl get pods
NAME                                    READY   STATUS    RESTARTS   AGE
load-generator                          1/1     Running   0          5m11s
nginx-hpa-deployment-5754bc4859-56jcj   1/1     Running   0          2m40s
nginx-hpa-deployment-5754bc4859-9bc2v   1/1     Running   0          15m
nginx-hpa-deployment-5754bc4859-q2b9d   1/1     Running   0          2m25s

Auto Scaling 확인 (Scale-down)

1
2
3
4
5
6
7
8
9
10
11
12
root@ip-10-0-0-241:~# kubectl delete pod load-generator
pod "load-generator" deleted

root@Zest ~/Code/k8s-study/HPA(main)# kubectl get hpa
NAME        REFERENCE                         TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
nginx-hpa   Deployment/nginx-hpa-deployment   cpu: 0%/40%   1         5         3          17m

root@Zest ~/Code/k8s-study/HPA(main)# kubectl get pods
NAME                                    READY   STATUS        RESTARTS   AGE
nginx-hpa-deployment-5754bc4859-9bc2v   1/1     Running       0          21m
nginx-hpa-deployment-5754bc4859-j8vsl   0/1     Terminating   0          5m31s
nginx-hpa-deployment-5754bc4859-q2b9d   0/1     Terminating   0          8m47s

부하가 적어지자 pod가 종료되는 것을 확인할 수 있습니다.

5. 추가내용

load-generator를 종료해도 pod의 개수가 바로 줄어들진 않습니다. 이유는 안정화 기간 때문입니다. 기본 안정화 기간은 5분입니다. 안정화 기간이 설정되어 HPA는 Pod의 수를 급격히 줄이는 것을 방지합니다. HPA는 기본적으로 스케일 다운을 안정화하기 위해 일정 기간 동안 최소한의 변경만 허용합니다. 안정화 기간을 변경하기 위해서는 HPA를 생성할 때 다음과 같이 설정할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-hpa-deployment
  minReplicas: 1
  maxReplicas: 5
  targetCPUUtilizationPercentage: 40
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 60  # 안정화 기간을 60초로 설정
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60

궁금하신 점이나 추가해야할 부분은 댓글이나 아래의 링크를 통해 문의해주세요.
Written with KKam._.Ji

This post is licensed under CC BY 4.0 by the author.