KUBERNETES

07. 파드 오토스케일링 – Metrics-Server & HPA

이번 장은 파드 오토스케일링을 알아봅니다. 실습을 통하여 세부 설정을 확인해 보고 실제 운영 환경 적용 시 어떠한 부분을 고려해야 하는지 알아보겠습니다.

오토스케일링(Autoscaling)이란 시스템의 부하 또는 수요에 따라 자동으로 리소스를 확장하거나 축소하여 애플리케이션의 성능과 서비스 가용성을 유지하는 기능입니다. 이는 클라우드 환경에서 주로 사용되며, 자동화된 방식으로 애플리케이션 및 인프라스트럭처의 확장을 관리합니다.

쿠버네티스는 크게 파드와 노드의 오토스케일링이 가능합니다. 파드는 주로 HPA(Horizontal Pod Autoscaler)를 이용하여 자동으로 파드의 수를 수평(Horizontal)으로 증가하고 감소합니다. 노드는 Cluster Autoscaler와 Karpneter를 이용하여 파드가 실행되는 노드의 수량을 변경할 수 있습니다. 

주요 내용

  • AutoScaling의 이해
  • Metrics-Server를 이용한 노드, 파드의 자원 사용량 모니터링 

사용자 부하 증가, 감소에 따른 자동으로 파드의 증가, 감소를 수행하는 오케스케일링(HPA) 이해

실습 과제

  • Metrics-Server 설치
  • 파드 오케스케일링(HPA) 실습

이번 장에 사용하는 소스 파일의 깃헙 디렉토리입니다.

1. Autoscaling의 주요 요소

그럼 간단히 오토스케일링을 설정하기 위한 주요 구성 요소를 알아봅니다.

. 모니터링: 오토스케일링은 시스템의 부하를 기준으로 수량을 증가하고 감소합니다. 시스템의 부하를 측정하기 위한 모니터링 솔루션이 필요합니다. 주로 CPU 사용량, 메모리 사용량, 네트워크 트래픽 등과 같은 메트릭을 수집하여 시스템의 현재 상태를 파악합니다.

. 조정 기준 설정: 사용자는 오토스케일링을 위한 조정 기준을 설정합니다. 예를 들어, CPU 사용량이 설정한 임계값을 초과하면 리소스를 확장하고, 설정한 임계값 아래로 내려가면 리소스를 축소하는 방식으로 특정한 조정 기준을 설정합니다. 임계값에 따른 반응 시간 역시 조정할 수 있습니다. 예를 들어 CPU 사용량이 감소하였다가 다시 증가하는 변화가 자주 발생하는 경우 잦은 변동을 방지하기 위하여 Scaling Down 안정화 시간을 5분 등으로 지정할 수 있습니다.

. 스케일링 정책: 오토스케일링은 다양한 스케일링 정책을 지원합니다. 주로 수직 스케일링(Vertical Scaling)과 수평 스케일링(Horizontal Scaling)을 사용합니다. 수직 스케일링은 인스턴스의 리소스 크기를 변경하여 리소스를 조절(cpu request 0.5 core to 1 Core 등)하는 것이며, 수평 스케일링은 인스턴스의 수량을 조절하여 애플리케이션의 부하에 맞춰 확장하거나 축소합니다.

오토스케일링은 위와 같은 요소를 이용하여 시스템의 부하 변동에 자동으로 대응하여 리소스를 효율적으로 사용하고 애플리케이션의 성능과 가용성을 유지하는 데 도움을 줍니다. 이를 통해 사용자는 수동으로 리소스를 관리하거나 예측된 부하에 대한 대비를 할 필요 없이, 자동으로 시스템을 조정하여 효율적인 운영이 가능합니다.

클라우드 환경에서는 자동화된 오토스케일링이 특히 유용하며, 클라우드 제공업체가 제공하는 오토스케일링 기능을 사용할 수 있습니다. 반면 온프레미스 환경에서는 늘어나는 파드를 수용할 수 있는 노드의 수량이 한정적이라 오토스케일링 사용에 제약이 있습니다.

2. Metrics-Server를 이용한 자원 사용량 확인

오토스케일링을 적용하기 위해서는 먼저 시스템의 자원 사용량을 파악해야 합니다. 쿠버네티스 환경에서 파드와 노드의 CPU, Memory 리소스 사용량을 확인하기 위해서는 Metrics-Server가 필요합니다. 설치는 ArgoCD와 헬름을 사용합니다. 헬름으로 애플리케이션을 설치하는 자세한 방법은 8장에서 다루며 이번 장에서는 간단히 실행 명령어만 정리합니다.

