수평 Pod 자동 확장
수평 Pod 자동 확장 (Horizontal Pod Autoscaling)
Kubernetes에서 HorizontalPodAutoscaler는 워크로드 리소스(예: Deployment나 StatefulSet)를 자동으로 업데이트해서, 용량을 수요에 맞게 자동으로 조정하는 것을 목표로 해요.
수평 확장(horizontal scaling)은 증가한 부하에 대한 응답으로 더 많은 Pod를 배포하는 것을 의미해요. 이는 수직 확장과 다르며, Kubernetes에서 수직 확장은 이미 워크로드에 대해 실행 중인 Pod에 더 많은 리소스(예: 메모리나 CPU)를 할당하는 것을 뜻해요.
부하가 감소하고 Pod 수가 구성된 최소값보다 많으면, HorizontalPodAutoscaler는 워크로드 리소스(Deployment, StatefulSet, 또는 다른 유사한 리소스)에 축소하라고 지시해요.
수평 Pod 자동 확장은 확장할 수 없는 객체(예: DaemonSet)에는 적용되지 않아요.
HorizontalPodAutoscaler는 Kubernetes API 리소스이자 컨트롤러로 구현돼요. 리소스가 컨트롤러의 동작을 결정해요. Kubernetes 컨트롤 플레인 안에서 실행되는 수평 pod 자동 확장 컨트롤러는 주기적으로 대상(예: Deployment)의 원하는 규모를, 평균 CPU 사용률, 평균 메모리 사용률, 또는 지정한 다른 커스텀 메트릭 같은 관찰된 메트릭과 일치하도록 조정해요.
수평 pod 자동 확장을 사용하는 둘러보기(walkthrough) 예시가 있어요.
HorizontalPodAutoscaler는 어떻게 작동하나요?
그림 1. HorizontalPodAutoscaler가 Deployment와 그 ReplicaSet의 규모를 제어해요
Kubernetes는 수평 pod 자동 확장을 간헐적으로 실행되는 제어 루프로 구현해요(연속 프로세스가 아니에요). 간격은 kube-controller-manager에 대한 --horizontal-pod-autoscaler-sync-period 파라미터로 설정돼요(기본 간격은 15초).
각 기간 동안 한 번, 컨트롤러 매니저는 각 HorizontalPodAutoscaler 정의에 지정된 메트릭에 대해 리소스 사용률을 조회해요. 컨트롤러 매니저는 scaleTargetRef가 정의하는 대상 리소스를 찾고, 대상 리소스의 .spec.selector 라벨에 따라 pod를 선택하며, 리소스 메트릭 API(pod별 리소스 메트릭용)나 커스텀 메트릭 API(다른 모든 메트릭용)에서 메트릭을 가져와요.
pod별 리소스 메트릭(CPU 같은 것)의 경우, 컨트롤러는 HorizontalPodAutoscaler가 대상으로 하는 각 Pod에 대해 리소스 메트릭 API에서 메트릭을 가져와요. 그런 다음 대상 사용률 값이 설정되어 있으면, 컨트롤러는 각 Pod의 컨테이너에 있는 동등한 리소스 요청의 백분율로 사용률 값을 계산해요. 대상 원시 값이 설정되어 있으면 원시 메트릭 값이 직접 사용돼요. 컨트롤러는 대상으로 하는 모든 Pod에 걸쳐 사용률이나 원시 값(지정된 대상 유형에 따라)의 평균을 내고, 원하는 복제본 수를 확장하는 데 사용되는 비율을 만들어요.
Pod의 일부 컨테이너가 관련 리소스 요청을 설정하지 않았다면 해당 Pod의 CPU 사용률은 정의되지 않고, 자동 확장기는 그 메트릭에 대해 어떤 조치도 취하지 않는다는 점을 유의하세요. 자동 확장 알고리즘이 어떻게 작동하는지에 대한 자세한 내용은 아래 알고리즘 상세 섹션을 참고하세요.
pod별 커스텀 메트릭의 경우, 컨트롤러는 사용률 값이 아닌 원시 값과 함께 작동한다는 점을 제외하면 pod별 리소스 메트릭과 유사하게 기능해요.
객체 메트릭과 외부 메트릭의 경우, 해당 객체를 설명하는 단일 메트릭이 가져와져요. 이 메트릭을 대상 값과 비교해 위와 같이 비율을 만들어요. autoscaling/v2 API 버전에서는 이 값을 비교를 하기 전에 선택적으로 Pod 수로 나눌 수 있어요.
HorizontalPodAutoscaler의 일반적인 용도는 집계된 API(metrics.k8s.io, custom.metrics.k8s.io, external.metrics.k8s.io)에서 메트릭을 가져오도록 구성하는 거예요. metrics.k8s.io API는 보통 별도로 시작해야 하는 Metrics Server라는 애드온이 제공해요. 리소스 메트릭에 대한 자세한 내용은 Metrics Server를 참고하세요.
메트릭 API 지원
기본적으로 HorizontalPodAutoscaler 컨트롤러는 일련의 API에서 메트릭을 검색해요. 이 API들에 접근하려면 클러스터 관리자가 다음을 확인해야 해요.
- API 집계 계층(aggregation layer)이 활성화되어 있어요.
- 해당 API가 등록되어 있어요.
- 리소스 메트릭의 경우
metrics.k8s.ioAPI이며, 일반적으로 metrics-server가 제공해요. 클러스터 애드온으로 시작할 수 있어요. - 커스텀 메트릭의 경우
custom.metrics.k8s.ioAPI예요. 메트릭 솔루션 벤더가 제공하는 "adapter" API 서버가 제공해요. 메트릭 파이프라인에서 Kubernetes 메트릭 어댑터를 사용할 수 있는지 확인하세요. - 외부 메트릭의 경우
external.metrics.k8s.ioAPI예요. 위에서 제공된 커스텀 메트릭 어댑터가 제공할 수 있어요.
- 리소스 메트릭의 경우
HorizontalPodAutoscaler가 대상으로 하는 것에 대해 여러 가지 리소스 메트릭 유형을 사용할 수 있어요.
HorizontalPodAutoscaler 컨트롤러는 확장을 지원하는 해당 워크로드 리소스(Deployment, StatefulSet 같은 것)에 접근해요. 이들 리소스는 각각 scale이라는 하위 리소스를 가지는데, 이는 복제본 수를 동적으로 설정하고 각각의 현재 상태를 검사할 수 있는 인터페이스예요. Kubernetes API의 하위 리소스에 대한 일반적인 정보는 Kubernetes API 개념을 참고하세요.
HorizontalPodAutoscaler에서 여러 메트릭이 지정되면, 이 계산은 각 메트릭에 대해 수행되고, 그다음 가장 큰 원하는 복제본 수가 선택돼요. 이 메트릭 중 어떤 것을 원하는 복제본 수로 변환할 수 없고(예: 메트릭 API에서 메트릭을 가져오는 중 오류로 인해) 가져올 수 있는 메트릭이 축소를 제안하면, 확장은 건너뛰어져요. 이는 HPA가 하나 이상의 메트릭이 현재 값보다 큰 desiredReplicas를 주면 여전히 확장할 수 있다는 것을 의미해요.
마지막으로 HPA가 대상을 확장하기 직전에 확장 권장 사항이 기록돼요. 컨트롤러는 구성 가능한 창(window) 안의 모든 권장 사항을 고려해 그 창 안에서 가장 높은 권장 사항을 선택해요. 이 값을 구성하려면 기본값 5분인 --horizontal-pod-autoscaler-downscale-stabilization 커맨드라인 옵션을 사용해요. 이는 축소가 점진적으로 발생해서, 급격히 변동하는 메트릭 값의 영향을 완화한다는 것을 의미해요.
알고리즘 상세 (Algorithm details)
가장 기본적인 관점에서 HorizontalPodAutoscaler 컨트롤러는 원하는 메트릭 값과 현재 메트릭 값의 비율로 작동해요:
desiredReplicas = ceil( currentReplicas × ( currentMetricValue / desiredMetricValue ) )
예를 들어 현재 메트릭 값이 200m이고 원하는 값이 100m이면, 200.0 ÷ 100.0 = 2.0이므로 복제본 수가 두 배가 돼요. 현재 값이 대신 50m이면 50.0 ÷ 100.0 = 0.5이므로 복제본 수를 절반으로 줄여요. 컨트롤 플레인은 비율이 1.0에 충분히 가까우면(구성 가능한 공차, 기본 0.1 이내) 어떤 확장 동작도 건너뛰어요.
targetAverageValue나 targetAverageUtilization이 지정되면, currentMetricValue는 HorizontalPodAutoscaler의 확장 대상에 있는 모든 Pod에서 주어진 메트릭의 평균을 내어 계산돼요.
공차를 확인하고 최종 값을 결정하기 전에, 컨트롤 플레인은 메트릭이 누락되었는지, 그리고 Ready Pod가 몇 개인지도 고려해요. pod별 리소스 메트릭의 경우, 삭제 타임스탬프가 설정된 모든 Pod(삭제 타임스탬프가 있는 객체는 종료/제거되는 과정에 있음)는 무시되고, 실패한 Pod는 모두 폐기돼요. 외부 및 객체 메트릭의 경우 복제본 수는 Running 및 Ready Pod 수를 기반으로 하며, 아직 Ready인 종료 중 Pod는 그 총계에 계속 포함돼요.
특정 Pod가 메트릭을 누락하면 나중을 위해 제쳐두고, 메트릭이 누락된 Pod는 최종 확장량을 조정하는 데 사용돼요.
CPU로 확장할 때 어떤 pod가 아직 준비되지 않았거나(여전히 초기화 중이거나, 불건강할 수도 있음) 그 pod의 가장 최근 메트릭 지점이 준비되기 이전이라면, 그 pod도 제쳐둬요.
기술적 제약 때문에 HorizontalPodAutoscaler 컨트롤러는 특정 CPU 메트릭을 제쳐둘지 결정할 때 pod가 처음 준비되는 시점을 정확히 알 수 없어요. 대신, pod가 unready이고 시작 후 짧고 구성 가능한 시간 창 내에 ready로 전환했다면 "아직 준비되지 않은" 것으로 간주해요. 이 값은 --horizontal-pod-autoscaler-initial-readiness-delay 커맨드라인 옵션으로 구성되며 기본값은 30초예요. pod가 준비된 후에는, 시작 후 더 긴 구성 가능한 시간 내에 발생한 ready로의 전환을 첫 번째로 간주해요. 이 값은 --horizontal-pod-autoscaler-cpu-initialization-period 커맨드라인 옵션으로 구성되며 기본값은 5분이에요.
그런 다음 위에서 제쳐두거나 폐기하지 않은 남은 pod를 사용해 기본 확장 비율(currentMetricValue / desiredMetricValue)이 계산돼요.
누락된 메트릭이 있으면 컨트롤 플레인은 평균을 더 보수적으로 다시 계산하는데, 축소의 경우 그 pod들이 원하는 값의 100%를 소비하고, 확장의 경우 0%를 소비한다고 가정해요. 이는 잠재적 확장의 크기를 줄여줘요.
게다가 아직 준비되지 않은 pod가 있고, 누락된 메트릭이나 아직 준비되지 않은 pod를 고려하지 않으면 워크로드가 확장됐을 상황이라면, 컨트롤러는 아직 준비되지 않은 pod가 원하는 메트릭의 0%를 소비한다고 보수적으로 가정해서 확장의 크기를 더 줄여요.
아직 준비되지 않은 pod와 누락된 메트릭을 고려한 후, 컨트롤러는 사용률 비율을 다시 계산해요. 새 비율이 확장 방향을 역전시키거나 공차 내에 있으면 컨트롤러는 어떤 확장 동작도 취하지 않아요. 다른 경우에는 새 비율이 Pod 수 변경을 결정하는 데 사용돼요.
평균 사용률의 원래 값은 새 사용률 비율이 사용되더라도, 아직 준비되지 않은 pod나 누락된 메트릭을 고려하지 않고 HorizontalPodAutoscaler 상태를 통해 다시 보고된다는 점을 유의하세요.
Pod 준비성과 자동 확장 메트릭
HorizontalPodAutoscaler(HPA) 컨트롤러에는 시작 중에 Pod에서 CPU 메트릭이 수집되는 방식을 영향 주는 두 개의 커맨드라인 옵션이 포함돼요.
--horizontal-pod-autoscaler-cpu-initialization-period(기본값: 5분)
이것은 Pod가 시작된 후의 시간 창을 정의하는데, 그 동안에는 CPU 사용량이 무시돼요(단, - Pod가 Ready 상태이고 - 메트릭 샘플이 Ready 기간 동안 완전히 취해진 경우는 제외).
이 커맨드라인 옵션은 HPA 확장 결정에서 초기화 중인 Pod(예: 예열 중인 Java 앱)의 오해를 부르는 높은 CPU 사용량을 배제하는 데 도움이 돼요.
--horizontal-pod-autoscaler-initial-readiness-delay(기본값: 30초)
이것은 Pod가 시작된 후의 짧은 지연 기간을 정의하는데, 그 동안 HPA 컨트롤러는 이전에 잠깐 Ready로 전환된 적이 있더라도 현재 Unready인 Pod를 여전히 초기화 중인 것으로 취급해요.
이것은 다음을 위해 설계됐어요. - 시작 중에 Ready와 Unready를 빠르게 오가는 Pod를 포함하지 않는다. - HPA가 그들의 메트릭을 유효한 것으로 간주하기 전에 초기 준비성 신호의 안정성을 보장한다.
이 커맨드라인 옵션은 클러스터 전체에서만 설정할 수 있어요.
pod 준비성의 주요 동작
- Pod가 Ready이고 Ready를 유지하면, 지연 안에서도 메트릭 기여로 계산될 수 있어요.
- Pod가 Ready와 Unready를 빠르게 오가면, 안정적으로 Ready로 간주될 때까지 메트릭이 무시돼요.
pod 준비성의 좋은 관행
- 높은 CPU 사용량이 지나갈 때까지 통과하지 않는 startupProbe를 구성하거나,
- readinessProbe가 CPU 급증이 가라앉은 후에만 Ready를 보고하도록 initialDelaySeconds를 사용해 보장하세요.
그리고 이상적으로 CPU 시작 기간을 포함하도록 --horizontal-pod-autoscaler-cpu-initialization-period도 설정하세요.
API 객체
HorizontalPodAutoscaler는 Kubernetes autoscaling API 그룹의 API 종류예요. 현재 안정 버전은 autoscaling/v2 API 버전에서 찾을 수 있는데, 여기에는 메모리와 커스텀 메트릭으로 확장하는 지원이 포함돼요. autoscaling/v2에서 도입된 새 필드는 autoscaling/v1로 작업할 때 애노테이션으로 보존돼요.
HorizontalPodAutoscaler API 객체를 만들 때 지정한 이름이 유효한 DNS 하위 도메인 이름인지 확인하세요. API 객체에 대한 더 자세한 내용은 HorizontalPodAutoscaler 객체에서 찾을 수 있어요.
워크로드 규모의 안정성
HorizontalPodAutoscaler를 사용해 복제본 그룹의 규모를 관리할 때, 평가되는 메트릭의 동적 특성 때문에 복제본 수가 자주 변동할 수 있어요. 이것은 때때로 쓰래싱(thrashing) 또는 플래핑(flapping) 이라고 불려요. 이는 사이버네틱스의 히스테리시스(hysteresis) 개념과 비슷해요.
롤링 업데이트 중 자동 확장
Kubernetes를 사용하면 Deployment에서 롤링 업데이트를 수행할 수 있어요. 이 경우 Deployment가 밑바탕의 ReplicaSet을 관리해요. Deployment에 대한 자동 확장을 구성할 때, 단일 Deployment에 HorizontalPodAutoscaler를 바인딩해요. HorizontalPodAutoscaler는 Deployment의 replicas 필드를 관리해요. deployment 컨트롤러는 롤아웃 중 그리고 그 후에도 합계가 적절한 수가 되도록 밑바탕의 ReplicaSet의 replicas를 설정하는 책임을 져요.
자동 확장된 복제본 수를 가진 StatefulSet의 롤링 업데이트를 수행하면, StatefulSet이 자체 Pod 집합을 직접 관리해요(ReplicaSet과 유사한 중간 리소스가 없어요).
리소스 메트릭 지원
모든 HPA 대상은 확장 대상에 있는 pod의 리소스 사용량을 기반으로 확장될 수 있어요. Pod 사양을 정의할 때 cpu와 memory 같은 리소스 요청을 지정해야 해요. 이것은 리소스 사용률을 결정하는 데 사용되고 HPA 컨트롤러가 대상을 위아래로 확장하는 데 사용해요. 리소스 사용률 기반 확장을 사용하려면 다음과 같이 메트릭 소스를 지정해요:
type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
이 메트릭으로 HPA 컨트롤러는 확장 대상에 있는 pod의 평균 사용률을 60%로 유지해요. 사용률은 리소스의 현재 사용량과 pod의 요청 리소스 사이의 비율이에요. 사용률이 어떻게 계산되고 평균 내는지에 대한 자세한 내용은 알고리즘을 참고하세요.
참고:
모든 컨테이너의 리소스 사용량이 합산되므로, 총 pod 사용률은 개별 컨테이너 리소스 사용량을 정확히 나타내지 못할 수 있어요. 이는 단일 컨테이너가 높은 사용량으로 실행되고 있는데 전체 pod 사용량이 여전히 허용 한도 내라서 HPA가 확장하지 않는 상황으로 이어질 수 있어요.
컨테이너 리소스 메트릭
이것은 Kubernetes에서 1.30 릴리스 이후로 안정적인 기능이에요. 더 이상 이 기능을 토글할 수 없어요(관련 기능 게이트가 제거됨).
HorizontalPodAutoscaler API는 컨테이너 메트릭 소스도 지원해서, HPA가 대상 리소스를 확장하기 위해 일련의 Pod에 걸쳐 개별 컨테이너의 리소스 사용량을 추적할 수 있게 해줘요. 이렇게 하면 특정 Pod에서 가장 중요한 컨테이너에 대한 확장 임계값을 구성할 수 있어요. 예를 들어 웹 애플리케이션과 로깅을 제공하는 사이드카 컨테이너가 있다면, 사이드카 컨테이너와 그 리소스 사용량을 무시하고 웹 애플리케이션의 리소스 사용을 기반으로 확장할 수 있어요.
대상 리소스를 다른 컨테이너 집합이 있는 새 Pod 사양으로 수정한다면, 새로 추가된 컨테이너도 확장에 사용되어야 한다면 HPA 스펙을 수정해야 해요. 메트릭 소스에 지정된 컨테이너가 존재하지 않거나 pod의 일부에만 존재하면 그 pod들은 무시되고 권장 사항이 다시 계산돼요. 계산에 대한 자세한 내용은 알고리즘을 참고하세요. 자동 확장에 컨테이너 리소스를 사용하려면 다음과 같이 메트릭 소스를 정의해요:
type: ContainerResource
containerResource:
name: cpu
container: application
target:
type: Utilization
averageUtilization: 60
위 예시에서 HPA 컨트롤러는 모든 pod의 application 컨테이너에서 cpu의 평균 사용률이 60%가 되도록 대상을 확장해요.
참고:
HorizontalPodAutoscaler가 추적하는 컨테이너의 이름을 변경한다면, 변경이 적용되는 동안 확장이 계속 사용 가능하고 효과적이도록 특정 순서로 변경할 수 있어요. 컨테이너를 정의하는 리소스(예: Deployment)를 업데이트하기 전에, 새 컨테이너 이름과 이전 컨테이너 이름을 모두 추적하도록 관련 HPA를 업데이트해야 해요. 이렇게 하면 HPA가 업데이트 과정 내내 확장 권장 사항을 계산할 수 있어요.
컨테이너 이름 변경을 워크로드 리소스에 롤아웃한 뒤에는 HPA 사양에서 이전 컨테이너 이름을 제거해 정리하세요.
커스텀 메트릭으로 확장
기능 상태: Kubernetes v1.23 [stable]
(autoscaling/v2beta2 API 버전이 이전에 이 능력을 베타 기능으로 제공했어요)
autoscaling/v2 API 버전을 사용한다면, HorizontalPodAutoscaler가 커스텀 메트릭(Kubernetes나 어떤 Kubernetes 컴포넌트에도 내장되지 않은)에 기반해 확장하도록 구성할 수 있어요. 그러면 HorizontalPodAutoscaler 컨트롤러가 Kubernetes API에서 이 커스텀 메트릭을 조회해요.
요구사항은 메트릭 API 지원을 참고하세요.
여러 메트릭으로 확장
기능 상태: Kubernetes v1.23 [stable]
(autoscaling/v2beta2 API 버전이 이전에 이 능력을 베타 기능으로 제공했어요)
autoscaling/v2 API 버전을 사용한다면, HorizontalPodAutoscaler가 확장할 여러 메트릭을 지정할 수 있어요. 그런 다음 HorizontalPodAutoscaler 컨트롤러는 각 메트릭을 평가하고 그 메트릭에 기반해 새 규모를 제안해요. HorizontalPodAutoscaler는 각 메트릭에 대해 권장된 최대 규모를 취하고 워크로드를 그 크기로 설정해요(구성한 전체 최대값보다 크지 않다는 전제 하에).
메트릭 API 지원
기본적으로 HorizontalPodAutoscaler 컨트롤러는 일련의 API에서 메트릭을 검색해요. 이 API들에 접근하기 위해 클러스터 관리자는 다음을 확인해야 해요.
- API 집계 레이어가 활성화되어 있어요.
- 해당 API가 등록되어 있어요.
- 리소스 메트릭의 경우
metrics.k8s.ioAPI이며, 일반적으로 metrics-server가 제공해요. 클러스터 애드온으로 시작할 수 있어요. - 커스텀 메트릭의 경우
custom.metrics.k8s.ioAPI예요. 메트릭 솔루션 벤더가 제공하는 "adapter" API 서버가 제공해요. - 외부 메트릭의 경우
external.metrics.k8s.ioAPI예요. 위에서 제공된 커스텀 메트릭 어댑터가 제공할 수 있어요.
- 리소스 메트릭의 경우
이런 다양한 메트릭 경로와 그것들이 어떻게 다른지에 대한 자세한 내용은 HPA V2, custom.metrics.k8s.io, external.metrics.k8s.io에 대한 관련 설계 제안을 참고하세요.
구성 가능한 확장 동작
기능 상태: Kubernetes v1.23 [stable]
(autoscaling/v2beta2 API 버전이 이전에 이 능력을 베타 기능으로 제공했어요)
v2 HorizontalPodAutoscaler API를 사용한다면, behavior 필드(API 참조 참고)를 사용해 별도의 확장(scale-up)과 축소(scale-down) 동작을 구성할 수 있어요. behavior 필드 아래에 scaleUp 및/또는 scaleDown을 설정해 이 동작들을 지정해요.
확장 정책(scaling policies)은 확장 중 복제본의 변화율을 제어할 수 있게 해줘요. 또한 플래핑을 방지하기 위해 두 가지 설정을 사용할 수 있어요: 복제본 수를 부드럽게 하기 위한 안정화 창(stabilization window)과, 지정된 임계값 아래의 사소한 메트릭 변동을 무시하기 위한 공차(tolerance)를 지정할 수 있어요.
확장 정책 (Scaling policies)
스펙의 behavior 섹션에 하나 이상의 확장 정책을 지정할 수 있어요. 여러 정책이 지정되면 가장 많은 변화를 허용하는 정책이 기본적으로 선택돼요. 다음 예시는 축소할 때 이 동작을 보여줘요.
behavior:
scaleDown:
policies:
- type: Pods
value: 4
periodSeconds: 60
- type: Percent
value: 10
periodSeconds: 60
periodSeconds는 정책이 유지되어야 하는 과거의 시간 길이를 나타내요. periodSeconds에 설정할 수 있는 최대값은 1800(30분)이에요. 첫 번째 정책(Pods)은 1분 안에 최대 4개 복제본이 축소되도록 허용해요. 두 번째 정책(Percent)은 1분 안에 현재 복제본의 최대 10%가 축소되도록 허용해요.
기본적으로 가장 많은 변화를 허용하는 정책이 선택되므로, 두 번째 정책은 pod 복제본 수가 40보다 많을 때만 사용돼요. 복제본이 40개 이하이면 첫 번째 정책이 적용돼요. 예를 들어 복제본이 80개이고 대상을 10개로 축소해야 한다면 첫 번째 단계에서 8개의 복제본이 줄어들어요. 다음 반복에서 복제본 수가 72개일 때 pod의 10%는 7.2이지만 숫자는 8로 올림돼요. 자동 확장기 컨트롤러의 각 루프에서 변경할 pod 수는 현재 복제본 수를 기반으로 다시 계산돼요. 복제본 수가 40 미만으로 떨어지면 첫 번째 정책(Pods)이 적용되고 한 번에 4개 복제본이 줄어들어요.
확장 방향에 대한 selectPolicy 필드를 지정해 정책 선택을 변경할 수 있어요. 값을 Min으로 설정하면 복제본 수에서 가장 작은 변화를 허용하는 정책이 선택돼요. 값을 Disabled로 설정하면 그 방향의 확장을 완전히 비활성화해요.
안정화 창 (Stabilization window)
안정화 창은 확장에 사용되는 메트릭이 계속 변동할 때 복제본 수의 플래핑을 제한하는 데 사용돼요. 자동 확장 알고리즘은 이 창을 사용해 이전의 원하는 상태를 추론하고 워크로드 규모에 원하지 않는 변화를 피해요.
예를 들어 다음 예시 조각에서는 scaleDown에 대해 안정화 창이 지정돼요.
behavior:
scaleDown:
stabilizationWindowSeconds: 300
메트릭이 대상을 축소해야 한다고 나타내면 알고리즘은 이전에 계산된 원하는 상태를 살펴보고 지정된 구간에서 가장 높은 값을 사용해요. 위 예시에서는 지난 5분의 모든 원하는 상태가 고려돼요.
이것은 롤링 최대값에 가깝게 동작하며, 몇 순간 후에 동등한 Pod를 다시 만드는 일을 촉발하기 위해 자동 확장 알고리즘이 자주 Pod를 제거하는 것을 피해요.
공차 (Tolerance)
기능 상태: Kubernetes v1.37 [stable]
tolerance 필드는 메트릭 변동의 임계값을 구성해서, 그 값보다 낮은 변화에 대해서는 자동 확장기가 확장하지 않도록 해요.
이 공차는 원하는 메트릭 값 주변에서 확장이 발생하지 않는 변동량으로 정의돼요. 예를 들어 대상 메모리 소비량이 100MiB이고 확장 공차가 5%인 HorizontalPodAutoscaler를 생각해보세요:
behavior:
scaleUp:
tolerance: 0.05 # 확장에 대한 5% 공차
이 구성으로 HPA 알고리즘은 메모리 소비량이 105MiB보다 높을 때만(즉 대상보다 5% 높을 때) 확장을 고려해요.
이 필드를 설정하지 않으면 HPA는 클러스터 전체 기본 공차인 10%를 적용해요. 이 기본값은 kube-controller-manager --horizontal-pod-autoscaler-tolerance 커맨드라인 인자를 사용해 확장과 축소 모두에 대해 업데이트할 수 있어요. (Kubernetes API로는 이 기본값을 구성할 수 없어요.)
기본 동작 (Default behavior)
커스텀 확장을 사용할 때 모든 필드를 지정할 필요는 없어요. 커스터마이즈해야 하는 값만 지정하면 돼요. 이 커스텀 값들은 기본값과 병합돼요. 기본값은 HPA 알고리즘의 기존 동작과 일치해요.
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
축소의 경우 안정화 창은 300초(또는 --horizontal-pod-autoscaler-downscale-stabilization 커맨드라인 옵션이 제공된다면 그 값)예요. 축소를 위한 정책은 현재 실행 중인 복제본의 100%를 제거할 수 있게 하는 단일 정책뿐인데, 이는 확장 대상을 허용된 최소 복제본까지 축소할 수 있다는 뜻이에요. 확장의 경우 안정화 창이 없어요. 메트릭이 대상을 확장해야 한다고 나타내면 대상이 즉시 확장돼요. HPA가 안정 상태에 도달할 때까지 15초마다 최대 4개 pod 또는 현재 실행 중인 복제본의 100%가 추가될 수 있는 두 정책이 있어요.
예시: 축소 안정화 창 변경
1분의 커스텀 축소 안정화 창을 제공하려면 다음 동작이 HPA에 추가돼요:
behavior:
scaleDown:
stabilizationWindowSeconds: 60
예시: 축소 속도 제한
HPA가 pod를 제거하는 속도를 분당 10%로 제한하려면 다음 동작이 HPA에 추가돼요:
behavior:
scaleDown:
policies:
- type: Percent
value: 10
periodSeconds: 60
분당 5개 이상의 Pod가 제거되지 않도록 하려면, 고정 크기 5의 두 번째 축소 정책을 추가하고 selectPolicy를 최소로 설정할 수 있어요. selectPolicy를 Min으로 설정하면 자동 확장기가 가장 적은 Pod 수에 영향을 주는 정책을 선택한다는 뜻이에요:
behavior:
scaleDown:
policies:
- type: Percent
value: 10
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
selectPolicy: Min
예시: 축소 비활성화
selectPolicy 값 Disabled는 주어진 방향의 확장을 꺼요. 따라서 축소를 방지하려면 다음 정책이 사용돼요:
behavior:
scaleDown:
selectPolicy: Disabled
kubectl에서의 HorizontalPodAutoscaler 지원
HorizontalPodAutoscaler는 모든 API 리소스처럼 kubectl에서 표준 방식으로 지원돼요. kubectl create 명령으로 새 자동 확장기를 만들 수 있어요. kubectl get hpa로 자동 확장기를 나열하고 kubectl describe hpa로 자세한 설명을 얻을 수 있어요. 마지막으로 kubectl delete hpa로 자동 확장기를 삭제할 수 있어요.
추가로, HorizontalPodAutoscaler 객체를 만들기 위한 특별한 kubectl autoscale 명령이 있어요. 예를 들어 kubectl autoscale rs foo --min=2 --max=5 --cpu=80%를 실행하면 ReplicaSet foo에 대한 자동 확장기가 생성되는데, 대상 CPU 사용률이 80%로 설정되고 복제본 수가 2에서 5 사이예요.
0으로 확장하기 (Scaling to and from zero)
기능 상태: Kubernetes v1.37 [beta](기본 활성화)
커스텀(객체) 또는 외부 메트릭으로 확장하는 HorizontalPodAutoscaler의 경우 spec.minReplicas를 0으로 설정할 수 있어요. 그러면 부하가 없을 때 워크로드가 0개 복제본까지 완전히 축소되고, 메트릭이 복제본 하나 이상이 필요하다고 나타내면 다시 확장돼요. 이것은 가끔 사용되는 큐의 소비자나 GPU 같은 전용 하드웨어가 필요한 job처럼 오래 유휴 상태로 있고 실행을 유지하는 데 비용이 드는 워크로드에 유용해요.
0으로 확장하는 것은 객체 및 외부 메트릭에만 지원돼요. 리소스 메트릭(CPU나 메모리 사용률 같은 것)에서는 사용할 수 없어요. 그런 메트릭은 실행 중인 Pod에서만 측정할 수 있기 때문이에요. minReplicas: 0을 설정하려면 객체 또는 외부 메트릭이 하나 이상 구성되어야 해요. 그렇지 않으면 API 서버가 HorizontalPodAutoscaler를 거부해요.
이 동작은 기본 활성화된 HPAScaleToZero 기능 게이트로 제어돼요. 기능 게이트는 kube-apiserver(minReplicas: 0을 허용)와 kube-controller-manager(확장을 수행) 모두에서 활성화되어야 해요.
HPA가 워크로드를 0개 복제본에 붙잡고 있는 동안, HorizontalPodAutoscaler의 status에 ScaledToZero 조건이 True로 설정되어 기록돼요. HPA는 이 조건을 사용해 자기가 0으로 확장한 워크로드(메트릭이 돌아오면 다시 확장됨)와 복제본 수를 0으로 설정해 수동으로 비활성화된 워크로드를 구분해요. 워크로드가 다시 확장되면 그 조건은 NotScaledToZero reason으로 False로 설정돼요.
암시적 유지보수 모드 비활성화
HPA 구성 자체를 변경할 필요 없이 대상에 대한 HPA를 암시적으로 비활성화할 수 있어요. 대상의 원하는 복제본 수가 0으로 설정되고 HPA의 최소 복제본 수가 0보다 크면, HPA는 대상을 조정하는 것을 중단하고(자기 자신의 ScalingActive 조건을 false로 설정) 대상의 원하는 복제본 수나 HPA의 최소 복제본 수를 수동으로 조정해 재활성화할 때까지 그 상태를 유지해요.
Deployment와 StatefulSet을 수평 자동 확장으로 마이그레이션
HPA가 활성화되면 Deployment 및/또는 StatefulSet의 spec.replicas 값을 매니페스트에서 제거하는 것이 권장돼요. 이렇게 하지 않으면, 예를 들어 kubectl apply -f deployment.yaml로 그 객체에 변경이 적용될 때마다 Kubernetes가 현재 Pod 수를 spec.replicas 키의 값으로 확장하라고 지시해요. 이것은 원하지 않을 수 있고 HPA가 활성 상태일 때 쓰래싱이나 플래핑 동작을 일으켜 골치 아플 수 있어요.
spec.replicas의 제거는 이 키의 기본값이 1이므로(Deployment Replicas 참고) Pod 수의 일회성 저하를 초래할 수 있다는 점을 유의하세요. 업데이트 시 모든 Pod 중 1개를 제외한 모든 Pod의 종료 절차가 시작돼요. 이후의 deployment 적용은 정상적으로 동작하고 원하는 대로 롤링 업데이트 구성을 존중해요. 이 저하를 피하려면 deployment를 수정하는 방식에 따라 다음 두 방법 중 하나를 선택할 수 있어요.
- 클라이언트 측 적용(Client Side Apply)(기본값):
kubectl apply edit-last-applied deployment/<deployment_name>을 실행해요. 편집기에서spec.replicas를 제거해요. 저장하고 편집기를 나가면 kubectl이 업데이트를 적용해요. 이 단계에서는 Pod 수 변경이 일어나지 않아요. - 서버 측 적용(Server Side Apply): 매니페스트에서
spec.replicas를 제거할 수 있어요. 소스 코드 관리를 사용한다면 변경 사항을 커밋하거나 소스 코드 수정에 적합한 다른 단계를 밟아 업데이트를 추적하세요. 이제부터kubectl apply -f deployment.yaml을 실행할 수 있어요.
다음으로 볼 것 (What's next)
클러스터에서 자동 확장을 구성한다면, 올바른 수의 노드를 실행하고 있는지 확인하기 위해 노드 자동 확장 사용도 고려할 수 있어요. 수직 Pod 자동 확장에 대해서도 더 읽을 수 있어요.
HorizontalPodAutoscaler에 대한 더 많은 정보:
- 수평 pod 자동 확장의 둘러보기 예시 읽기
kubectl autoscale문서 읽기- 자체 커스텀 메트릭 어댑터를 작성하고 싶다면 boilerplate 확인하기
- HorizontalPodAutoscaler의 API 참조 읽기