1. HPA (Horizontal Pod Autoscaler)

HPA(Horizontal Pod Autoscaler)는 타겟의 메트릭이 일정 수치를 넘으면 POD의 Replicas를 늘릴 수 있다.

php-apache POD를 다운받자!

이 POD에 1000000번까지 OK!를 찍는 /var/www/html/index.php 파일이 들어 있다.

curl -s -O https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/php-apache.yaml
kubectl apply -f php-apache.yaml

또한 resources.requests.cpu200m Core이다.

Untitled

POD를 생성하고 나면 HPA를 만들건데 이는 kubectl autoscale로 만들 수 있다.

kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

Untitled 1

the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)

HPA는 cpu 사용률(request 퍼센티지)로 replicas를 계산할 수 있었다고 되어 있다

계속 강조되는 as a percentage of request 이다!

hpa의 내용을 살펴 보면,

Untitled 2

  • Replicas의 min, max가 1~10 ⇒ minReplicas, maxReplicas
  • 타겟은 php-apache 라는 Deployment 리소스로 지정 ⇒ scaleTargetRef
  • 스케일링 기준은 cpu 평균 사용률 50% 이상인 경우 ⇒ metrics.resource.target.averageUtilization

위 세 가지를 알 수 있다.

이제 부하를 빠르게 준다

Untitled

부하량에 따라 POD의 cpu request는 점점 증가했고 TARGETS의 50%를 넘으니 점점 POD 개수가 늘어나면서 REPLICAS는 7개까지 증가하였다.

Untitled 3

6분이 되니 더 이상 POD의 개수는 증가하지 않았고 10분쯤에 부하테스트를 중단하였다.

Untitled 4

그라파나로 확인해 보면 그래프는 다음과 같다. 테스트를 중단하고 5분 뒤에 Replicas가 줄어 들었다.

HPA의 알고리즘에 따라 HorizontalPodAutoscaler 컨트롤러는 desired 메트릭 값과 current 메트릭 값 사이의 비율을 계산하고 동작한다.

실행 주기는 kube-controller-manager의 --horizontal-pod-autoscaler-sync-period 파라미터에 의해 설정되고 기본 값은 15초이다. 다운스케일링할 때는 --horizontal-pod-autoscaler-downscale-stabilization 값을 참조하고 기본 값은 5분이다.

HPA의 알고리즘 공식은 아래와 같다.

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

Horizontal Pod Autoscaling

좀 더 쉽게 한글로 말하자면 아래와 같이 말할 수 있다.

필요한 Pod  = (올림)[현재 CPU 사용률 / 타겟 CPU 사용률 * 현재 Pod ]

현재 CPU 사용률은 해당 POD의 CPU requests에 대한 비율로 계산하여 평균을 구해야 한다.

POD의 CPU requests 200m이지만 실제 사용률은 120m을 사용하게 된다면

⇒ 120m / 200m * 100 = 60%

실습에 대입해 보자면

  1. POD 1개일 때, 60% / 50% * 1 =1.2 ⇒ 2
  2. POD 2개일 때, 60% / 50% * 2 = 2.4 ⇒ 3
  3. POD 3개일 때, 60% / 50% * 3 = 3.6 ⇒ 4
  4. POD 4개일 때, 60% / 50% * 4 = 4.8 ⇒ 5
  5. POD 5개일 때, 60% / 50% * 5 = 6 ⇒ 6
  6. POD 6개일 때, 60% / 50% * 6 = 7.2 ⇒ 8

마지막 8은 60%까지 안넘어갔기 때문에 replicas는 7까지 생성된 것 같다.

결론

Untitled 5

  1. HPA는 metric server가 설치되어 있어야 하며, 리소스 수집 서버 역할을 해 준다.

  2. HPA가 설정되면 HPA의 타켓은 Deployment이기 때문에, 아무리 Deployment의 replicas를 변경해도 minReplicas 값을 따른다. 그래서 POD의 수는 HPA의 minReplicas 값에 따라 Desired한 값으로 생성된다.

    하지만 Deployment의 Replicas를 0으로 줄인다면 HPA의 타겟이 없어지게 된다. 아래와 같이 TARGETS에 unknown이 발생한다. 즉 타겟의 리소스를 수집해 오지 못한다.

    (컨테이너에 request 값을 지정하지 않아도 동일하게 unknown이 표시된다. 리소스 request 값과 연관있기 때문!)

    Untitled 6

  3. HPA 알고리즘 공식

     desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
    

    requset 값에 따라 currentMetricValue가 달라지고 스케일링 기준이 달라진다!

2. VPA (Vertical Pod Autoscaler)

VPA(Vertical Pod Autoscaler)는 타겟의 메트릭이 일정 수치를 넘으면 POD의 Resource(CPU, Memory)를 높일 수 있다.

HPA와 동일하게 metric server를 통하여 리소스를 수집한다.