$ (⎈ |switch-singapore-test:monitoring) helm repo add metrics-server 
$ (⎈ |switch-singapore-test:monitoring) helm pull metrics-server/metrics-server --version 3.10.0
$ (⎈ |switch-singapore-test:monitoring) tar xvfz metrics-server-3.10.0.tgz 
$ (⎈ |switch-singapore-test:monitoring) rm -rf metrics-server-3.10.0.tgz 
$ (⎈ |switch-singapore-test:monitoring) mv metrics-server metrics-server-3.10.0
$ (⎈ |switch-singapore-test:monitoring) cd metrics-server-3.10.0
$ (⎈ |switch-singapore-test:monitoring) mkdir ci
$ (⎈ |switch-singapore-test:monitoring) cp values.yaml ci/

헬름 Value 파일을 아래와 같이 수정합니다.

ci/values.yaml

apiService:
  insecureSkipTLSVerify: true

ArgoCD를 이용하여 배포하기 위하여 ArgoCD application 파일을 준비합니다. 아래와 같이 argo-cd-app-of-apps 디렉토리로 이동합니다.

$ (⎈ |switch-seoul-stage:kubecost) cd ../argo-cd-app-of-apps 

metrics-server 용도의 ArgoCD Application CRD 파일을 생성합니다.

templates/metrics-server-applications.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: metrics-server
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: kube-system
    server: {{ .Values.spec.destination.server }}
  project: default
  source:
    path: metrics-server-3.10.0
    helm:
      valueFiles:
      - ci/values.yaml
    repoURL: {{ .Values.spec.source.repoURL }}
    targetRevision: {{ .Values.spec.source.targetRevision }}

ArgoCD의 Apps Application은 아래와 같이 ‘templates’ 디렉토리의 applications 파일을 자동으로 인식하도록 syncPolicy/automated 옵션이 설정되어 있습니다.

apps-applications.yaml

syncPolicy:
    automated:
      prune: true
      selfHeal: true

ArgoCD GUI에서 확인하면 아래와 같이 ‘metrics-server’ 리소스를 확인할 수 있습니다.

화면 위 메뉴의 ‘SYNC’ 클릭하면 리소스가 배포됩니다.

kube-system 네임스페이스에 확인하면 아래와 같이 metrics-server 파드가 실행됩니다.

$ (⎈ |switch-singapore-test:kube-system) k get pod metrics-server-6f9cdd486c-2fqm2 
NAME                              READY   STATUS    RESTARTS   AGE
metrics-server-6f9cdd486c-2fqm2   0/1     Running   0          24s

Metrics-Server는 각 노드에 배포된 kubelet과 cAdvisor를 이용하여 전체 노드와 파드의 자원 사용량을 수집하여 API Server 통하여 조회할 수 있습니다. 명령어는 ‘k top’ 을 사용합니다.

노드 사용량 조회

$ (⎈ |switch-singapore-test:kube-system) k top nodes
NAME                                               CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
ip-10-110-24-222.ap-southeast-1.compute.internal   171m         8%     2256Mi          31%       
ip-10-110-47-109.ap-southeast-1.compute.internal   88m          4%     907Mi           12%  

파드 사용량 조회

$ (⎈ |switch-singapore-test:kube-system) k top pods
NAME                                            CPU(cores)   MEMORY(bytes)          
aws-load-balancer-controller-7d96db6884-nrcgf   2m           24Mi            
aws-node-84wfr                                  3m           41Mi
(생략)

Metrics-Server 설치가 완료되었습니다.

3. HPA(Horizontal Pod Autoscaler) 실습

HPA는 애플리케이션의 부하가 증가하여 리소스 사용량이 변경되면 자동으로 파드의 개수를 조정합니다. 앞에서 설치한 메트릭 서버가 수집한 CPU, Memory 사용량을 확인하여 임계값을 초과하거나 감소하면 자동으로 파드의 갯수를 증가헙니다.

자세한 사용법을 예제로 알아봅니다. 그럼, 테스트에 사용할 파드를 배포합니다.

php-apache.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: registry.k8s.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache

. spec.template.spec.containers.resources.requests.cpu: 200m
파드가 실행되는 노드에 요청(request)할 수 있는 CPU Core를 입력합니다. 단위는 1,000m = 1 vCore 로 200m은 0.2 Core를 의미합니다.

위 예제는 쿠버네티스 공식 홈페이지에서 제공하며 외부 접속에 따라 부하가 증가하는 PHP Apache 샘플 애플리케이션입니다. 리소스를 생성합니다.

$ (⎈ |switch-singapore-test:default) k apply -f php-apache.yaml 
deployment.apps/php-apache created
service/php-apache created

$ (⎈ |switch-singapore-test:default) k get deploy,svc
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/php-apache   1/1     1            1           40s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   172.20.0.1      <none>        443/TCP   59d
service/php-apache   ClusterIP   172.20.92.196   <none>        80/TCP    39s

