DevOps Tasks
[Kubernetes] Karpenter 를 이용한 EKS 노드 그룹 관리 본문
Karpenter 개요
Karpenter는 Kubernetes 클러스터를 위한 오토스케일링 솔루션입니다.
클러스터의 파드 수요에 따라 자동으로 노드를 생성하거나 제거하여 리소스를 효율적으로 관리합니다.
Karpenter는 파드의 스케줄링 요구 사항을 실시간으로 분석하고, 필요한 경우 새로운 노드를 신속하게 프로비저닝 하여 애플리케이션의 확장성과 가용성을 보장합니다.
Karpenter를 사용하면 다음과 같은 이점이 있습니다
- 자동 노드 스케일링 : 클러스터의 리소스 사용량을 실시간으로 모니터링하고 필요에 따라 노드를 자동으로 생성하거나 제거합니다.
- 비용 최적화 : 필요할 때만 노드를 생성하므로, 리소스 사용을 최적화하고 비용을 절감할 수 있습니다.
- 유연한 프로비저닝 : 다양한 인스턴스 유형과 지역을 지원하여 파드의 요구 사항에 따라 최적의 노드를 선택합니다.
Karpenter는 Kubernetes 클러스터의 파드 수요에 따라 자동으로 노드를 생성하거나 제거하여 리소스를 효율적으로 관리하는 오토스케일링 솔루션입니다. 이를 통해 애플리케이션의 확장성과 가용성을 보장하며, 비용 최적화와 유연한 프로비저닝을 지원합니다.
Karpenter v1.0 주요 업데이트 사항
- API 안정화 : `Karpenter v1.0`에서는 API가 베타 단계를 넘어 안정화되었습니다. 이를 통해 향후 1.0 마이너 버전에서도 API의 호환성이 유지됩니다.
- 향상된 중단 제어 기능 : 중단 예산에 대한 중단 원인을 지정할 수 있어, 노드의 낮은 사용률, 비어 있음, 드리프트 등의 이유로 인한 중단을 세부적으로 관리할 수 있습니다.
- 강제 중단 모드 도입 : 애플리케이션의 가용성과 보안 요구 사항 간의 균형을 맞추기 위해 강제 중단 모드가 추가되었습니다.
- ConsolidateAfter 기능 확장 : Karpenter의 통합 기능을 더 잘 조정할 수 있도록 `ConsolidateAfter` 설정이 확장되어, 비용 효율성과 애플리케이션 가용성 요구 사항을 충족시킬 수 있습니다.
이러한 업데이트를 통해 Karpenter는 더욱 안정적이고 유연한 노드 스케일링을 지원하며, Kubernetes 클러스터 운영의 효율성을 높입니다.
Karpenter 설치 및 스케일링 테스트 단계
네임스페이스 생성
- Karpenter를 배포할 네임스페이스를 생성합니다.
kubectl create namespace karpenter
IAM OIDC 설정 확인
- EKS 클러스터에 OIDC 제공자가 설정되어 있는지 확인합니다.
eksctl utils associate-iam-oidc-provider --cluster <클러스터 이름> --approve
IAM 역할 및 정책 구성
Karpenter가 AWS 리소스에 접근하려면 IAM 역할과 정책이 필요합니다.
이 단계에서는 CloudFormation 템플릿을 사용하여 필요한 역할과 정책을 설정합니다.
curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v"${KARPENTER_VERSION}"/website/content/en/preview/getting-started/getting-started-with-karpenter/cloudformation.yaml > $TEMPOUT \
&& aws cloudformation deploy \
--stack-name "Karpenter-${CLUSTER_NAME}" \
--template-file "${TEMPOUT}" \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides "ClusterName=${CLUSTER_NAME}"
eksctl create cluster -f - <<EOF
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ${CLUSTER_NAME}
region: ${AWS_DEFAULT_REGION}
version: "${K8S_VERSION}"
tags:
karpenter.sh/discovery: ${CLUSTER_NAME}
iam:
withOIDC: true
serviceAccounts:
- metadata:
name: karpenter
namespace: "${KARPENTER_NAMESPACE}"
roleName: ${CLUSTER_NAME}-karpenter
attachPolicyARNs:
- arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}
roleOnly: true
iamIdentityMappings:
- arn: "arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}"
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
## If you intend to run Windows workloads, the kube-proxy group should be specified.
# For more information, see https://github.com/aws/karpenter/issues/5099.
# - eks:kube-proxy-windows
fargateProfiles:
- name: karpenter
selectors:
- namespace: "${KARPENTER_NAMESPACE}"
EOF
export CLUSTER_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text)"
export KARPENTER_IAM_ROLE_ARN="arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/${CLUSTER_NAME}-karpenter"
echo $CLUSTER_ENDPOINT $KARPENTER_IAM_ROLE_ARN
IAM 역할에서 AssumeRoleWithWebIdentity 사용
Karpenter는 `AssumeRoleWithWebIdentity` 를 사용해 AWS 리소스에 안전하게 접근합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:sub": "system:serviceaccount:karpenter:karpenter"
}
}
}
]
}
`AssumeRoleWithWebIdentity`는 Karpenter가 AWS 리소스에 안전하게 접근해 자동 스케일링을 수행하도록 돕습니다.
Karpenter는 클러스터에서 파드 수요를 실시간으로 감지하고, 다음 작업을 자동으로 처리합니다:
- 스케일 아웃: 파드가 부족하면 EC2 인스턴스를 생성해 노드를 추가.
- 스케일 인: 사용되지 않는 파드가 많으면 불필요한 인스턴스를 삭제해 리소스를 최적화.
이를 통해 Karpenter는 EC2 인스턴스의 생성, 삭제, 네트워크 구성을 효율적으로 관리합니다.
IAM 서비스 계정 생성
- Karpenter가 노드를 프로비저닝 할 때 사용할 서비스 계정을 생성하고 IAM 역할과 연결합니다.
eksctl create iamserviceaccount \\
--name karpenter \\
--namespace karpenter \\
--cluster <CLUSERTER_NAME> \\
--attach-role-arn arn:aws:iam::<ACCOUNT_ID>:role/KarpenterControllerRole \\
--approve
Instance Profile 생성
aws iam create-instance-profile --instance-profile-name KarpenterNodeInstanceProfile
aws iam add-role-to-instance-profile --instance-profile-name KarpenterNodeInstanceProfile \\
--role-name KarpenterControllerRole
Karpenter 설치
Helm 저장소 업데이트
- Karpenter Helm 차트를 사용하기 위해 Helm 저장소를 추가하고 업데이트합니다.
helm repo add karpenter <https://charts.karpenter.sh>
helm repo update
Karpenter 설치
- Helm을 사용하여 Karpenter를 설치하고 `nodeAffinity`를 null로 설정합니다.
helm upgrade --install ${NAMESPACE} karpenter/karpenter \
--namespace ${NAMESPACE} \
--create-namespace \
--set clusterName=${CLUSTER_NAME} \
--set clusterEndpoint=${CLUSTER_ENDPOINT} \
--set serviceAccount.create=false \
--set serviceAccount.name=${SERVICE_ACCOUNT_NAME} \
--set aws.defaultInstanceProfile=${INSTANCE_PROFILE} \
--set controller.affinity.nodeAffinity=null
NodePool 설정
- `NodePool`은 Karpenter v1.0부터 도입된 리소스로, 기존 `Provisioner`의 역할을 대체하며 노드 프로비저닝 조건을 보다 직관적으로 정의할 수 있습니다.
- 아래는 `NodePool` 및 `EC2 NodeClass`를 설정하는 YAML 예제입니다.
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: ${EC2_NODECLASS_NAME}
spec:
amiFamily: Bottlerocket
role: "${NODE_ROLE}
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
securityGroupSelectorTerms:
- tags:
Name: "${SECURITY_GROUP_NAME}"
amiSelectorTerms:
- id: "${AMI_ID1}"
- id: "${AMI_ID2}"
---
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: ${NODEPOOL_NAME}
spec:
template:
spec:
template:
spec:
requirements:
- key: "karpenter.k8s.aws/instance-generation"
operator: Gt
values: [ "2" ]
- key: "topology.kubernetes.io/zone"
operator: In
values: [ "ap-northeast-2a", "ap-northeast-2c" ]
- key: kubernetes.io/arch
operator: In
values: [ "arm64", "amd64" ]
- key: kubernetes.io/os
operator: In
values: [ "linux" ]
- key: karpenter.sh/capacity-type
operator: In
values: [ "on-demand", "spot" ]
- key: "node.kubernetes.io/instance-type"
operator: In
values: [ "m6g.large", "c6gn.large", "t4g.large", "c7g.large", "m7g.medium", "r7g.medium", "r6g.medium", "c6g.large", "t4g.medium", "m6g.medium", "c6gn.medium", "m5a.large", "c5a.large", "t3a.large", "t4a.medium" ]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: ${NODECLASS_REF_NAME}
expireAfter: 720h
taints:
- key: "dedicated"
value: "${TAINT_VALUE}"
effect: "NoSchedule"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 10s
NodePool 적용
- `kubectl apply -f nodepool.yaml` 명령어를 사용하여 `nodepool`를 생성합니다.
kubectl apply -f nodepool.yaml
스케일링 테스트 준비 및 진행
테스트 워크로드 생성 및 배포
- 아래 코드는 기본적인 테스트 워크로드로, Karpenter의 스케일링 기능을 확인할 수 있습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: load-test
spec:
replicas: 50 # 원하는 파드 수로 설정
selector:
matchLabels:
app: load-test
template:
metadata:
labels:
app: load-test
spec:
containers:
- name: load
image: busybox
command: ["sh", "-c", "while true; do echo 'Load test'; sleep 10; done"]
워크로드 배포 및 스케일링 확인
- `kubectl apply -f load-test.yaml` 으로 워크로드를 배포하고 Karpenter의 자동 스케일링을 모니터링합니다.
kubectl get nodes
kubectl get pods -o wide
🌀 마무리
Karpenter는 Kubernetes 클러스터의 자동 노드 스케일링을 담당하며, 리소스를 효율적으로 관리하고 비용 절감을 실현합니다.
네임스페이스와 서비스 계정을 생성한 뒤, Helm을 통해 Karpenter를 설치하고 `NodePool` 설정으로 노드 프로비저닝 조건을 지정할 수 있습니다.
마지막으로 테스트 워크로드를 생성하여 Karpenter의 자동 스케일 아웃 및 스케일 인 기능을 검증하면, 클러스터의 확장성과 가용성을 최적화할 수 있습니다.
Karpenter의 강력한 오토스케일링 기능은 클라우드 리소스의 활용도를 극대화하고 관리 효율성을 높이는 데 기여합니다.
위 단계를 따라 설정과 검증을 마친다면, Kubernetes 클러스터 운영에서 한 단계 더 발전한 자동화 경험을 할 수 있을 것입니다.
'Kubernetes' 카테고리의 다른 글
[Kubernetes] AWS EKS에서 Kubernetes Pod별 보안 그룹 설정: 네트워크 보안 강화 (0) | 2024.12.03 |
---|---|
[Kubernetes] Karpenter Spot Node 모니터링을 위한 EventBridge 설정 (0) | 2024.12.03 |
[Kubernetes] EKS CoreDNS 및 Kubelet 통신 문제 (0) | 2024.11.30 |
Kubernetes 에서 Finalizer로 인한 리소스 삭제 지연 처리 방법 (1) | 2024.09.28 |
[K8S] AWS Load Balancer Controller (0) | 2024.08.04 |