POD의 request 값을 최대한 최적값으로 수정해 준다. 다만 HPA와 동시에 사용은 불가능하며, VPA가 최적의 값으로 requests를 수정하게 되면 기존 POD를 지우고 신규 POD로 생성된다.

공식 문서의 예제대로 VPA를 다운받고 생성한다.

autoscaler/vertical-pod-autoscaler at master · kubernetes/autoscaler

git clone https://github.com/kubernetes/autoscaler.git
cd ~/autoscaler/vertical-pod-autoscaler/
cat examples/hamster.yaml | yh
kubectl apply -f examples/hamster.yaml
  • VPA minAllowedmaxAllowed 값으로 VPA가 Deployment를 타겟으로 cpu, memory 리소스를 조절할 수 있다.

    Untitled

  • Deployment replicas는 2로 설정하고 cpu 100m, memory 50Mi를 설정한다.

    Untitled

이제 화면을 모니터링해 보면 POD는 계속 일을 하는데, VPA는 그걸 모니터링하다가 지정한 범위 내에 최적의 값으로 Scale Up/Down해 준다.

Untitled 1

최종적으로 548m, 262144k 값으로 두 개 POD를 유지하게 된다.

Untitled

이벤트 로그를 확인해 보면 POD를 계속 재생성했다는 VPA의 이벤트 로그를 볼 수 있다.

Untitled 10

만약 VPA에서 spec.updatePolicy.updateModeOff 로 변경 시 POD에 Spec을 자동으로 변경하고 재실행하지 않는다. 기본값은 Auto이다.

Untitled 11

마지막으로 그라파나로 확인한 모습은 VPA 노력이 한 눈에 보였다!

Untitled

3. KEDA(Kubernetes based Event Driven Autoscaler)

KEDA는 예전 HPA는 Resource(CPU, Memory) 메트릭을 기반으로 하였는데, 그 점을 보안하여 특정 이벤트를 기반으로 POD의 Replicas를 조절할 수 있다.

Untitled

이번 실습에서는 ScaledObject를 통해 cron으로 트리거를 줘서 일정 시간마다 POD를 띄우고 내리게 해봤다.

[KEDA Cron](https://keda.sh/docs/2.10/scalers/cron/)

대상은 php-apache 서버로 하였고 ScaledObject를 생성하면 해당 서버를 대상으로 hpa도 생성되었다.

기본적으로 HPA와 VPA는 metric server를 사용하였는데, KEDA는 전용 metric server를 사용한다.

실습을 시작하기 위해 우선 먼저 아래 metric server 설정을 추가한 values 파일을 만들었다

cat <<EOT > keda-values.yaml
metricsServer:
  useHostNetwork: true

prometheus:
  metricServer:
    enabled: true
    port: 9022
    portName: metrics
    path: /metrics
    serviceMonitor:
      # Enables ServiceMonitor creation for the Prometheus Operator
      enabled: true
    podMonitor:
      # Enables PodMonitor creation for the Prometheus Operator
      enabled: true
  operator:
    enabled: true
    port: 8080
    serviceMonitor:
      # Enables ServiceMonitor creation for the Prometheus Operator
      enabled: true
    podMonitor:
      # Enables PodMonitor creation for the Prometheus Operator
      enabled: true

  webhooks:
    enabled: true
    port: 8080
    serviceMonitor:
      # Enables ServiceMonitor creation for the Prometheus webhooks
      enabled: true
EOT

이제 keda 네임스페이스를 만들고 실습 환경을 구성할 것이다.

위에 만든 keda values 파일로 keda 헬름을 구성하였다.

kubectl create namespace keda
helm repo add kedacore https://kedacore.github.io/charts
helm install keda kedacore/keda --version 2.13.0 --namespace keda -f keda-values.yaml

생성하고 나면 아래와 같은 리소스가 생성된다.

Untitled

이제 대상 서버를 생성하고

kubectl apply -f php-apache.yaml -n keda
kubectl get pod -n keda

ScaledObject **정책을 cron으로 생성한다.

매 시에 00-05, 15-20, 30-35, 45-50분 마다 desiredReplicas 1개만큼 POD를 생성한다.

근데 스케일인은 cooldownPeriod가 5분이기 때문에 실제 POD가 내려가는 시각은 5분 뒤에 이루어졌다.

Untitled

hpa를 확인해 보면 ScaledObject에서 만들었던 cron 설정이 들어가 있다.

Untitled

그리고 대시보드를 확인해 보면 아래와 같은 그래프를 얻을 수 있다!

Untitled

원래 */3 * * * *와 같이 3분마다 라는 형식을 crontab에서는 사용할 수 있는데 ScaledObject에 사용하려면 따옴표로 묶어줘야 했다. 근데 start-end 부분의 간격을 맞추려면 조건이 맞지 않아서 사용할 수 없었다.

Categories:

Updated:

Leave a comment