php-apache 디플로이먼트와 서비스가 정상으로 설치되었습니다.

다음으로 HPA 리소스를 생성합니다. HPA 역시 쿠버네티스 리소스로 YAML 파일로 만들 수 있습니다.

php-hpa.yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  maxReplicas: 10
  metrics:
  - resource:
      name: cpu
      target:
        averageUtilization: 50
        type: Utilization
    type: Resource
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache

. spec.maxReplicas
최고로 증가하는 파드의 수량을 지정합니다.

. spec.metrics.resource.name: cpu
파드의 수량이 증가하는 기준이 되는 메트릭을 입력합니다. CPU, Memory 등을 입력할 수 있습니다.

. spec.metrics.resource.target.averageUtilization: 50
averageUtilization(평균 사용량) 기준, 즉 퍼센티지 기준으로 임계값을 지정하였습니다. 기준이 되는 수치는 파드에 지정한 Resource Request 입니다. 저희 예제는 Request에 200m(0.2Core)를 지정하고 averageUtilization에 50을 지정하였으니 100m(50%) 이상을 사용하면 파드가 증가합니다. 유의할 사항은 Resource의 Limit이 아니라 Request라는 것 입니다.

대상이 되는 모든 파드의 평균 사용량을 기준으로 사용량을 측정합니다.

spec.metrics.type: Resource
자원 사용량을 기준으로 메트릭을 지정합니다. Resource 이 외 Custom 메트릭을 사용하면 세션 숫자, 지연 시간 등의 다양한 메트릭을 추가할 수 있습니다.

. spec.scaleTargetRef.kind: Deployment
HPA가 실행하여 증가할 대상 자원을 지정합니다. 저희 예제는 php-apache 이름의 Deployment 자원입니다.

. spec.scaleTargetRef.name: php-apache
Deployment 중 php-apache 이름을 가지는 리소스를 HPA Target으로 지정합니다.

php-apache HPA 리소스를 배포합니다.

$ (⎈ |switch-singapore-test:default) k apply -f php-hpa.yaml 
horizontalpodautoscaler.autoscaling/php-apache created

HPA 리소스를 확인할 수 있습니다.

$ (⎈ |switch-singapore-test:default) k get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   0%/50%    1         10        1          64s

. TARGETS
CPU 사용량의 Target이 50%인데 현재 0%입니다. 현재는 사용량이 없습니다.

. MINPODS, MAXPODS, REPLICAS
각 1, 10, 1로 현재 php-apache 파드의 Replica 수량이 1개로 CPU 사용량이 Target 보다 아래라 MINPODS 수량과 동일합니다.

그럼 부하를 발생하여 php-apache 파드의 자원 사용량을 증가하겠습니다. 아래 스크립트는 busybox 이미지를 실행하여 ‘0.01’초 간격으로 앞에서 실행한 php 파드에 접속하는 예제입니다.

$ (⎈ |switch-singapore-test:default) kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"

If you don't see a command prompt, try pressing enter.
OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!OK!

또 하나의 창을 열어서 HPA 변화를 확인합니다.

$ (⎈ |switch-singapore-test:kube-system) k get hpa -w
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   133%/50%   1         10        1          4m53s
php-apache   Deployment/php-apache   239%/50%   1         10        3          5m
php-apache   Deployment/php-apache   128%/50%   1         10        5          5m15s
php-apache   Deployment/php-apache   53%/50%    1         10        5          5m30s

-w(watch) 옵션을 사용하면 실시간으로 변화를 확인할 수 있습니다. 부하를 발생하고 있어 ‘TARGETS’ (133% -> 239%)이 증가하고 있습니다. 이에 따라 파드의 수량(REPLICAS)도 같이 1 -> 3 -> 5로 증가합니다.

$ (⎈ |switch-singapore-test:default) k get pod
NAME                          READY   STATUS    RESTARTS   AGE
load-generator                1/1     Running   0          3m44s
php-apache-7495ff8f5b-66zzq   1/1     Running   0          113s
php-apache-7495ff8f5b-d4fdp   1/1     Running   0          3m23s
php-apache-7495ff8f5b-kghnk   1/1     Running   0          3m8s
php-apache-7495ff8f5b-l6n86   1/1     Running   0          28m
php-apache-7495ff8f5b-ldljv   1/1     Running   0          3m23s
php-apache-7495ff8f5b-msx5z   1/1     Running   0          3m8s

