최근 EKS에 대해 여러가지를 찾아보았다.
여기에서 클러스터의 워커노드 오토스케일링 방법에 대해 알아본다.
두 기술 모두 기존 워커노드에 Pod를 스케줄링할 수 없는 상황일 때, 새로운 워커노드를 생성하고 관리한다.

Managed Node Group 문서에 따르면
관리형 노드 그룹의 일부로 시작된 노드는 Kubernetes Cluster Autoscaler에서 자동 검색할 수 있도록 태그가 자동으로 지정됩니다. 노드 그룹을 사용하여 Kubernetes 레이블을 노드에 적용하고 언제든지 업데이트할 수 있습니다.
오토 스케일링 과정 자체가 클라우드 벤더의 오토스케일링 서비스에 종속된다.
EKS의 규모가 커질수록, 다수의 ASG와 launchTemplate에 대한 관리에 어려움이 생긴다.
Cluster Autoscaler를 사용했을 때 생기는 여러 어려운 점을 해소하기 위해, AWS에서 새로 개발한 k8s 노드 오토스케일링 오픈소스. 현재 지원되는 환경은 AWS, Azure 2개이다.

노드 오토스케일링 정책을 k8s Custom Resource를 통해 정의한다.
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: sample-provisioner
spec:
requirements:
- key: node.kubernetes.io/instance-type # 여러 타입 정의 가능
operator: In
values: [ r5.xlarge, r5.4xlarge ]
- key: topology.kubernetes.io/zone # 여러 AZ에서 할당
operator: In
values: [ ap-northeast-2a, ap-northeast-2b, ap-northeast-2c ]
- key: karpenter.sh/capacity-type # on-demand vs spot
operator: In
values: [ on-demand ]
providerRef:
name: sample-template # AWSNodeTemplate과 연동
ttlSecondsAfterEmpty: 30
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: sample-template
spec:
# EC2는 아래 라벨을 가진 subnet에서 생성됨.
subnetSelector:
kubernetes.io/role/internal-elb: "1"
kubernetes.io/cluster/my-eks: "shared"
# EC2는 아래 라벨을 가진 SG와 연동됨.
securityGroupSelector:
aws:eks:cluster-name: "my-eks"
# EC2의 instance profile (Cluster API와 동일하게 사용 가능)
instanceProfile: "nodes.cluster-api-provider-aws.sigs.k8s.io"
amiSelector:
aws-ids: "ami-085d85b69823fe795"
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100G
volumeType: gp3
iops: 3000
deleteOnTermination: true
# EC2는 아래의 태그를 포함하여 생성됨.
tags:
Name: managed-by-karpenter
Provisioner에는 워커노드의 생명주기를 정의하는 옵션이 포함된다.
ttlSecondsAfterEmpty(int): 해당 노드에 DaemonSet을 제외하고 아무 파드도 없는 경우, n초뒤에 해당 노드를 삭제ttlSecondsUntilExpired(int): 해당 시간만큼 노드가 유지되었다면, 삭제 후 동일 스펙으로 새로 생성consolidation(bool): 해당 노드에 배포된 Pod를 다른 노드로 이동시켰을 때 이 노드를 삭제할 수 있다면, Pod를 이동시킴. (ttlSecondsAfterEmpty와 동시에 사용 불가)
- AWSIAMInstanceProfileControlPlane
- AWSIAMInstanceProfileControllers
- AWSIAMInstanceProfileNodes
- AWSIAMManagedPolicyCloudProviderControlPlane
- AWSIAMManagedPolicyCloudProviderNodes
- AWSIAMManagedPolicyControllers
- AWSIAMManagedPolicyControllersEKS
- AWSIAMRoleControlPlane
- AWSIAMRoleControllers
- AWSIAMRoleEKSControlPlane
- AWSIAMRoleNodes
Controller는 k8s에 Pod로 배포되고, AWS의 리소스를 Reconcile할 때 위의 Controller 네이밍의 IAM 리소스들이 사용된다.
EKS와 관련된 AWS 리소스를 조회/수정하기 위한 권한이 필요하다.
Cluster API의 IAM 리소스와 대부분 호환 가능.
아래 설정만 따로 Policy를 만들어 기존 CAPI Controller Role에 추가하면 된다.
{
"Statement": [
{
"Action": [
"ec2:DescribeInstanceTypeOfferings",
"ec2:CreateFleet",
"ec2:DescribeSpotPriceHistory",
"pricing:GetProducts"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "Karpenter"
},
{
"Effect": "Allow",
"Action": "eks:DescribeCluster",
"Resource": "arn:aws:eks:ap-northeast-2:*:cluster/*",
"Sid": "EKSClusterEndpointLookup"
}
],
"Version": "2012-10-17"
}
export KARPENTER_VERSION="v0.29.0"
export CLUSTER_ENDPOINT="EKS 엔드포인트 URL"
export CLUSTER_NAME="EKS 이름"
export AWS_ACCOUNT_ID="EKS가 배포된 AWS 계정 ID"
export ROLE_NAME="controllers.cluster-api-provider-aws.sigs.k8s.io" # karpenter가 사용할 IAM Role (Cluster API Role과 호환 가능)
# karpenter helm repo 추가
helm repo add karpenter https://charts.karpenter.sh/
helm repo update
# karpenter 배포 manifest 구성
helm template karpenter oci://public.ecr.aws/karpenter/karpenter --version ${KARPENTER_VERSION} --namespace karpenter \
--set settings.aws.defaultInstanceProfile="nodes.cluster-api-provider-aws.sigs.k8s.io" \
--set settings.aws.clusterEndpoint="${CLUSTER_ENDPOINT}" \
--set settings.aws.clusterName=${CLUSTER_NAME} \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME}" \
--set replicas=1 > karpenter.yaml
# 기본 설정은 replicas=2 이다.
# karpenter 배포
kubectl create namespace karpenter
kubectl apply -f https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.sh_provisioners.yaml
kubectl apply -f https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.k8s.aws_awsnodetemplates.yaml
kubectl apply -f https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.sh_machines.yaml
kubectl apply -f karpenter.yaml
/heath말고 /ready로 사용하라