시작하기 전에

제약사항

현재 지원 버전은 Beta 이며 기능에 제한이 있습니다.

  • Multi Node pool 미지원
  • Cluster Autoscaler Version 자동 Upgrade 미지원
  • Helm을 통한 설치만 지원

Kubernetes에서는 다음 기능을 통해 클러스터를 자동으로 확장하거나 축소되도록 할 수 있습니다.

Horizontal Pod Autoscaler는 현재 Pod이 사용 중인 자원에 따라서 필요한 Pod의 개수를 증가시키거나 감소시킵니다.

Cluster Autoscaler 는 클러스터의 사용가능한 자원과 Pod 이 요청하는 자원량을 비교 하여 Node 를 증가시키거나 감소시킵니다.

두가지 Autoscaler 를 사용하면 클러스터 부하에 따라서 Pod, Node 갯수를 자동으로 조절되도록 할 수 있습니다.

이 가이드에서는 Cluster Autoscaler에 대한 설명과 설치방법에 대해서 설명합니다.

Cluster Autoscaler

자동 조절 방식

  • 사용자가 요청한 Pod의 자원량 보다 현재 Cluster의 자원이 부족한 경우 노드 증가
  • 일정 시간 동안 특정 노드의 사용률이 저조한 경우 해당 노드 감소

Cluster Autoscaler는 현재 사용 중인 자원 기반으로 동작하지 않습니다. 따라서 Pod의 부하가 아무리 높더라도 요청한 자원량이 없다면 Node가 증가하지 않습니다.

노드 감소 예외

아래와 같은 경우에 노드 사용률이 저조하여도 해당 노드는 축소되지 않습니다.

  • Controller (ex. Deployment, StatefulSet .. )에 의해 제어되지 않는 경우
  • Local Storage가 설정되어 있는 경우
  • 다른 노드로 Pod이 이동할 수 없는 경우
  • Annotation "cluster-autoscaler.kubernetes.io/safe-to-evict": "false"이 설정되어 있는 경우

좀 더 자세한 예외 상황에 대해서는 링크를 참조하세요.

적용하기

Helm 설치

현재 버전에서 Cluster Autoscaler 설치는 Helm 을 통한 설치만 지원하므로

Helm 이 설치되어 있지 않다면 helm 설치가이드를 따라 Helm 설치를 진행합니다.

Ncloud Repository 추가

Cluster Autoscaler를 설치하기 위해 Ncloud Repository를 추가합니다.

$ helm repo add ncloud https://navercloudplatformdeveloper.github.io/helm-charts

Cluster Autoscaler 설치

Cluster Autoscaler 설치 시 현재 설치하고자 하는 Cluster의 버전에 맞게 설치를 진행해야 합니다. Kubernetes Version 별로 지원되는 버전은 다음과 같습니다.

Kubernetes Version CA Version
1.12.7 1.12.7-beta-201909190000

추가로 --set 을 통하여 설치 옵션을 지정할 수 있습니다. 현재 Helm으로 설치 시 지원하는 옵션은 다음과 같습니다.

옵션 설명 기본값
min 최소 노드 수 1
max 최대 노드 수 3
$ helm --kubeconfig=$KUBE_CONFIG install ncloud/autoscaler \
--set min=1 \
--set max=3 \
--version [Cluster Autoscaler Version]

정상 동작 확인

설치가 제대로 완료 되었다면 ConfigMap 에서 현재 Cluster Autoscaler 의 상태를 확인하실수 있습니다.

$ kubectl --kubeconfig $KUBE_CONFIG get cm cluster-autoscaler-status -o yaml -n kube-system