파드의 수량을 확인하면 위와 같이 자동으로 증가합니다. 이처럼 외부 사용자 접속이 증가하여 자원 사용량이 증가하면 쿠버네티스는 HPA 설정으로 자동으로 파드를 증가할 수 있습니다. 애플리케이션의 리소스 사용량에 따라 자동으로 파드의 수를 조절되므로 추가 관리자의 개입없이 자동으로 트래픽을 처리할 수 있어 매우 유용합니다. 

참고로 기준이 되는 메트릭은 CPU 또는 메모리 혹은 CPU, 메모리 2개 메트릭 모두 사용할 수 있습니다.

4. HPA 적용 시 고려 사항

오토스케일링을 실무에 적용하기 위해서는 몇가지 고려 사항이 있습니다. 먼저, 부하가 증가하고 감소하는 상황이 빠르게 반복되어 파드의 수량이 감소, 증가 역시 반복되는 현상(Flapping)을 방지하기 위하여 안정화 시간(stabilizationWindowSeconds)을 적절하게 지정하는 것이 필요합니다.

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
    - type: Pods
      value: 4
      periodSeconds: 15
    selectPolicy: Max

. behavior.scaleDown.stabilizationWindowSeconds: 300
파드의 감소, 증가가 빠르게 반복되는 것을 방지하기 위하여 안정화 시간(stabilizationWindowSeconds)을 지정할 수 있습니다. 위 예제는 300s(5분)을 두어 5분이 지난 후에 파드의 수량을 감소하는 작업을 진행합니다.

. behavior.scaleDown.policies.value: 100, periodSeconds: 15
한번에 감소할 수 있는 파드의 수량을 현재 실행 중인 파드의 100%까지 지정하여 MIN PODS 수량까지 줄일 수 있게 합니다. 15초마다 최대 100%까지 파드 수를 줄일 수 있습니다.

. behavior.scaleUp.stabilizationWindowSeconds: 0
파드의 수량 감소와 다르게 파드의 수량 증가 시 안정화 시간을 ‘0’으로 두었습니다. 늘어나는 트래픽을 빠르게 처리하기 위하여 안정화 시간을 ‘0’으로 지정하는 경우가 많습니다.

. behavior.scaleUp.policies.value: 100, periodSeconds: 15, value:4, periodSeconds: 15 
scaleDown 설정과 동일한데, 15초 마다 현재 파드의 수를 100% 퍼센트 또는 4개 파드까지 증가하도록 설정하였습니다.

그리고 실제 트래픽은 증가하였는데 오토스케일링 반응이 늦어서 트래픽을 제대로 처리하지 못하는 경우가 발생할 수 있습니다. 새롭게 노드를 실행하기 위한 시간(Karpenter 기준 약 40s 가량), 파드를 실행하는 시간 등이 추가로 소요됩니다. 사전에 예상 트래픽에 맞게 쿠버네티스의 노드를 미리 Cronjob 등으로 증가할 수 있으며 혹은 ‘over-provisioner’를 이용하여 미리 비어있는 노드를 준비하는 방법도 가능합니다.

다음으로 사용자 트래픽은 시스템 자원 사용량에 비례하여 증가하지 못하는 경우도 많이 있습니다. 별도의 사용자 정의 메트릭이 필요합니다. 사용자 접속 커넥션 숫자를 기준으로 파드의 수량을 증가하도록 ‘Service Monitor’, ‘Keda’ 등을 사용할 수 있습니다.

이상으로 시스템 부하에 따라 자동으로 파드의 수량을 증가하고 감소하는 HPA를 알아보았습니다.

실습에 사용한 자원은 아래와 같이 삭제합니다.

$ (⎈ |switch-singapore-test:default) k delete -f php-apache.yaml -f php-hpa.yaml 
deployment.apps "php-apache" deleted
service "php-apache" deleted
horizontalpodautoscaler.autoscaling "php-apache" deleted

해당 기술 블로그에 질문이 있으시면 언제든지 문의해 주세요. 직접 답변해 드립니다.
k8sqna@jennifersoft.com

Next

Contact Us

안녕하세요? 제니퍼소프트입니다.
기술 문의의 경우 질문자의 회사/이름/연락처를 본문에 기술해 주셔야만 원할한 지원이 가능합니다.
보내주신 문의 사항을 검토하여 빠른 시일 내에 답변해 드리겠습니다.

  • Chris
  • Irene

메일을 보냈습니다.

메일 전송이 완료되었습니다.
빠른 시일 내에 답변드리겠습니다.
감사합니다.
제니퍼소프트 웹사이트는 쿠키를 사용합니다. 쿠키에 대한 자세한 정보 및 삭제 방법은 제니퍼소프트의 개인정보처리방침을 참고하시기 바라며 본 사이트를 계속해서 이용하는 것은 제니퍼소프트의 쿠키 사용에 동의함을 의미합니다.