목차

Kubernetes HPA (Horizontal Pod Autoscaler)

  • 수평적 Pod 자동 조정기(scale-out)로 시스템의 가동 상황에 맞춰 시스템을 유연하게 확장 축소
  • CPU, Memory 사용량을 관찰하여 Deployment, ReplicaSet, StatefulSet의 Pod 개수를 자동 확장(DaemonSet 제외)
  • 컨트롤러는 관찰된 평균 CPU 사용률이 사용자가 지정한 대상과 일치하도록 Deployment에서 replicas 개수를 주기적으로 조정
  • 워크로드의 크기를 수요에 맞게 자동으로 스케일링하는 것이 목표
  • HPA 컨트롤러는 원하는(desired) Metric값과 현재(current) Metric값 사이의 비율로 작동
    • Metric값이 200m이고 원하는 값 100m 인경우 200.0/100.0 == 2.0 이므로 복제본 수가 두배가 됨
    • Metric값이 50m 이면 50.0/100.0==0.5이므로 복제본수를 반으로 줄임
    • 조정할 레플리카 갯수 = ceil [ 현재 레플리카 갯수 * ( 현재 Metric / 원하는 Metric) ]
    • 주로 Deployment에 연결하고, 옵션으로 resources를 반드시 포함해야한다.
  1. metric 수집
  2. metric server가 집계
  3. 수집한 정보(metric) APIserver에 전달
  4. APIserver가 HPA에 전달(Get Memory, CPU → default: 15sec)
  5. HPA가 Replicaset에 전달
  6. Replicaset이 scale 정보를 APIserver에 전달
  7. etcd에 기록, scheduler가 Pod 생성 node 지정
  8. Node kubelet이 scale 정보확인
  9. Pod 생성 / 축소 (scale in/out)
# 최신 정보 , https://github.com/kubernetes-sigs/metrics-server/releases/
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

#비활성화 상태
$ kubectl -n kube-system get deployments.apps metrics-server
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
metrics-server   0/1     1            0           96s

$ kubectl get apiservices | grep metrics
v1beta1.metrics.k8s.io                 kube-system/metrics-server   False (MissingEndpoints)   4m12s

#활성화
$ kubectl edit -n kube-system deployments.apps metrics-server
...
spec:
  containers:
  - args:
    - --cert-dir=/tmp
    - --secure-port=4443
    - --kubelet-insecure-tls  # 추가, 저장후 반영되기까지 시간 소요 약 20초 이상
...

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

$ kubectl -n kube-system get deployments.apps metrics-server
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
metrics-server   1/1     1            1           5m5s

#정보확인 kubectl top
$ kubectl top node
NAME         CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
k8s-master   273m         6%     5759Mi          73%
k8s-node1    139m         3%     3662Mi          46%
k8s-node2    152m         3%     3658Mi          46%

$ kubectl top po
cm-volume-pod                       0m           4Mi
cmtest-pod                          0m           7Mi
kubeshark-front-5d78866868-z5kq5    1m           4Mi
kubeshark-hub-697dfcbd8b-ktfv7      7m           22Mi
kubeshark-worker-daemon-set-crc7b   9m           114Mi
kubeshark-worker-daemon-set-l7lsh   10m          118Mi
kubeshark-worker-daemon-set-v2crv   10m          110Mi
nginx-app-pod                       0m           4Mi
openebs-pod                         0m           3Mi
$ kubectl create deployment hpa-test --image nginx --port 80 --replicas=2
deployment.apps/hpa-test created

$ kubectl expose deployment hpa-test --name hpa-test-svc --type NodePort --port 80 --target-port 80
service/hpa-test-svc exposed

$ kubectl edit deployment hpa-test
#아래의 내용 추가
...
spec:
  ...
  template:
  ...
    spec:
      containers:
      - image: nginx
        ...
        resources:
          requests:
            cpu: 10m
          limits:
            cpu: 20m

#확인
$ kubectl describe deployments.apps hpa-test
Name:                   hpa-test
Namespace:              default
CreationTimestamp:      Mon, 22 Apr 2024 13:46:18 +0900
Labels:                 app=hpa-test
Annotations:            deployment.kubernetes.io/revision: 2
Selector:               app=hpa-test
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=hpa-test
  Containers:
   nginx:
    Image:      nginx
    Port:       80/TCP
    Host Port:  0/TCP
    Limits:
      cpu:  20m
    Requests:
      cpu:        10m

$ kubectl get po,svc -o wide | grep hpa
pod/hpa-cpu50-deploy-85d5cf789-hdlh9    1/1     Running   0          8m25s   10.111.156.111   k8s-node1    <none>           <none>
pod/hpa-cpu50-deploy-85d5cf789-qr6w5    1/1     Running   0          8m25s   10.109.131.37    k8s-node2    <none>           <none>
pod/hpa-test-554d698b6d-4mwss           1/1     Running   0          84s     10.111.156.113   k8s-node1    <none>           <none>
pod/hpa-test-554d698b6d-9s6q5           1/1     Running   0          76s     10.109.131.39    k8s-node2    <none>           <none>
service/hpa-test-svc               NodePort    10.103.52.170   <none>        80:30746/TCP   3m43s   app=hpa-test

#curl yourNodeIP:NodePort
$ curl 10.10.10.91:30746
...

hpa.yaml

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  creationTimestamp: null
  name: hpa-test
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hpa-test
  targetCPUUtilizationPercentage: 50
status:
  currentReplicas: 0
  desiredReplicas: 0

수정된 hpa.yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  creationTimestamp: null
  name: hpa-test
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hpa-test
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
status:
  currentReplicas: 0
  desiredReplicas: 0
#hpa 생성
$ kubectl autoscale deployment hpa-test --cpu-percent 50 --min 1 --max 10 --dry-run=client -o yaml > hpa.yaml

$ kubectl api-resources | grep -i hpa
horizontalpodautoscalers          hpa          autoscaling/v2                         true         HorizontalPodAutoscaler

#hpa 수정 위의 내용 참조
$ vi hpa.yaml

#hpa 실행
$ kubectl apply -f hpa.yaml
horizontalpodautoscaler.autoscaling/hpa-test created

#부하 테스트 및 확인
#모니터링을 통해 레플리카가 증가하는 것 확인 가능
#워크로드 종료후 레플리카 감소 하는것 확인 가능

#추가 터미널 모니터링
$ kubectl get hpa -w
NAME       REFERENCE             TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
hpa-test   Deployment/hpa-test   0%/50%          1         10        2          15s
hpa-test   Deployment/hpa-test   35%/50%         1         10        2          60s
hpa-test   Deployment/hpa-test   55%/50%         1         10        2          75s
hpa-test   Deployment/hpa-test   55%/50%         1         10        3          90s
hpa-test   Deployment/hpa-test   40%/50%         1         10        3          105s
hpa-test   Deployment/hpa-test   36%/50%         1         10        3          2m
hpa-test   Deployment/hpa-test   33%/50%         1         10        3          3m1s
hpa-test   Deployment/hpa-test   36%/50%         1         10        3          3m16s

#추가2 대량 workload 수행
$ while true; do curl 10.10.10.91:30746; sleep 0.05; done