DevOps/Kubernetes

[Kubernetes] AWS EKS - Clustering Autoscaling (클러스터 오토스케일링)

TTOII 2022. 6. 13. 11:04
728x90

🚀 Cluster Autoscaler

AutoScaling - Amazon EKS

 

EKS의 각각의 워커 노드를 EC2 인스턴스로 구성했을 때 파드의 크기가 아주 작다고해도 무한정의 파드를 배치할 수는 없다.

 

여러명의 개발자가 여러개의 파드를 배치하거나 HPA(Horizontal Pod AutoScaling)에 의해 여러개의 파드가 만들어지면,

노드가 가득 차버려서 파드가 스케줄링 될 수 없어 pending 상태에 머무르는 상황이 발생한다.

 

이럴 때 사용하는 것이 Cluster Autoscaling(CA)이다.

 

CA는 리소스 부족으로 인해 예약할 수 없는 파드가 있는 경우 클러스터의 크기를 늘린다. 

특정 수의 시스템을 초과해 확장 또는 축소하지 않도록 구성할 수 있다.

 

워커 노드의 확장 결정을 내리는 순서는 다음과 같다.

  1. CA가 활성화되면 CA 알고리즘이 pending 상태의 파드를 확인한다.
  2. CA는 새로 프로비저닝된 노드를 요청한다.
  3. 쿠버네티스는 기본 인프라(ex. AWS)에 의해 프로비저닝된 새 노드를 감지한다.
  4. 쿠버네티스 스케줄러는 보류 중인 파드를 새 노드에 할당한다.
  5. 보류 상태의 파드가 여전히 존재하면 단계 1로 돌아간다.

 

워커 노드의 축소 결정을 내리는 순서는 다음과 같다.

  1. 노드를 삭제하는 것이 안전한지 확인하는 프로세스는 해당 노드에 대한 파드 요청이 사용자 정의 임계값 (default는 50% 요청 사용률)보다 낮을 때 시작된다. 
  2. 이 노드 축소는 실제 CPU/Memory 사용량을 고려하지 않는 대신 리소스 요청만 살펴본다.
  3. 노드가 해당 검사를 통과하면 실제 쿠버네티스 스케줄링 알고리즘이 호출되어 해당 노드에서 실행 중인 파드를 다른 곳으로 이동할 수 있는지의 여부를 결정한다.
  4. 클러스터 자동 확장 처리는 노드의 각 파드에서 다음 검사를 실행하여 서비스 중단 가능성을 최소화한다.

 

Clustering Autoscaling을 위해서는 Metrics Server가 구성되어야 한다. 

 

 

수동 스케일링

eksctl scale nodegroup --name myeks-ng1 --cluster myeks-custom --nodes 2
PS C:\Users\Shinsohui\aws-eks> eksctl get nodegroup --cluster myeks-custom
CLUSTER         NODEGROUP       STATUS  CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY        INSTANCE TYPE   IMAGE ID        ASG NAME                                               TYPE
myeks-custom    myeks-ng1       ACTIVE  2022-05-31T14:18:59Z    2               4               3                       t3.medium       AL2_x86_64      eks-myeks-ng1-e6c08d3d-f18d-78cb-5fbf-1f97663fc565     managed

 

자동 스케일링

curl -o cluster-autoscaler-autodiscover.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/aws/examples/cluster-autoscaler-autodiscover.yaml

 

cluster-autoscaler-autodiscover.yaml

163: - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/myeks-custom

cluster-autoscaler-autodiscover.yaml 파일에서 해당 163번째 라인을 다음과 같이 변경한다.

 

kubectl apply -f cluster-autoscaler-autodiscover.yaml

수정한 cluster-autoscaler-autodiscover.yaml 파일을 적용시킨다. 

 

PS C:\Users\Shinsohui\aws-eks\ca> kubectl get po -n kube-system
cluster-autoscaler-894774d4f-pbjjz              1/1     Running   0          10s
PS C:\Users\Shinsohui\aws-eks\ca> kubectl -n kube-system describe sa cluster-autoscaler
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::471702632719:role/eksctl-myeks-custom-addon-iamserviceaccount-Role1-WPSNTCTVMI7L
PS C:\Users\Shinsohui\aws-eks\ca> kubectl -n kube-system get deploy
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           58m
cluster-autoscaler             1/1     1            1           2m9s
coredns                        2/2     2            2           116m
ebs-csi-controller             2/2     2            2           17m
metrics-server                 1/1     1            1           13m
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"

spec.template.matadata.annotations에 해당 내용을 추가한다.

 

kubectl -n kube-system edit deployment.apps/cluster-autoscaler

      - command:
        - ./cluster-autoscaler
        - --v=4
        - --stderrthreshold=info
        - --cloud-provider=aws
        - --skip-nodes-with-local-storage=false
        - --expander=least-waste
        - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/myeks-custom
        - --balance-similar-node-groups
        - --skip-nodes-with-system-pods=false
        image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.22.6
kubectl set image deployment cluster-autoscaler -n kube-system cluster-autoscaler=k8s.gcr.io/autoscaling/cluster-autoscaler:v1.22.2

또는 다음 명령을 실행한다.

 

PS C:\Users\Shinsohui\aws-eks\ca> kubectl get deploy -n kube-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           71m
cluster-autoscaler             1/1     1            1           15m
coredns                        2/2     2            2           129m
ebs-csi-controller             2/2     2            2           30m
metrics-server                 1/1     1            1           26m

