VPC 환경에서 이용 가능합니다.
Kubernetes는 클러스터 자동 스케일링과 리소스 관리를 위해 Cluster Autoscaler와 Vertical Pod AutoScaler 두 가지 기능을 제공합니다. 이 중 Cluster Autoscaler를 통해 클러스터의 워커 노드를 자동으로 확장 및 축소할 수 있습니다. 이를 통해 리소스 관리가 보다 유연하고 효율적으로 이루어집니다.
이 가이드는 Ncloud Kubernetes Service에서 Cluster Autoscaler의 기능과 사용 방법을 설명합니다.
Cluster Autoscaler
Cluster Autoscaler는 Kubernetes 클러스터의 크기를 자동으로 조정하여 리소스 사용을 최적화합니다. 리소스 부족으로 인해 스케줄링 되지 못한 파드가 있을 때 클러스터를 확장합니다. 반대로, 클러스터 내 노드 중 일부가 지속적으로 낮은 리소스 사용률을 보이면 해당 노드를 축소하여 리소스 낭비를 방지합니다. 이 과정은 파드의 요구 사항과 클러스터의 현재 리소스 상황을 기반으로 자동으로 수행됩니다.
Cluster Autoscaler의 동작을 위해서는 파드의 리소스 요청(requests)과 제한(limits)이 정의되어 있어야 합니다. 이 정보는 Cluster Autoscaler가 클러스터의 리소스 사용률을 분석하고, 필요에 따라 클러스터의 크기를 조정하는 데 필수적입니다. 리소스 요청은 파드가 시작할 때 필요한 최소 리소스 양을 지정하고, 리소스 제한은 파드가 사용할 수 있는 최대 리소스 양을 제한합니다.
Cluster Autoscaler 동작 원리
Cluster Autoscaler는 클러스터의 리소스 사용률을 분석하고, 필요에 따라 클러스터의 크기를 조정합니다. 이 과정은 파드의 요구 사항과 클러스터의 현재 리소스 상황을 기반으로 자동으로 수행됩니다.
- 스케일 업 조건
- 새로 생성된 파드가 Pending 상태로 일정 시간 이상 머무르고 있으며, 현재 클러스터의 최대 노드 수와 노드풀의 maxSize 제한을 넘지 않는 경우 노드가 추가됩니다.
- Cluster Autoscaler는 Pending 파드의 리소스 요청(Requests)을 기반으로 노드 추가 여부를 결정합니다.
- 스케일 다운 조건
- 클러스터 내 노드 중 일부가 지속적으로 낮은 리소스 사용률을 보이면 해당 노드를 축소합니다.
- 노드의 CPU/Memory 요청(Requests)의 합이 노드의 allocatable 대비 scale-down-utilization-threshold(기본값: 0.5) 미만일 때 저사용 노드로 간주됩니다.
- 기본적으로 --scale-down-unneeded-time(기본값: 10분) 동안 다른 파드가 해당 노드를 필요로 하지 않으면 축소 후보로 등록됩니다.
- 이후 Cluster Autoscaler는 파드를 다른 노드로 안전하게 이동시킬 수 있는지 확인한 다음 노드를 제거합니다.
- 단 아래와 같은 경우 축소 대상에서 제외됩니다.
- Controller(예: Deployment, StatefulSet 등)에 의해 제어되지 않는 경우
- Local Storage가 설정되어 있는 경우
- 다른 노드로 Pod가 이동할 수 없는 경우
- Annotation "cluster-autoscaler.kubernetes.io/safe-to-evict": "false"가 설정되어 있는 경우
Cluster Autoscaler에 대한 자세한 내용은 Cluster Autoscaler FAQ에서 확인할 수 있습니다.
Cluster Autoscaler 활성화
Ncloud Kubernetes Service의 클러스터는 기본적으로 Cluster Autoscaler 기능이 비활성화 된 상태로 제공됩니다. 사용자는 콘솔의 노드풀 설정을 통해 이 기능을 간편하게 활성화할 수 있으며, 이를 통해 자동으로 클러스터의 크기를 조절하고 리소스 사용을 최적화할 수 있습니다.
- 네이버 클라우드 플랫폼의 콘솔에서 Services > Containers > Ncloud Kubernetes Service > Clusters 메뉴를 차례대로 클릭해 주십시오.
- Cluster Autoscaler를 활성화하고 싶은 노드풀을 선택합니다.
- 상단의 [수정] 버튼을 클릭합니다.
- [설정] 버튼을 클릭한 다음 최소 노드 수, 최대 노드 수를 기입합니다.
- 클러스터의 워커 노드 총 개수는 Cluster Autoscaler의 최대 노드 수를 포함하여 계산됩니다. 클러스터 운영 시 해당 요소를 고려하여 적절한 관리가 필요합니다.
- 최초 설정 시 현재 노드 수가 설정된 최소 노드 수보다 적을 경우에도 자동으로 노드 수를 증가시키지 않습니다. 필요한 경우 노드 수를 수동으로 조정한 다음 설정해야 합니다.
- [수정] 버튼을 클릭해 Cluster Autoscaler를 활성화합니다.
- kubectl을 통해 Cluster Autoscaler의 동작을 확인합니다.
$ kubectl get configmap -n kube-system cluster-autoscaler-status -o yaml ... data: status: | Cluster-autoscaler status at 2024-02-20 07:04:01.141727455 +0000 UTC: Cluster-wide: Health: Healthy (ready=5 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=5 longUnregistered=0) LastProbeTime: 2024-02-20 07:04:01.121214914 +0000 UTC m=+2227353.262936722 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 ScaleUp: NoActivity (ready=5 registered=5) LastProbeTime: 2024-02-20 07:04:01.121214914 +0000 UTC m=+2227353.262936722 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 ScaleDown: NoCandidates (candidates=0) LastProbeTime: 2024-02-20 07:04:01.121214914 +0000 UTC m=+2227353.262936722 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 NodeGroups: Name: node Health: Healthy (ready=2 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=2 longUnregistered=0 cloudProviderTarget=2 (minSize=1, maxSize=8)) LastProbeTime: 2024-02-20 11:25:31.98194832 +0000 UTC m=+2243044.123670024 LastTransitionTime: 2024-02-20 11:13:49.540592255 +0000 UTC m=+2242341.682313956 ScaleUp: NoActivity (ready=2 cloudProviderTarget=2) LastProbeTime: 2024-02-20 11:25:31.98194832 +0000 UTC m=+2243044.123670024 LastTransitionTime: 2024-02-20 11:25:11.920272102 +0000 UTC m=+2243024.061993805 ScaleDown: NoCandidates (candidates=0) LastProbeTime: 2024-02-20 11:25:31.98194832 +0000 UTC m=+2243044.123670024 LastTransitionTime: 2024-02-20 11:25:11.920272102 +0000 UTC m=+2243024.061993805 ...
Cluster Autoscaler 예시
Cluster Autoscaler와 Horizontal Pod Autoscaler를 사용하여 Kubernetes 클러스터에서 부하 테스트를 진행합니다. 테스트를 통해 클러스터의 파드 수와 노드 수가 동적으로 조절되는 과정을 확인할 수 있습니다.
사용된 예제는 HorizontalPodAutoscaler Walkthrough에서 상세히 확인할 수 있습니다.
-
Cluster Autoscaler를 테스트 할 클러스터를 준비합니다.
-
Cluster Autoscaler와 Metrics Server가 정상적으로 동작하는지 확인합니다.
- Cluster Autoscaler 확인
$ kubectl get configmap -n kube-system cluster-autoscaler-status -o yaml ... data: status: | Cluster-autoscaler status at 2024-02-20 07:04:01.141727455 +0000 UTC: Cluster-wide: Health: Healthy (ready=5 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=5 longUnregistered=0) LastProbeTime: 2024-02-20 07:04:01.121214914 +0000 UTC m=+2227353.262936722 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 ScaleUp: NoActivity (ready=5 registered=5) LastProbeTime: 2024-02-20 07:04:01.121214914 +0000 UTC m=+2227353.262936722 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 ScaleDown: NoCandidates (candidates=0) LastProbeTime: 2024-02-20 07:04:01.121214914 +0000 UTC m=+2227353.262936722 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 NodeGroups: Name: node Health: Healthy (ready=2 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=2 longUnregistered=0 cloudProviderTarget=2 (minSize=1, maxSize=8)) LastProbeTime: 2024-02-20 11:25:31.98194832 +0000 UTC m=+2243044.123670024 LastTransitionTime: 2024-02-20 11:13:49.540592255 +0000 UTC m=+2242341.682313956 ScaleUp: NoActivity (ready=2 cloudProviderTarget=2) LastProbeTime: 2024-02-20 11:25:31.98194832 +0000 UTC m=+2243044.123670024 LastTransitionTime: 2024-02-20 11:25:11.920272102 +0000 UTC m=+2243024.061993805 ScaleDown: NoCandidates (candidates=0) LastProbeTime: 2024-02-20 11:25:31.98194832 +0000 UTC m=+2243044.123670024 LastTransitionTime: 2024-02-20 11:25:11.920272102 +0000 UTC m=+2243024.061993805 ...- Metrics Server 확인
$ kubectl top pods -n kube-system NAME CPU(cores) MEMORY(bytes) cilium-mct9p 7m 96Mi cilium-operator-846758784c-t2hpj 2m 21Mi cilium-qqwdl 6m 88Mi cilium-sspl4 6m 88Mi ... -
php-apache deployment를 클러스터에 배포합니다.
$ kubectl apply -f https://k8s.io/examples/application/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 -
HorizontalPodAutoscaler(HPA)를 생성하고 확인합니다.
- HPA 생성
$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10- HPA 확인
$ kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 0%/50% 1 10 1 144m -
부하를 일으켜 파드의 증가를 확인합니다.
- 별도의 터미널에서 부하 증가
$ 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"- HPA 관측 및 레플리카 수 증가 확인
$ kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 106%/50% 1 10 7 154m -
신규로 생성 된 파드의 Pending을 확인하고, Cluster Autosclaer의 동작을 확인합니다.
- 파드의 Pending 상태 확인
$ kubectl get pods -o wide | grep php-apache ... php-apache-78c9f8cbf6-4n794 0/1 Pending 0 20s php-apache-78c9f8cbf6-c8xdc 0/1 Pending 0 24s php-apache-78c9f8cbf6-t75w2 0/1 Pending 0 24s php-apache-78c9f8cbf6-wc98s 1/1 Running 0 24s ...- Cluster Autoscaler 동작 확인
$ kubectl get configmap -n kube-system cluster-autoscaler-status -o yaml ... Cluster-wide: Health: Healthy (ready=3 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=3 longUnregistered=0) LastProbeTime: 2024-02-20 11:15:50.82048015 +0000 UTC m=+2242462.962201862 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 ScaleUp: InProgress (ready=3 registered=3) LastProbeTime: 2024-02-20 11:15:50.82048015 +0000 UTC m=+2242462.962201862 LastTransitionTime: 2024-02-20 11:14:29.611869206 +0000 UTC m=+2242381.753590773 ScaleDown: NoCandidates (candidates=0) LastProbeTime: 2024-02-20 11:15:50.82048015 +0000 UTC m=+2242462.962201862 LastTransitionTime: 2024-01-25 12:22:06.170599081 +0000 UTC m=+38.312320847 NodeGroups: Name: node Health: Healthy (ready=1 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=1 longUnregistered=0 cloudProviderTarget=2 (minSize=1, maxSize=8)) LastProbeTime: 2024-02-20 11:15:50.82048015 +0000 UTC m=+2242462.962201862 LastTransitionTime: 2024-02-20 11:13:49.540592255 +0000 UTC m=+2242341.682313956 ScaleUp: InProgress (ready=1 cloudProviderTarget=2) LastProbeTime: 2024-02-20 11:15:50.82048015 +0000 UTC m=+2242462.962201862 LastTransitionTime: 2024-02-20 11:14:29.611869206 +0000 UTC m=+2242381.753590773 ScaleDown: NoCandidates (candidates=0) LastProbeTime: 2024-02-20 11:15:50.82048015 +0000 UTC m=+2242462.962201862 LastTransitionTime: 2024-02-20 11:13:49.540592255 +0000 UTC m=+2242341.682313956 ... -
워커 노드의 확장 및 파드의 스케줄링을 확인합니다.
- 워커노드 확장 확인
$ kubectl get nodes NAME STATUS ROLES AGE VERSION node-1 Ready <none> 13m v1.27.9 node-2 Ready <none> 2m8s v1.27.9 node-3 Ready <none> 88d v1.27.9 node-4 Ready <none> 15d v1.27.9- 파드의 Running 상태 확인
$ kubectl get pods | grep php-apache -
부하가 중지되면 파드의 수가 줄어듭니다. 이후 Cluster Autoscaler는 노드의 리소스 사용량을 관찰하여 필요에 따라 워커 노드의 수를 줄여 클러스터의 규모를 축소합니다.
- 클러스터를 구성할 때 선택한 노드의 사양에 따라 결과가 달라질 수 있으므로, 테스트 전에 노드 사양을 적절히 고려해야 합니다.
- 부하가 중지된 후에도, 특정 조건으로 인해 노드 감소가 즉시 발생하지 않을 수 있습니다. 예를 들어, 노드에 중요한 시스템 파드가 실행 중이거나, 로컬 스토리지를 사용하는 파드가 있을 경우 노드 감소가 제한될 수 있습니다.
- 부하 테스트를 통한 클러스터의 확장 및 축소는 실제 운영 환경에서의 성능과 다를 수 있으므로, 테스트 결과를 토대로 실제 환경에 적용하기 전에 충분한 검토가 필요합니다.
문제 해결
Cluster Autoscaler 사용 도중 발생한 문제는 Ncloud Kubernetes Service 문제 해결 - 확장성 및 성능 문제을 참조해 주십시오.