[Kubernetes] AWS EKS - Clustering Autoscaling (클러스터 오토스케일링)
🚀 Cluster Autoscaler
EKS의 각각의 워커 노드를 EC2 인스턴스로 구성했을 때 파드의 크기가 아주 작다고해도 무한정의 파드를 배치할 수는 없다.
여러명의 개발자가 여러개의 파드를 배치하거나 HPA(Horizontal Pod AutoScaling)에 의해 여러개의 파드가 만들어지면,
노드가 가득 차버려서 파드가 스케줄링 될 수 없어 pending 상태에 머무르는 상황이 발생한다.
이럴 때 사용하는 것이 Cluster Autoscaling(CA)이다.
CA는 리소스 부족으로 인해 예약할 수 없는 파드가 있는 경우 클러스터의 크기를 늘린다.
특정 수의 시스템을 초과해 확장 또는 축소하지 않도록 구성할 수 있다.
워커 노드의 확장 결정을 내리는 순서는 다음과 같다.
- CA가 활성화되면 CA 알고리즘이 pending 상태의 파드를 확인한다.
- CA는 새로 프로비저닝된 노드를 요청한다.
- 쿠버네티스는 기본 인프라(ex. AWS)에 의해 프로비저닝된 새 노드를 감지한다.
- 쿠버네티스 스케줄러는 보류 중인 파드를 새 노드에 할당한다.
- 보류 상태의 파드가 여전히 존재하면 단계 1로 돌아간다.
워커 노드의 축소 결정을 내리는 순서는 다음과 같다.
- 노드를 삭제하는 것이 안전한지 확인하는 프로세스는 해당 노드에 대한 파드 요청이 사용자 정의 임계값 (default는 50% 요청 사용률)보다 낮을 때 시작된다.
- 이 노드 축소는 실제 CPU/Memory 사용량을 고려하지 않는 대신 리소스 요청만 살펴본다.
- 노드가 해당 검사를 통과하면 실제 쿠버네티스 스케줄링 알고리즘이 호출되어 해당 노드에서 실행 중인 파드를 다른 곳으로 이동할 수 있는지의 여부를 결정한다.
- 클러스터 자동 확장 처리는 노드의 각 파드에서 다음 검사를 실행하여 서비스 중단 가능성을 최소화한다.
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 상태로 변한다.
다음과 같이 워커 노드도 스케일링 할 수 있다.