PS C:\Users\Shinsohui\aws-eks\ca> kubectl get rs -n kube-system
NAME                                      DESIRED   CURRENT   READY   AGE
aws-load-balancer-controller-5d9867ff4d   2         2         2       71m
cluster-autoscaler-58554f79c6             1         1         1       6m47s
cluster-autoscaler-66965d55c6             1         1         0       2m47s
cluster-autoscaler-894774d4f              0         0         0       15m
coredns-556f6dffc4                        2         2         2       129m
ebs-csi-controller-84bcf56778             2         2         2       30m
metrics-server-64cf6869bd                 1         1         1       26m
PS C:\Users\Shinsohui\aws-eks\ca> kubectl get nodes
NAME                                                 STATUS   ROLES    AGE    VERSION
ip-192-168-112-98.ap-northeast-2.compute.internal    Ready    <none>   148m   v1.22.6-eks-7d68063
ip-192-168-159-84.ap-northeast-2.compute.internal    Ready    <none>   148m   v1.22.6-eks-7d68063

시간이 지나면 스케일 다운이 완료된다.

 

Deployment, ReplicaSet을 생성할 때 requests, limits을 지정하지 않으면 무한대에 근사한 양을 사용할 수 있다.

따라서 requests, limits을 세팅해야 한다.
Deployment, ReplicaSet를 생성하고 파드의 개수를 점점 늘리면 CA에 의해 노드가 자동으로 생성된다.

 

 

🚀 샘플 코드

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
              memory: 200M
            limits:
              cpu: 200m
              memory: 200M
PS C:\Users\Shinsohui\aws-eks\ca> kubectl get deploy -n kube-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           106m
cluster-autoscaler             1/1     1            1           50m
coredns                        2/2     2            2           164m
ebs-csi-controller             2/2     2            2           65m
metrics-server                 1/1     1            1           61m
PS C:\Users\Shinsohui\aws-eks\ca> kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
myweb-deploy-5c4cbfd766-6czb4   1/1     Running   0          6s
myweb-deploy-5c4cbfd766-vdspv   1/1     Running   0          6s

현재 2개의 파드가 있다.

 

PS C:\Users\Shinsohui\aws-eks\ca> kubectl scale deploy myweb-deploy --replicas=10
deployment.apps/myweb-deploy scaled

PS C:\Users\Shinsohui\aws-eks\ca> kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
myweb-deploy-5c4cbfd766-55smt   0/1     Pending   0          24s
myweb-deploy-5c4cbfd766-686zs   1/1     Running   0          24s
myweb-deploy-5c4cbfd766-6czb4   1/1     Running   0          57s
myweb-deploy-5c4cbfd766-9v2tx   1/1     Running   0          24s
myweb-deploy-5c4cbfd766-bscb8   1/1     Running   0          24s
myweb-deploy-5c4cbfd766-fdjhx   0/1     Pending   0          24s
myweb-deploy-5c4cbfd766-j7h8j   0/1     Pending   0          24s
myweb-deploy-5c4cbfd766-rb4qk   1/1     Running   0          24s
myweb-deploy-5c4cbfd766-s79mh   1/1     Running   0          24s
myweb-deploy-5c4cbfd766-vdspv   1/1     Running   0          57s
PS C:\Users\Shinsohui\aws-eks\ca> kubectl get po -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP                NODE                                                NOMINATED NODE   READINESS GATES
myweb-deploy-5c4cbfd766-55smt   0/1     Pending   0          42s   <none>            <none>                                              <none>           <none>
myweb-deploy-5c4cbfd766-686zs   1/1     Running   0          42s   192.168.149.73    ip-192-168-159-84.ap-northeast-2.compute.internal   <none>           <none>
myweb-deploy-5c4cbfd766-6czb4   1/1     Running   0          75s   192.168.106.215   ip-192-168-112-98.ap-northeast-2.compute.internal   <none>           <none>
myweb-deploy-5c4cbfd766-9v2tx   1/1     Running   0          42s   192.168.106.206   ip-192-168-112-98.ap-northeast-2.compute.internal   <none>           <none>
myweb-deploy-5c4cbfd766-bscb8   1/1     Running   0          42s   192.168.123.147   ip-192-168-112-98.ap-northeast-2.compute.internal   <none>           <none>
myweb-deploy-5c4cbfd766-fdjhx   0/1     Pending   0          42s   <none>            <none>                                              <none>           <none>
myweb-deploy-5c4cbfd766-j7h8j   0/1     Pending   0          42s   <none>            <none>                                              <none>           <none>
myweb-deploy-5c4cbfd766-rb4qk   1/1     Running   0          42s   192.168.144.199   ip-192-168-159-84.ap-northeast-2.compute.internal   <none>           <none>
myweb-deploy-5c4cbfd766-s79mh   1/1     Running   0          42s   192.168.123.129   ip-192-168-112-98.ap-northeast-2.compute.internal   <none>           <none>
myweb-deploy-5c4cbfd766-vdspv   1/1     Running   0          75s   192.168.145.15    ip-192-168-159-84.ap-northeast-2.compute.internal   <none>           <none>

파드 3개는 생성되지 못했다.

 

PS C:\Users\Shinsohui\aws-eks\ca> kubectl describe po myweb-deploy-5c4cbfd766-55smt

Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Normal   TriggeredScaleUp  2m 28s                   cluster-autoscaler  pod triggered scale-up: [{eks-myeks-ng1-e6c08d3d-f18d-78cb-5fbf-1f97663fc565 2->3 (max: 4)}]     
  Warning  FailedScheduling  24s (x4 over 2m54s)  default-scheduler  0/2 nodes are available: 2 Insufficient cpu.

Pending 상태의 파드가 trigger로 작동해 워커 노드를 2개에서 3개로 늘린다.
워커 노드가 3개가 되면 파드는 Pending → Running 상태로 변한다.
다음과 같이 워커 노드도 스케일링 할 수 있다.

728x90