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 파일을 아래와 같이 수정합니다.
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 옵션이 설정되어 있습니다.
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 사용량을 확인하여 임계값을 초과하거나 감소하면 자동으로 파드의 갯수를 증가헙니다.
자세한 사용법을 예제로 알아봅니다. 그럼, 테스트에 사용할 파드를 배포합니다.
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 파일로 만들 수 있습니다.
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