apiVersion: v1
data:
  status: |+
    Cluster-autoscaler status at 2019-09-03 08:59:53.84165088 +0000 UTC:
    Cluster-wide:
      Health:      Healthy (ready=1 unready=0 notStarted=0 longNotStarted=0 registered=1 longUnregistered=0)
                   LastProbeTime:      2019-09-03 08:59:53.70167178 +0000 UTC m=+23.846174142
                   LastTransitionTime: 2019-09-03 08:59:43.520248394 +0000 UTC m=+13.664750787
      ScaleUp:     NoActivity (ready=1 registered=1)
                   LastProbeTime:      2019-09-03 08:59:53.70167178 +0000 UTC m=+23.846174142
                   LastTransitionTime: 2019-09-03 08:59:43.520248394 +0000 UTC m=+13.664750787
      ScaleDown:   NoCandidates (candidates=0)
                   LastProbeTime:      2019-09-03 08:59:53.70167178 +0000 UTC m=+23.846174142
                   LastTransitionTime: 2019-09-03 08:59:43.520248394 +0000 UTC m=+13.664750787

    NodeGroups:
      Name:        k8s-default-group
      Health:      Healthy (ready=1 unready=0 notStarted=0 longNotStarted=0 registered=1 longUnregistered=0 cloudProviderTarget=1 (minSize=1, maxSize=5))
                   LastProbeTime:      2019-09-03 08:59:53.70167178 +0000 UTC m=+23.846174142
                   LastTransitionTime: 2019-09-03 08:59:43.520248394 +0000 UTC m=+13.664750787
      ScaleUp:     NoActivity (ready=1 cloudProviderTarget=1)
                   LastProbeTime:      2019-09-03 08:59:53.70167178 +0000 UTC m=+23.846174142
                   LastTransitionTime: 2019-09-03 08:59:43.520248394 +0000 UTC m=+13.664750787
      ScaleDown:   NoCandidates (candidates=0)
                   LastProbeTime:      2019-09-03 08:59:53.70167178 +0000 UTC m=+23.846174142
                   LastTransitionTime: 2019-09-03 08:59:43.520248394 +0000 UTC m=+13.664750787

kind: ConfigMap
metadata:
  annotations:
    cluster-autoscaler.kubernetes.io/last-updated: 2019-09-03 08:59:53.84165088 +0000
      UTC
  creationTimestamp: 2019-09-03T08:59:31Z
  name: cluster-autoscaler-status
  namespace: kube-system
  resourceVersion: "426558451"
  selfLink: /api/v1/namespaces/kube-system/configmaps/cluster-autoscaler-status
  uid: 248a8014-ce29-11e9-8a51-f220cd8c2e67

사용 예시

Horizontal Pod Autoscaler와 Cluster Autoscaler가 설치된 Cluster에 부하 테스트를 진행하여

Pod 과 Node 가 증가되는 모습을 확인해 보겠습니다.

Cluster 준비 및 Metric Server 정상유무 확인

Node가 1개인 Cluster 를 생성합니다.

$ kubectl --kubeconfig $KUBE_CONFIG get nodes

NAME             STATUS    ROLES     AGE       VERSION
nks-worker-5uh   Ready     node      3h        v1.12.7

Metrics Server 가 정상적으로 동작하는지 확인합니다.

Metric 정보 수집까지 약간의 시간이 걸릴 수 있습니다.

$ kubectl --kubeconfig $KUBE_CONFIG top node

NAME                  CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%
nks-worker-5uh   94m          4%        1330Mi          36%

적용하기를 참고하여 Cluster Autoscaler를 설치합니다.

HPA 설정 및 부하 테스트

HPA 설정 및 부하테스트는 아래 링크를 참고하여 php-apache 서버 구동 및 노출부터 부하 증가 까지 진행을 합니다.

Horizontal Pod Autoscaler 연습

부하 테스트를 진행하게 되면 아래와 같이 Pod의 개수가 자동으로 증가한 것을 확인할 수 있습니다.

예시에서 사용한 Cluster의 Node의 자원 사용량이 모든 Pod의 요청량보다 적기 때문에 아직 Node는 증가하지 않습니다.

Cluster 설치시 지정한 Node 사양에 따라서 결과가 다를 수 있습니다.

$ kubectl --kubeconfig $KUBE_CONFIG get hpa

NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   46%/50%   1         10        5          28m

$ kubectl --kubeconfig $KUBE_CONFIG get pods

NAME                               READY     STATUS    RESTARTS   AGE
php-apache-f67db78b-2lvww          1/1       Running   0          28m
php-apache-f67db78b-hbc86          1/1       Running   0          2m
php-apache-f67db78b-mppcl          1/1       Running   0          2m
php-apache-f67db78b-pctkv          1/1       Running   0          2m
php-apache-f67db78b-wr5dh          1/1       Running   0          2m

HPA 설정 변경

Horizontal Pod Autoscaler 의 cpu 상한값을 50에서 20으로 변경 합니다.

$ kubectl --kubeconfig $KUBE_CONFIG patch hpa php-apache --patch '{"spec":{"targetCPUUtilizationPercentage":20}}'

Node의 가용량이 Pod의 자원 요청량보다 적기때문에 Pending 상태의 Pod 이 증가하게 됩니다.

$ kubectl --kubeconfig $KUBE_CONFIG get pods

