[Kubernetes] HPA(Horizontal Pod Autoscaling)란?
HPA(Horizontal Pod Autoscaling)는 워크로드를 자동으로 업데이트하며
Deployment, ReplicaSets, StatefulSet의 복제본 개수를 조정한다.
Metric이 Pod의 CPU 사용량을 측정해서 HPA에 전달하고(HPA는 Metric을 모니터링하고),
실제로 Pod의 수를 늘리거나 줄이는것은 ReplicaSet이나 Deployment에 의해서 컨트롤 된다.
CPU 등의 리소스 사용량이 증가 하면 Pod 개수를 늘리고, 리소스 사용량이 감소하면 다시 Pod 개수를 줄인다.
따라서 HPA를 사용하기 위해서는 사용량을 측정하기 위해 반드시 Metric 서버가 필요하다.
단, HPA는 크기를 조정할 수 없는 Object (ex : DaemonSet, Service 등)에는 적용되지 않는다.
AutoScaling 대상
- Pod
- HPA : Horizontal Pod Autoscaling
- VPA : Vertical Pod Autoscaler --> Cloud에서만 가능
- 수직적으로 파드의 크기를 조정(Request,Limit 실시간 조정)
- Node
- ClusterAutoScaler --> Cloud에서만 가능
리소스 확인
$ kubectl api-resources| grep hpa
horizontalpodautoscalers hpa autoscaling/v1 true HorizontalPodAutoscaler
리소스 정의 방법 확인
$ kubectl explain hpa.spec
scaleTargetRef
hpa.spec.scaleTargetRef
오토스케일링할 리소스에 관한 내용을 작성하는 것으로, required 필드이다.
apiVersion
kind(required)
name(required)
targetCPUUtilizationPercentage
hpa.spec.targetCPUUtilizationPercentage
CPU사용률이 몇 퍼센트를 넘어갔을 때 스케일링 할 것인지 정의한다.
☁️ 참고
HPA 버전v2beta2
의 metrics
는 targetCPUUtilizationPercentage
와 유사한 것으로,
metrics
는 CPU 뿐만 아니라 다양한 다른 metric들을 확인할 수 있다.
$ kubectl explain hpa.spec.metrics --api-version autoscaling/v2beta2
...
FIELDS:
containerResource <Object>
container resource refers to a resource metric (such as those specified in
requests and limits) known to Kubernetes describing a single container in
each pod of the current scale target (e.g. CPU or memory). Such metrics are
built in to Kubernetes, and have special scaling options on top of those
available to normal per-pod metrics using the "pods" source. This is an
alpha feature and can be enabled by the HPAContainerMetrics feature flag.
external <Object>
external refers to a global metric that is not associated with any
Kubernetes object. It allows autoscaling based on information coming from
components running outside of cluster (for example length of queue in cloud
messaging service, or QPS from loadbalancer running outside of cluster).
object <Object>
object refers to a metric describing a single kubernetes object (for
example, hits-per-second on an Ingress object).
pods <Object>
pods refers to a metric describing each pod in the current scale target
(for example, transactions-processed-per-second). The values will be
averaged together before being compared to the target value.
resource <Object>
resource refers to a resource metric (such as those specified in requests
and limits) known to Kubernetes describing each pod in the current scale
target (e.g. CPU or memory). Such metrics are built in to Kubernetes, and
have special scaling options on top of those available to normal per-pod
metrics using the "pods" source.
type <string> -required-
type is the type of metric source. It should be one of "ContainerResource",
"External", "Object", "Pods" or "Resource", each mapping to a matching
field in the object. Note: "ContainerResource" type is available on when
the feature-gate HPAContainerMetrics is enabled
minReplicas
hpa.spec.minReplicas
파드의 최소 개수
maxReplicas
hpa.spec.maxReplicas
파드의 최대 개수로, required 필드이다.
HPA 알고리즘
원하는 레플리카 수 = ceil[현재 레플리카 수 * ( 현재 메트릭 값 / 원하는 메트릭 값 )]
워크로드 스케일링의 안정성
너무 자주 스케일링하게 되면, 리소스가 많이 소모되기 때문에 오히려 역효과가 날 수 있다.
이렇게 경계를 계속 넘나드는 형태를 thrashing 또는 flapping이라고 불린다.
안정한 윈도우
임계값을 넘어가는 상황이 일정 시간 이상 지속되었을 때 스케일링한다.
기본적으로 세팅되어있는 것이 300초이다.
- 스케일 아웃: 180초
- 스케일 인: 300초
예시
behavior:
scaleDown:
stabilizationWindowSeconds: 300
💻 실습 : HPA를 이용한 AutoScaling
myweb-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myweb-deploy
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb
ports:
- containerPort: 8080
myweb-hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: myweb-hpa
spec:
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50
scaleTargetRef:
kind: Deployment
name: myweb-deploy
$ kubectl create -f myweb-deploy.yaml -f myweb-hpa.yaml
hpa를 확인해보면 TARGETS이 <unknown>
인 것을 확인할 수 있는데,
원래라면 시간이 조금 지나면 값으로 측정되어 나타난다.
$ kubectl get deploy,rs,po,hpa
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/myweb-deploy 2/2 2 2 6s
NAME DESIRED CURRENT READY AGE
replicaset.apps/myweb-deploy-657f957c85 2 2 2 6s
NAME READY STATUS RESTARTS AGE
pod/myweb-deploy-657f957c85-cskms 1/1 Running 0 6s
pod/myweb-deploy-657f957c85-n6dqh 1/1 Running 0 6s
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/myweb-hpa Deployment/myweb-deploy <unknown>/50% 1 10 0 6s
그러나 이 상황에서는 아무리 기다려도 <unknown>
이 사라지지 않는다.
왜일까❔❔
kubectl describe
명령어로 Events를 보면, missing request for cpu
를 확인할 수 있다.
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedGetResourceMetric 2s (x8 over 107s) horizontal-pod-autoscaler failed to get cpu utilization: missing request for cpu
Warning FailedComputeMetricsReplicas 2s (x8 over 107s) horizontal-pod-autoscaler invalid metrics (1 invalid out of 1), first error is: failed to get cpu utilization: missing request for cpu
deployment에 request 설정이 안되어있기 때문이다.
관리되는 대상은 Request 설정이 되어있어야한다.⭐
다음과 같이 request
를 포함하여 수정 후, apply하면 <unknown>
이 값으로 변경된 것을 확인할 수 있다.
myweb-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myweb-deploy
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
ports:
- containerPort: 8080
resources:
requests:
cpu: 200m
limits:
cpu: 200m
$ kubectl apply -f myweb-deploy.yaml
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myweb-hpa Deployment/myweb-deploy 0%/50% 1 10 2 5m27s
이제 스케일링을 확인하기 위해 파드에 인위적으로 부하를 가해보자.
$ kubectl get po
NAME READY STATUS RESTARTS AGE
myweb-deploy-6dcf6c95c6-dmw84 1/1 Running 0 3m49s
$ kubectl exec myweb-deploy-6dcf6c95c6-dmw84 -- sha256sum /dev/zero
잠시후 CPU 사용률이 점점 증가하고,
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myweb-hpa Deployment/myweb-deploy 13%/50% 1 10 1 4m33s
Replicas가 3으로 스케일링되어, 파드가 새로 생성된 것을 확인할 수 있다.
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myweb-hpa Deployment/myweb-deploy 33%/50% 1 10 3 6m35s
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
myweb-deploy-6dcf6c95c6-dmw84 201m 1Mi
myweb-deploy-6dcf6c95c6-kmm4n 0m 1Mi
myweb-deploy-6dcf6c95c6-z68j8 0m 1Mi
☁️ 참고
myweb-hpa.yaml
를 버전v2beta2
로 작성하면 다음과 같다.
myweb-hpa-v2beta2.yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: myweb-hpa
spec:
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization #비율
avarageUtilization: 50
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myweb-deploy
myweb-hpa.yaml
과 myweb-hpa-v2beta2.yaml
은 완벽하게 똑같이 작동하는 HPA이다.
참고