NAME                               READY     STATUS    RESTARTS   AGE
php-apache-f67db78b-nz6zq          0/1       Pending   0          3m
php-apache-f67db78b-x2gr9          0/1       Pending   0          3m
php-apache-f67db78b-2lvww          1/1       Running   0          41m
php-apache-f67db78b-hbc86          1/1       Running   0          15m
php-apache-f67db78b-mppcl          1/1       Running   0          15m
php-apache-f67db78b-p2q6r          1/1       Running   0          3m
php-apache-f67db78b-pctkv          1/1       Running   0          15m
php-apache-f67db78b-r8whp          1/1       Running   0          3m
php-apache-f67db78b-sjrh7          1/1       Running   0          3m
php-apache-f67db78b-wr5dh          1/1       Running   0          15m

Node 증가

사용자가 요청한 Pod의 자원량 보다 현재 Cluster의 자원이 부족한 경우 노드 증가 의 조건을 만족하게 되면서

Cluster Autoscaler 가 동작하여 현재 Pod의 추가 요청량에 따라 필요한 Node 갯수 cloudProviderTarget 를 판단하게 되고 현재 Cluster 에서는 추가로 필요한 Node 를 1대로 판단하여 전체 Node 갯수를 2로 늘리도록 요청하게 됩니다.

ConfigMap을 통해 현재 목표 갯수 cloudProviderTarget 를 확인할 수 있습니다.

$ kubectl --kubeconfig $KUBE_CONFIG get cm cluster-autoscaler-status -o yaml -n kube-system

apiVersion: v1
data:
  status: |+
    Cluster-autoscaler status at 2019-09-03 09:53:35.841671859 +0000 UTC:
    Cluster-wide:
      Health:      Healthy (ready=1 unready=0 notStarted=0 longNotStarted=0 registered=1 longUnregistered=0)
                   LastProbeTime:      2019-09-03 09:53:35.645663163 +0000 UTC m=+276.303106480
                   LastTransitionTime: 2019-09-03 09:49:29.11931241 +0000 UTC m=+29.776755835
      ScaleUp:     InProgress (ready=1 registered=1)
                   LastProbeTime:      2019-09-03 09:53:35.645663163 +0000 UTC m=+276.303106480
                   LastTransitionTime: 2019-09-03 09:50:20.028647773 +0000 UTC m=+80.686091197
      ScaleDown:   NoCandidates (candidates=0)
                   LastProbeTime:      2019-09-03 09:53:35.645663163 +0000 UTC m=+276.303106480
                   LastTransitionTime: 2019-09-03 09:49:29.11931241 +0000 UTC m=+29.776755835

    NodeGroups:
      Name:        k8s-default-group
      Health:      Healthy (ready=1 unready=0 notStarted=0 longNotStarted=0 registered=1 longUnregistered=0 cloudProviderTarget=2 (minSize=1, maxSize=5))
                   LastProbeTime:      2019-09-03 09:53:35.645663163 +0000 UTC m=+276.303106480
                   LastTransitionTime: 2019-09-03 09:49:29.11931241 +0000 UTC m=+29.776755835
      ScaleUp:     InProgress (ready=1 cloudProviderTarget=2)
                   LastProbeTime:      2019-09-03 09:53:35.645663163 +0000 UTC m=+276.303106480
                   LastTransitionTime: 2019-09-03 09:50:20.028647773 +0000 UTC m=+80.686091197
      ScaleDown:   NoCandidates (candidates=0)
                   LastProbeTime:      2019-09-03 09:53:35.645663163 +0000 UTC m=+276.303106480
                   LastTransitionTime: 2019-09-03 09:49:29.11931241 +0000 UTC m=+29.776755835

kind: ConfigMap
metadata:
  annotations:
    cluster-autoscaler.kubernetes.io/last-updated: 2019-09-03 09:53:35.841671859 +0000
      UTC
  creationTimestamp: 2019-09-03T08:59:31Z
  name: cluster-autoscaler-status
  namespace: kube-system
  resourceVersion: "426684212"
  selfLink: /api/v1/namespaces/kube-system/configmaps/cluster-autoscaler-status
  uid: 248a8014-ce29-11e9-8a51-f220cd8c2e67

추가 작업이 완료되면 추가된 Node를 확인 할 수 있습니다.

$kubectl --kubeconfig $KUBE_CONFIG get nodes

NAME             STATUS    ROLES     AGE       VERSION
nks-worker-5uh   Ready     node      3h        v1.12.7
nks-worker-5ad   Ready     node      32s       v1.12.7

""에 대한 건이 검색되었습니다.

    ""에 대한 검색 결과가 없습니다.

    처리중...