-
1. Karpenter란?
-
Cluster Autoscaler vs Karpenter
-
카펜터 동작 방식
-
카펜터의 주요 특징
-
NodePool 구성 전략
-
Karpenter 리소스 명칭 변경
-
2. Karpenter 설치
-
AWS 리소스 생성(CloudFormation)
-
EKS 클러스터 생성(eksctl)
-
카펜터 설치(Helm)
-
Karpenter 모니터링 도구 설치
-
3. Karpenter 실습
-
Karpenter NodePool 및 EC2 NodeClass
-
Karpenter 테스트 워크로드 배포 및 모니터링
-
4. Karpenter Distruption
-
Disruption 작동 방식
-
Disruption 유형
-
Disruption 설정 예시
-
Reference
1. Karpenter란?
AWS Karpenter는 Kubernetes 클러스터의 노드 프로비저닝을 자동화하는 오픈소스 도구로, Kubernetes 네이티브 오토스케일러입니다. 워크로드 요구사항에 맞게 적절한 컴퓨팅 리소스를 실시간으로 프로비저닝 하여 클러스터의 효율성과 비용 최적화를 동시에 달성합니다.
Cluster Autoscaler vs Karpenter
Cluster Autoscaler?
- CAS(Cluster Autoscaler)는 클러스터에서 파드가 스케줄링되지 못하는 상황을 감지하고 클러스터의 노드 수를 자동으로 조정하는 도구입니다.
- EKS에서는 ASG(Auto Scaling group)을 이용하여 노드의 수를 조정하였습니다.

기존에는 노드 프로비저닝 자동화 도구로 CA(Cluster Autoscaler)가 널리 사용되었지만, Cluster Autoscaler에는 다음과 같은 한계가 있었습니다.
- 리소스 관리 분리: ASG와 EKS 리소스가 별도로 관리되어 동기화 문제 발생 (정보의 비대칭)
- 수동 정리 필요: EKS 노드 삭제 시 ASG의 인스턴스는 여전히 존재하여 수동 삭제 작업 필요
- 느린 스케일링 속도: 여러 단계를 거쳐야 하므로 스케일링 속도가 느림
- 제한된 유연성: 사전 정의된 노드 그룹에 의존하여 다양한 워크로드 요구사항 충족에 한계
Karpenter는 이러한 문제점을 해결하기 위해 설계되었습니다.
카펜터 동작 방식

Cluster Autscler와의 공통점:
- 파드가 Pending 상태(스케줄링하지 못하는 상태)가 될 때 이벤트 발생
Cluster Autscler와의 차이점:
- Cluster Autoscaler: Pending 파드 발견 → ASG 조정 요청 → 노드 생성 → 파드 스케줄링
- Karpenter: Pending 파드 발견 → EC2 Fleet API 직접 호출 → 노드 생성 → 파드 스케줄링
Karpenter는 중간 단계인 ASG를 거치지 않고 EC2 Fleet API를 직접 사용하기 때문에 노드 프로비저닝 속도가 월등히 빠릅니다.


EC2 Fleet이란?
EC2 Fleet은 다양한 EC2 인스턴스 유형, 구매 옵션(온디맨드, 스팟, 예약 인스턴스), 가용 영역에 걸쳐 컴퓨팅 용량을 자동으로 프로비저닝 하는 AWS 서비스입니다. 단일 API 호출로 여러 인스턴스 유형과 구매 옵션을 조합하여 비용 최적화와 성능 요구사항을 동시에 충족시킬 수 있습니다.
카펜터의 주요 특징
- Kubernetes 네이티브:
NodePool
(이전Provisioner
) CR이 ASG를 대체하며, 쿠버네티스 리소스이므로 GitOps 방식(ArgoCD 등)으로 관리 가능 - 간소화된 설정:
- EC2 시작 템플릿이 필요 없음
- 보안 그룹과 서브넷은 태그 기반으로 자동 검색 또는 명시적 지정 가능
- 유연한 인스턴스 선택:
- 가드레일 방식으로 인스턴스 타입 선언 (제약조건 기반)
- 온디맨드/스팟 인스턴스 선택 가능
- 가중치 기반 인스턴스 선택 지원
- 지능적인 노드 배치:
- PV가 존재하는 서브넷에 자동으로 노드 생성
- 워크로드 요구사항에 최적화된 인스턴스 유형 선택
- 효율적인 리소스 관리:
- 사용되지 않는 노드 자동 정리
- 노드 통합(consolidation)을 통한 비용 최적화
NodePool 구성 전략
- 단일 구성: 모든 워크로드에 대해 하나의 NodePool 사용
- 복수 구성: 워크로드 특성에 따라 여러 NodePool 사용 (예: 컴퓨팅 집약적, 메모리 집약적)
- 가중치 구성: 특정 인스턴스 유형에 가중치를 부여하여 선호도 설정
Karpenter 리소스 명칭 변경
Karpenter의 버전이 올라가면서 카펜터의 리소스명이 다음과 같이 변경되었습니다.
Provisioner
→NodePool
AWSNodeTemplate
→EC2 NodeClass
Machine
→NodeClaim
2. Karpenter 설치
Karpenter 설치 준비
Karpenter를 구성하기 위해 관련 환경변수를 먼저 설정합니다. 이 단계는 AWS 환경과 Karpenter가 작동할 EKS 클러스터 정보를 정의합니다.
# 변수 설정
export KARPENTER_NAMESPACE="kube-system" # Karpenter가 설치될 네임스페이스
export KARPENTER_VERSION="1.2.1" # 설치할 Karpenter 버전
export K8S_VERSION="1.32" # 클러스터의 Kubernetes 버전
export AWS_PARTITION="aws" # 표준 파티션 사용 (중국/정부 리전은 aws-cn/aws-us-gov)
export CLUSTER_NAME="gasida-karpenter-demo" # EKS 클러스터 이름 (고유한 이름 사용 권장)
export AWS_DEFAULT_REGION="ap-northeast-2" # AWS 리전 (한국 서울)
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)" # AWS 계정 ID 자동 설정
# 임시 파일 및 AMI 별칭 버전 설정
export TEMPOUT="$(mktemp)"
export ALIAS_VERSION="$(aws ssm get-parameter --name "/aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2023/x86_64/standard/recommended/image_id" --query Parameter.Value | xargs aws ec2 describe-images --query 'Images[0].Name' --image-ids | sed -r 's/^.*(v[[:digit:]]+).*$/\1/')"
# 변수 확인
echo "${KARPENTER_NAMESPACE}" "${KARPENTER_VERSION}" "${K8S_VERSION}" "${CLUSTER_NAME}" "${AWS_DEFAULT_REGION}" "${AWS_ACCOUNT_ID}" "${TEMPOUT}" "${ALIAS_VERSION}"
AWS 리소스 생성(CloudFormation)
Karpenter가 작동하기 위해 필요한 AWS 리소스를 CloudFormation 스택을 통해 생성합니다. 이 과정에서 IAM 정책/역할, SQS 대기열, EventBridge 규칙 등이 생성됩니다.
- IAM 정책: Karpenter 컨트롤러가 AWS 리소스를 관리하는 데 필요한 권한
- IAM 역할: Karpenter가 프로비저닝 하는 노드에 할당되는 역할
- SQS 대기열: 노드 종료 이벤트 처리를 위한 대기열
- EventBridge 규칙: EC2 인스턴스 상태 변경 이벤트를 SQS로 전달
# CloudFormation 스택으로 IAM Policy/Role, SQS, Event/Rule 생성 : 3분 정도 소요
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}"
EKS 클러스터 생성(eksctl)
- karpenter.sh/discovery 태그: Karpenter가 AWS 리소스를 자동으로 검색하는 데 사용
- podIdentityAssociations: 최신 EKS Pod Identity 기능을 사용하여 IRSA 설정 (이전 방식보다 간소화됨)
- iamIdentityMappings: Karpenter가 생성하는 노드에 대한 IAM 역할 매핑
- managedNodeGroups: 초기 노드 그룹 설정 (Karpenter가 작동하기 전에 필요한 최소 노드)
# 클러스터 생성 : EKS 클러스터 생성 15분 정도 소요
eksctl create cluster -f - <<EOF
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ${CLUSTER_NAME} # 환경변수에서 클러스터 이름 사용
region: ${AWS_DEFAULT_REGION} # 환경변수에서 리전 사용
version: "${K8S_VERSION}" # 환경변수에서 K8S 버전 사용
tags:
karpenter.sh/discovery: ${CLUSTER_NAME} # Karpenter 리소스 검색용 태그
iam:
withOIDC: true # OIDC 인증 활성화 (IRSA 사용을 위함)
podIdentityAssociations: # EKS Pod Identity 연결 설정
- namespace: "${KARPENTER_NAMESPACE}" # Karpenter 네임스페이스
serviceAccountName: karpenter # 서비스 계정 이름
roleName: ${CLUSTER_NAME}-karpenter # IAM 역할 이름
permissionPolicyARNs: # 연결할 정책 ARN
- arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}
iamIdentityMappings: # 노드 IAM 역할 매핑
- arn: "arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}"
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers # 부트스트래핑 그룹
- system:nodes # 노드 그룹
## Windows 워크로드를 실행할 계획이라면 kube-proxy 그룹도 지정해야 합니다.
# - eks:kube-proxy-windows
managedNodeGroups: # 초기 관리형 노드 그룹 설정
- instanceType: m5.large # 인스턴스 타입
amiFamily: AmazonLinux2023 # AMI 패밀리
name: ${CLUSTER_NAME}-ng # 노드 그룹 이름
desiredCapacity: 2 # 초기 노드 수
minSize: 1 # 최소 노드 수
maxSize: 10 # 최대 노드 수
iam:
withAddonPolicies:
externalDNS: true # ExternalDNS 애드온 정책 활성화
addons:
- name: eks-pod-identity-agent # EKS Pod Identity 에이전트 애드온 설치
EOF
카펜터 설치(Helm)
Helm 차트를 통해 Karpenter를 설치합니다. Karpenter는 세 가지 주요 CRD로 구성됩니다.
- ec2 nodeclasses.karpenter.k8s.aws: EC2 인스턴스 구성 정의
- nodeclaims.karpenter.sh: 노드 요청 관리
- nodepools.karpenter.sh: 노드 풀 정의
# Helm 레지스트리 로그아웃 (인증 문제 방지)
helm registry logout public.ecr.aws
# Karpenter 설치를 위한 변수 설정 및 확인
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}"
# Karpenter 설치 (Helm 차트 사용)
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version "${KARPENTER_VERSION}" --namespace "${KARPENTER_NAMESPACE}" --create-namespace \
--set "settings.clusterName=${CLUSTER_NAME}" # 클러스터 이름 설정
--set "settings.interruptionQueue=${CLUSTER_NAME}" # 인터럽션 큐 이름 설정 (스팟 인스턴스 종료 알림용)
--set controller.resources.requests.cpu=1 # CPU 요청량
--set controller.resources.requests.memory=1Gi # 메모리 요청량
--set controller.resources.limits.cpu=1 # CPU 제한
--set controller.resources.limits.memory=1Gi # 메모리 제한
--wait # 설치 완료까지 대기
# 설치 확인
helm list -n kube-system # Helm 릴리스 확인
kubectl get-all -n $KARPENTER_NAMESPACE # 모든 리소스 확인 (커스텀 명령어)
kubectl get all -n $KARPENTER_NAMESPACE # 기본 리소스 확인
kubectl get crd | grep karpenter # Karpenter CRD 확인
Karpenter 모니터링 도구 설치
Karpenter의 성능과 동작을 모니터링하기 위해 Prometheus와 Grafana를 설정하는 방법을 설명합니다.
Prometheus 설치
# Helm 리포지토리 추가 및 업데이트
helm repo add grafana-charts https://grafana.github.io/helm-charts
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# 모니터링용 네임스페이스 생성
kubectl create namespace monitoring
# Prometheus 설치를 위한 values 파일 다운로드 및 적용
curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v"${KARPENTER_VERSION}"/website/content/en/preview/getting-started/getting-started-with-karpenter/prometheus-values.yaml | envsubst | tee prometheus-values.yaml
# Prometheus 설치
helm install --namespace monitoring prometheus prometheus-community/prometheus --values prometheus-values.yaml
# 프로메테우스 얼럿매니저 미사용으로 삭제
kubectl delete sts -n monitoring prometheus-alertmanager
prometheus-values.yaml 추가 스크랩 설정 확인
# Karpenter 메트릭 수집을 위한 추가 스크랩 설정
extraScrapeConfigs: |
- job_name: karpenter # Karpenter 메트릭 수집 작업 이름
kubernetes_sd_configs: # Kubernetes 서비스 디스커버리 설정
- role: endpoints # 엔드포인트 기반 디스커버리
namespaces:
names:
- kube-system # Karpenter가 설치된 네임스페이스
relabel_configs: # 레이블 재설정 규칙
- source_labels: # 소스 레이블
- __meta_kubernetes_endpoints_name # 엔드포인트 이름
- __meta_kubernetes_endpoint_port_name # 엔드포인트 포트 이름
action: keep # 조건에 맞는 대상만 유지
regex: karpenter;http-metrics # Karpenter 메트릭 엔드포인트 선택
프로메테우스 접속 설정
# 프로메테우스 접속 설정
export POD_NAME=$(kubectl get pods --namespace monitoring -l "app.kubernetes.io/name=prometheus,app.kubernetes.io/instance=prometheus" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace monitoring port-forward $POD_NAME 9090 &
open http://127.0.0.1:9090
아래와 같이 karpenter 관련 메트릭을 조회할 수 있습니다.

Grafana 설치
Grafana를 설치하여 Karpenter 메트릭을 시각화합니다.
# Grafana 설치를 위한 values 파일 다운로드
curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v"${KARPENTER_VERSION}"/website/content/en/preview/getting-started/getting-started-with-karpenter/grafana-values.yaml | tee grafana-values.yaml
# Grafana 설치
helm install --namespace monitoring grafana grafana-charts/grafana --values grafana-values.yaml
grafana-values.yaml 추가 설정 파일 확인
# Prometheus 데이터 소스 설정
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus # 데이터 소스 이름
type: prometheus # 데이터 소스 유형
version: 1 # 버전
url: http://prometheus-server:80 # Prometheus 서버 URL
access: proxy # 접근 방식
# 대시보드 프로바이더 설정
dashboardProviders:
dashboardproviders.yaml:
apiVersion: 1
providers:
- name: 'default' # 프로바이더 이름
orgId: 1 # 조직 ID
folder: '' # 폴더 경로
type: file # 유형
disableDeletion: false # 삭제 비활성화 여부
editable: true # 편집 가능 여부
options:
path: /var/lib/grafana/dashboards/default # 대시보드 파일 경로
# Karpenter 대시보드 설정
dashboards:
default:
capacity-dashboard: # 용량 대시보드
url: https://karpenter.sh/preview/getting-started/getting-started-with-karpenter/karpenter-capacity-dashboard.json
performance-dashboard: # 성능 대시보드
url: https://karpenter.sh/preview/getting-started/getting-started-with-karpenter/karpenter-performance-dashboard.json
Grafana 접속 설정
# admin 암호
kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
17JUGSjgxK20m4NEnAaG7GzyBjqAMHMFxRnXItLj
# 그라파나 접속
kubectl port-forward --namespace monitoring svc/grafana 3000:80 &
open http://127.0.0.1:3000
Karpenter 대시보드 확인


3. Karpenter 실습
Karpenter NodePool 및 EC2 NodeClass
Karpenter를 사용하여 EKS 클러스터에 자동 노드 프로비저닝을 설정하는 방법을 설명합니다.
Karpenter는 두 가지 주요 리소스를 통해 노드 프로비저닝을 관리합니다:
1. NodePool: 노드 생성 정책과 요구사항을 정의
2. EC2NodeClass: EC2 인스턴스 구성 세부 사항을 정의
NodePool & EC2NodeClass생성
- requirements: 노드 생성 시 필요한 요구사항 정의 (아키텍처, OS, 인스턴스 유형 등)
- expireAfter: 노드 수명 설정 (정기적인 노드 교체로 최신 상태 유지)
- limits: 전체 클러스터에서 사용할 수 있는 최대 리소스 제한
- disruption: 노드 통합 및 교체 정책 설정
- amiSelectorTerms: 사용할 AMI 선택 (환경변수를 통해 버전 지정)
- subnetSelectorTerms 및 securityGroupSelectorTerms: 태그를 통해 리소스 검색
# AMI 별칭 버전 확인
echo $ALIAS_VERSION
v20250228
# NodePool 및 EC2NodeClass 생성
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"] # # x86_64 아키텍처 사용
- key: kubernetes.io/os
operator: In
values: ["linux"] # Linux 운영체제 사용
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"] # 컴퓨팅, 범용, 메모리 최적화 인스턴스
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["2"] # 2세대 인스턴스 사용
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default # 사용할 EC2NodeClass 참조
expireAfter: 720h # 30 * 24h = 720h # 노드 수명 - 30일(720시간) 후 자동 교체
limits:
cpu: 1000
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m # 1분 후 통합
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: "KarpenterNodeRole-${CLUSTER_NAME}" # replace with your cluster name # 노드 역할 지정
amiSelectorTerms:
- alias: "al2023@${ALIAS_VERSION}" # ex) al2023@latest # AMI 별칭 사용
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name # 서브넷 선택 태그
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name # 보안 그룹 선택 태그
EOF
# 확인
kubectl get nodepool,ec2nodeclass,nodeclaims
Karpenter 테스트 워크로드 배포 및 모니터링
이제 Karpenter의 자동 노드 프로비저닝 기능을 테스트하기 위한 워크로드를 배포하고 모니터링하는 방법을 설명합니다
EKS Node Viewer : 모니터링 도구 설치
EKS Node Viewer는 노드 상태와 리소스 사용량을 시각적으로 보여주는 도구입니다.
# 설치
go install github.com/awslabs/eks-node-viewer/cmd/eks-node-viewer@latest # 설치 시 2~3분 정도 소요
# 사용법
eks-node-viewer
# Display both CPU and Memory Usage
eks-node-viewer --resources cpu,memory
eks-node-viewer --resources cpu,memory --extra-labels eks-node-viewer/node-age
테스트용 워크로드 배포
다음 명령을 사용하여 CPU 리소스를 요청하는 테스트 워크로드를 배포합니다:
- inflate: cpu를 사용량을 증가시키는 inflate 이미지를 노드가 스케줄링되도록 함
- cpu: 1 요청: 각 파드가 1 CPU 코어를 요청하도록 설정
- replicas: 0: 초기에는 파드를 생성하지 않고, 나중에 스케일링하여 테스트
# pause 파드 1개에 CPU 1개 최소 보장 할당할 수 있게 디플로이먼트 배포
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 0
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
terminationGracePeriodSeconds: 0
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
resources:
requests:
cpu: 1
securityContext:
allowPrivilegeEscalation: false
EOF
# 노드 상태 모니터링 (EKS Node Viewer 사용)
eks-node-viewer --resources cpu,memory
eks-node-viewer --resources cpu,memory --node-selector "karpenter.sh/registered=true" --extra-labels eks-node-viewer/node-age
inflate 파드를 30개까지 증가시켜 노드가 카펜터에 의해 스케일 업이 되는지 확인
# 워크로드 스케일 업 (30개 레플리카로 증가)
kubectl get pod
kubectl scale deployment inflate --replicas 30
# Karpenter 로그 확인
kubectl logs -f -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller
kubectl logs -f -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller | jq '.'
kubectl logs -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller | grep 'launched nodeclaim'
노드 프로비저닝 시간 (일반적으로 CA보다 훨씬 빠름) - 선택된 인스턴스 유형 (NodePool 요구사항에 따라 결정됨)



aws 콘솔에서 프로비저닝 된 EC2 인스턴스의 태그를 확인해 보면 karpenter 태그가 태깅되어 있음을 확인할 수 있습니다.

카펜터 pod의 로그 확인

scale out 확인 - 노드 증가

스케일 인(deprovosioning)
반대로, 리소스를 삭제하고 프로비저닝 된 노드가 줄어드는지 확인합니다.
리소스 삭제
kubectl delete deployment inflate && date
deployment.apps "inflate" deleted
Wed Mar 5 17:17:22 KST 2025
노드 정보 확인

karpenter 파드 로그 확인

scale-in 확인 - 노드 감소

4. Karpenter Distruption
Karpenter의 Disruption(중단) 기능은 클러스터 최적화를 위한 핵심 메커니즘으로, 노드를 적극적으로 관리하여 비용 효율성과 클러스터 안정성을 향상 시킵니다.
Disruption은 Karpenter가 클러스터 내 노드를 교체하거나 제거하는 프로세스입니다.
Disruption 작동 방식
Karpenter의 Disruption 프로세스는 다음과 같은 단계로 진행됩니다:
- 모니터링: Karpenter는 지속적으로 클러스터 상태를 모니터링합니다.
- Cordon 설정: Disruption 조건이 충족되면 해당 노드에 cordon을 설정하여 새 파드 스케줄링을 방지합니다.
- Drain 수행: 노드에서 실행 중인 파드를 안전하게 다른 노드로 이동(drain)합니다.
- 노드 종료: 빈 노드를 종료하고 필요시 새 노드를 프로비저닝 합니다.

- 설정 예시
Disruption 유형
Karpenter는 주요 3가지 유형의 Disruption을 제공합니다.
- Expiration(만료)
- 목적: 노드가 특정 시간(TTL) 이후 자동으로 교체되도록 설정
- 설정: expireAfter 파라미터 (이전 버전: ttlSecondsUntilExpired)
- 기본값: 720시간(30일)
- 장점:
- 노드를 주기적으로 교체하여 최신 상태 유지
- 보안 패치 및 업데이트 적용 보장
- 장기 실행 노드의 안정성 문제 방지
- Drift(드리프트)
- 목적: 노드가 원하는 상태(Desired State)에서 벗어났을 때 자동 교체
- 트리거 조건:
- NodePool 또는 EC2NodeClass 구성 변경
- AMI 업데이트
- 보안 그룹 변경
- 장점:
- 클러스터 구성 일관성 유지
- 보안 및 컴플라이언스 요구사항 충족
- 인프라 변경사항 자동 적용
- Consolidation(통합)
- 목적: 여러 개의 저활용 노드에서 실행 중인 파드들을 더 적은 수의 노드로 통합
- 설정: consolidationPolicy 및 consolidateAfter 파라미터
- 장점:
- 클러스터 리소스 활용도 향상
- 불필요한 노드 비용 절감
- 자동화된 클러스터 최적화
Disruption 설정 예시
consolidationPolicy: Karpenter가 노드를 대체하는 조건을 정의
WhenEmpty
- 모든 워크로드가 노드에서 제거된 경우에만 노드를 종료합니다.
- 리소스 활용도보다 워크로드 안정성이 더 중요한 경우에 적합합니다.
WhenUnderutilized
- 노드의 리소스 사용률이 낮고 워크로드를 다른 노드로 이동할 수 있는 경우 노드를 종료합니다.
- 비용 최적화가 중요한 환경에 적합합니다.
WhenEmptyOrUnderutilized
- 가장 적극적인 통합 정책으로, 노드가 비어있거나 충분히 활용되지 않을 때 통합합니다.
- 비용 효율성이 최우선인 환경에 적합합니다.
consolidateAfter: 1m
- 노드가 비어있거나 충분히 활용되지 않는 상태로 1분이 지나면 통합 작업을 시작합니다.
- 이 시간 설정은 일시적인 워크로드 변동에 너무 민감하게 반응하지 않도록 합니다
# Create a Karpenter NodePool and EC2NodeClass
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/os
operator: In
values: ["linux"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-size
operator: NotIn
values: ["nano","micro","small","medium"]
- key: karpenter.k8s.aws/instance-hypervisor
operator: In
values: ["nitro"]
expireAfter: 1h # nodes are terminated automatically after 1 hour
limits:
cpu: "1000"
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized # policy enables Karpenter to replace nodes when they are either empty or underutilized
consolidateAfter: 1m
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: "KarpenterNodeRole-${CLUSTER_NAME}" # replace with your cluster name
amiSelectorTerms:
- alias: "al2023@latest"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name
EOF
Reference
'AWS > EKS' 카테고리의 다른 글
AWS EKS 업그레이드, In-place부터 Blue/Green 마이그레이션까지 (1) | 2025.04.02 |
---|---|
EKS 서버리스 서비스 간략히 알아보기(Fargate & EKS AutoMode) (0) | 2025.03.23 |
EKS 기본 스토리지(EBS + EFS CSI Driver, Instance Store) (0) | 2025.02.23 |
EKS 기본 네트워크(AWS VPC CNI + AWS LoadBalancer Controller) (0) | 2025.02.16 |
EKS 설치 및 클러스터 엔드포인트(EKS Cluster Endpoint) (2) | 2025.02.09 |
1. Karpenter란?
AWS Karpenter는 Kubernetes 클러스터의 노드 프로비저닝을 자동화하는 오픈소스 도구로, Kubernetes 네이티브 오토스케일러입니다. 워크로드 요구사항에 맞게 적절한 컴퓨팅 리소스를 실시간으로 프로비저닝 하여 클러스터의 효율성과 비용 최적화를 동시에 달성합니다.
Cluster Autoscaler vs Karpenter
Cluster Autoscaler?
- CAS(Cluster Autoscaler)는 클러스터에서 파드가 스케줄링되지 못하는 상황을 감지하고 클러스터의 노드 수를 자동으로 조정하는 도구입니다.
- EKS에서는 ASG(Auto Scaling group)을 이용하여 노드의 수를 조정하였습니다.

기존에는 노드 프로비저닝 자동화 도구로 CA(Cluster Autoscaler)가 널리 사용되었지만, Cluster Autoscaler에는 다음과 같은 한계가 있었습니다.
- 리소스 관리 분리: ASG와 EKS 리소스가 별도로 관리되어 동기화 문제 발생 (정보의 비대칭)
- 수동 정리 필요: EKS 노드 삭제 시 ASG의 인스턴스는 여전히 존재하여 수동 삭제 작업 필요
- 느린 스케일링 속도: 여러 단계를 거쳐야 하므로 스케일링 속도가 느림
- 제한된 유연성: 사전 정의된 노드 그룹에 의존하여 다양한 워크로드 요구사항 충족에 한계
Karpenter는 이러한 문제점을 해결하기 위해 설계되었습니다.
카펜터 동작 방식

Cluster Autscler와의 공통점:
- 파드가 Pending 상태(스케줄링하지 못하는 상태)가 될 때 이벤트 발생
Cluster Autscler와의 차이점:
- Cluster Autoscaler: Pending 파드 발견 → ASG 조정 요청 → 노드 생성 → 파드 스케줄링
- Karpenter: Pending 파드 발견 → EC2 Fleet API 직접 호출 → 노드 생성 → 파드 스케줄링
Karpenter는 중간 단계인 ASG를 거치지 않고 EC2 Fleet API를 직접 사용하기 때문에 노드 프로비저닝 속도가 월등히 빠릅니다.


EC2 Fleet이란?
EC2 Fleet은 다양한 EC2 인스턴스 유형, 구매 옵션(온디맨드, 스팟, 예약 인스턴스), 가용 영역에 걸쳐 컴퓨팅 용량을 자동으로 프로비저닝 하는 AWS 서비스입니다. 단일 API 호출로 여러 인스턴스 유형과 구매 옵션을 조합하여 비용 최적화와 성능 요구사항을 동시에 충족시킬 수 있습니다.
카펜터의 주요 특징
- Kubernetes 네이티브:
NodePool
(이전Provisioner
) CR이 ASG를 대체하며, 쿠버네티스 리소스이므로 GitOps 방식(ArgoCD 등)으로 관리 가능 - 간소화된 설정:
- EC2 시작 템플릿이 필요 없음
- 보안 그룹과 서브넷은 태그 기반으로 자동 검색 또는 명시적 지정 가능
- 유연한 인스턴스 선택:
- 가드레일 방식으로 인스턴스 타입 선언 (제약조건 기반)
- 온디맨드/스팟 인스턴스 선택 가능
- 가중치 기반 인스턴스 선택 지원
- 지능적인 노드 배치:
- PV가 존재하는 서브넷에 자동으로 노드 생성
- 워크로드 요구사항에 최적화된 인스턴스 유형 선택
- 효율적인 리소스 관리:
- 사용되지 않는 노드 자동 정리
- 노드 통합(consolidation)을 통한 비용 최적화
NodePool 구성 전략
- 단일 구성: 모든 워크로드에 대해 하나의 NodePool 사용
- 복수 구성: 워크로드 특성에 따라 여러 NodePool 사용 (예: 컴퓨팅 집약적, 메모리 집약적)
- 가중치 구성: 특정 인스턴스 유형에 가중치를 부여하여 선호도 설정
Karpenter 리소스 명칭 변경
Karpenter의 버전이 올라가면서 카펜터의 리소스명이 다음과 같이 변경되었습니다.
Provisioner
→NodePool
AWSNodeTemplate
→EC2 NodeClass
Machine
→NodeClaim
2. Karpenter 설치
Karpenter 설치 준비
Karpenter를 구성하기 위해 관련 환경변수를 먼저 설정합니다. 이 단계는 AWS 환경과 Karpenter가 작동할 EKS 클러스터 정보를 정의합니다.
# 변수 설정
export KARPENTER_NAMESPACE="kube-system" # Karpenter가 설치될 네임스페이스
export KARPENTER_VERSION="1.2.1" # 설치할 Karpenter 버전
export K8S_VERSION="1.32" # 클러스터의 Kubernetes 버전
export AWS_PARTITION="aws" # 표준 파티션 사용 (중국/정부 리전은 aws-cn/aws-us-gov)
export CLUSTER_NAME="gasida-karpenter-demo" # EKS 클러스터 이름 (고유한 이름 사용 권장)
export AWS_DEFAULT_REGION="ap-northeast-2" # AWS 리전 (한국 서울)
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)" # AWS 계정 ID 자동 설정
# 임시 파일 및 AMI 별칭 버전 설정
export TEMPOUT="$(mktemp)"
export ALIAS_VERSION="$(aws ssm get-parameter --name "/aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2023/x86_64/standard/recommended/image_id" --query Parameter.Value | xargs aws ec2 describe-images --query 'Images[0].Name' --image-ids | sed -r 's/^.*(v[[:digit:]]+).*$/\1/')"
# 변수 확인
echo "${KARPENTER_NAMESPACE}" "${KARPENTER_VERSION}" "${K8S_VERSION}" "${CLUSTER_NAME}" "${AWS_DEFAULT_REGION}" "${AWS_ACCOUNT_ID}" "${TEMPOUT}" "${ALIAS_VERSION}"
AWS 리소스 생성(CloudFormation)
Karpenter가 작동하기 위해 필요한 AWS 리소스를 CloudFormation 스택을 통해 생성합니다. 이 과정에서 IAM 정책/역할, SQS 대기열, EventBridge 규칙 등이 생성됩니다.
- IAM 정책: Karpenter 컨트롤러가 AWS 리소스를 관리하는 데 필요한 권한
- IAM 역할: Karpenter가 프로비저닝 하는 노드에 할당되는 역할
- SQS 대기열: 노드 종료 이벤트 처리를 위한 대기열
- EventBridge 규칙: EC2 인스턴스 상태 변경 이벤트를 SQS로 전달
# CloudFormation 스택으로 IAM Policy/Role, SQS, Event/Rule 생성 : 3분 정도 소요
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}"
EKS 클러스터 생성(eksctl)
- karpenter.sh/discovery 태그: Karpenter가 AWS 리소스를 자동으로 검색하는 데 사용
- podIdentityAssociations: 최신 EKS Pod Identity 기능을 사용하여 IRSA 설정 (이전 방식보다 간소화됨)
- iamIdentityMappings: Karpenter가 생성하는 노드에 대한 IAM 역할 매핑
- managedNodeGroups: 초기 노드 그룹 설정 (Karpenter가 작동하기 전에 필요한 최소 노드)
# 클러스터 생성 : EKS 클러스터 생성 15분 정도 소요
eksctl create cluster -f - <<EOF
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ${CLUSTER_NAME} # 환경변수에서 클러스터 이름 사용
region: ${AWS_DEFAULT_REGION} # 환경변수에서 리전 사용
version: "${K8S_VERSION}" # 환경변수에서 K8S 버전 사용
tags:
karpenter.sh/discovery: ${CLUSTER_NAME} # Karpenter 리소스 검색용 태그
iam:
withOIDC: true # OIDC 인증 활성화 (IRSA 사용을 위함)
podIdentityAssociations: # EKS Pod Identity 연결 설정
- namespace: "${KARPENTER_NAMESPACE}" # Karpenter 네임스페이스
serviceAccountName: karpenter # 서비스 계정 이름
roleName: ${CLUSTER_NAME}-karpenter # IAM 역할 이름
permissionPolicyARNs: # 연결할 정책 ARN
- arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}
iamIdentityMappings: # 노드 IAM 역할 매핑
- arn: "arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}"
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers # 부트스트래핑 그룹
- system:nodes # 노드 그룹
## Windows 워크로드를 실행할 계획이라면 kube-proxy 그룹도 지정해야 합니다.
# - eks:kube-proxy-windows
managedNodeGroups: # 초기 관리형 노드 그룹 설정
- instanceType: m5.large # 인스턴스 타입
amiFamily: AmazonLinux2023 # AMI 패밀리
name: ${CLUSTER_NAME}-ng # 노드 그룹 이름
desiredCapacity: 2 # 초기 노드 수
minSize: 1 # 최소 노드 수
maxSize: 10 # 최대 노드 수
iam:
withAddonPolicies:
externalDNS: true # ExternalDNS 애드온 정책 활성화
addons:
- name: eks-pod-identity-agent # EKS Pod Identity 에이전트 애드온 설치
EOF
카펜터 설치(Helm)
Helm 차트를 통해 Karpenter를 설치합니다. Karpenter는 세 가지 주요 CRD로 구성됩니다.
- ec2 nodeclasses.karpenter.k8s.aws: EC2 인스턴스 구성 정의
- nodeclaims.karpenter.sh: 노드 요청 관리
- nodepools.karpenter.sh: 노드 풀 정의
# Helm 레지스트리 로그아웃 (인증 문제 방지)
helm registry logout public.ecr.aws
# Karpenter 설치를 위한 변수 설정 및 확인
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}"
# Karpenter 설치 (Helm 차트 사용)
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version "${KARPENTER_VERSION}" --namespace "${KARPENTER_NAMESPACE}" --create-namespace \
--set "settings.clusterName=${CLUSTER_NAME}" # 클러스터 이름 설정
--set "settings.interruptionQueue=${CLUSTER_NAME}" # 인터럽션 큐 이름 설정 (스팟 인스턴스 종료 알림용)
--set controller.resources.requests.cpu=1 # CPU 요청량
--set controller.resources.requests.memory=1Gi # 메모리 요청량
--set controller.resources.limits.cpu=1 # CPU 제한
--set controller.resources.limits.memory=1Gi # 메모리 제한
--wait # 설치 완료까지 대기
# 설치 확인
helm list -n kube-system # Helm 릴리스 확인
kubectl get-all -n $KARPENTER_NAMESPACE # 모든 리소스 확인 (커스텀 명령어)
kubectl get all -n $KARPENTER_NAMESPACE # 기본 리소스 확인
kubectl get crd | grep karpenter # Karpenter CRD 확인
Karpenter 모니터링 도구 설치
Karpenter의 성능과 동작을 모니터링하기 위해 Prometheus와 Grafana를 설정하는 방법을 설명합니다.
Prometheus 설치
# Helm 리포지토리 추가 및 업데이트
helm repo add grafana-charts https://grafana.github.io/helm-charts
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# 모니터링용 네임스페이스 생성
kubectl create namespace monitoring
# Prometheus 설치를 위한 values 파일 다운로드 및 적용
curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v"${KARPENTER_VERSION}"/website/content/en/preview/getting-started/getting-started-with-karpenter/prometheus-values.yaml | envsubst | tee prometheus-values.yaml
# Prometheus 설치
helm install --namespace monitoring prometheus prometheus-community/prometheus --values prometheus-values.yaml
# 프로메테우스 얼럿매니저 미사용으로 삭제
kubectl delete sts -n monitoring prometheus-alertmanager
prometheus-values.yaml 추가 스크랩 설정 확인
# Karpenter 메트릭 수집을 위한 추가 스크랩 설정
extraScrapeConfigs: |
- job_name: karpenter # Karpenter 메트릭 수집 작업 이름
kubernetes_sd_configs: # Kubernetes 서비스 디스커버리 설정
- role: endpoints # 엔드포인트 기반 디스커버리
namespaces:
names:
- kube-system # Karpenter가 설치된 네임스페이스
relabel_configs: # 레이블 재설정 규칙
- source_labels: # 소스 레이블
- __meta_kubernetes_endpoints_name # 엔드포인트 이름
- __meta_kubernetes_endpoint_port_name # 엔드포인트 포트 이름
action: keep # 조건에 맞는 대상만 유지
regex: karpenter;http-metrics # Karpenter 메트릭 엔드포인트 선택
프로메테우스 접속 설정
# 프로메테우스 접속 설정
export POD_NAME=$(kubectl get pods --namespace monitoring -l "app.kubernetes.io/name=prometheus,app.kubernetes.io/instance=prometheus" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace monitoring port-forward $POD_NAME 9090 &
open http://127.0.0.1:9090
아래와 같이 karpenter 관련 메트릭을 조회할 수 있습니다.

Grafana 설치
Grafana를 설치하여 Karpenter 메트릭을 시각화합니다.
# Grafana 설치를 위한 values 파일 다운로드
curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v"${KARPENTER_VERSION}"/website/content/en/preview/getting-started/getting-started-with-karpenter/grafana-values.yaml | tee grafana-values.yaml
# Grafana 설치
helm install --namespace monitoring grafana grafana-charts/grafana --values grafana-values.yaml
grafana-values.yaml 추가 설정 파일 확인
# Prometheus 데이터 소스 설정
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus # 데이터 소스 이름
type: prometheus # 데이터 소스 유형
version: 1 # 버전
url: http://prometheus-server:80 # Prometheus 서버 URL
access: proxy # 접근 방식
# 대시보드 프로바이더 설정
dashboardProviders:
dashboardproviders.yaml:
apiVersion: 1
providers:
- name: 'default' # 프로바이더 이름
orgId: 1 # 조직 ID
folder: '' # 폴더 경로
type: file # 유형
disableDeletion: false # 삭제 비활성화 여부
editable: true # 편집 가능 여부
options:
path: /var/lib/grafana/dashboards/default # 대시보드 파일 경로
# Karpenter 대시보드 설정
dashboards:
default:
capacity-dashboard: # 용량 대시보드
url: https://karpenter.sh/preview/getting-started/getting-started-with-karpenter/karpenter-capacity-dashboard.json
performance-dashboard: # 성능 대시보드
url: https://karpenter.sh/preview/getting-started/getting-started-with-karpenter/karpenter-performance-dashboard.json
Grafana 접속 설정
# admin 암호
kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
17JUGSjgxK20m4NEnAaG7GzyBjqAMHMFxRnXItLj
# 그라파나 접속
kubectl port-forward --namespace monitoring svc/grafana 3000:80 &
open http://127.0.0.1:3000
Karpenter 대시보드 확인


3. Karpenter 실습
Karpenter NodePool 및 EC2 NodeClass
Karpenter를 사용하여 EKS 클러스터에 자동 노드 프로비저닝을 설정하는 방법을 설명합니다.
Karpenter는 두 가지 주요 리소스를 통해 노드 프로비저닝을 관리합니다:
1. NodePool: 노드 생성 정책과 요구사항을 정의
2. EC2NodeClass: EC2 인스턴스 구성 세부 사항을 정의
NodePool & EC2NodeClass생성
- requirements: 노드 생성 시 필요한 요구사항 정의 (아키텍처, OS, 인스턴스 유형 등)
- expireAfter: 노드 수명 설정 (정기적인 노드 교체로 최신 상태 유지)
- limits: 전체 클러스터에서 사용할 수 있는 최대 리소스 제한
- disruption: 노드 통합 및 교체 정책 설정
- amiSelectorTerms: 사용할 AMI 선택 (환경변수를 통해 버전 지정)
- subnetSelectorTerms 및 securityGroupSelectorTerms: 태그를 통해 리소스 검색
# AMI 별칭 버전 확인
echo $ALIAS_VERSION
v20250228
# NodePool 및 EC2NodeClass 생성
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"] # # x86_64 아키텍처 사용
- key: kubernetes.io/os
operator: In
values: ["linux"] # Linux 운영체제 사용
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"] # 컴퓨팅, 범용, 메모리 최적화 인스턴스
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["2"] # 2세대 인스턴스 사용
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default # 사용할 EC2NodeClass 참조
expireAfter: 720h # 30 * 24h = 720h # 노드 수명 - 30일(720시간) 후 자동 교체
limits:
cpu: 1000
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m # 1분 후 통합
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: "KarpenterNodeRole-${CLUSTER_NAME}" # replace with your cluster name # 노드 역할 지정
amiSelectorTerms:
- alias: "al2023@${ALIAS_VERSION}" # ex) al2023@latest # AMI 별칭 사용
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name # 서브넷 선택 태그
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name # 보안 그룹 선택 태그
EOF
# 확인
kubectl get nodepool,ec2nodeclass,nodeclaims
Karpenter 테스트 워크로드 배포 및 모니터링
이제 Karpenter의 자동 노드 프로비저닝 기능을 테스트하기 위한 워크로드를 배포하고 모니터링하는 방법을 설명합니다
EKS Node Viewer : 모니터링 도구 설치
EKS Node Viewer는 노드 상태와 리소스 사용량을 시각적으로 보여주는 도구입니다.
# 설치
go install github.com/awslabs/eks-node-viewer/cmd/eks-node-viewer@latest # 설치 시 2~3분 정도 소요
# 사용법
eks-node-viewer
# Display both CPU and Memory Usage
eks-node-viewer --resources cpu,memory
eks-node-viewer --resources cpu,memory --extra-labels eks-node-viewer/node-age
테스트용 워크로드 배포
다음 명령을 사용하여 CPU 리소스를 요청하는 테스트 워크로드를 배포합니다:
- inflate: cpu를 사용량을 증가시키는 inflate 이미지를 노드가 스케줄링되도록 함
- cpu: 1 요청: 각 파드가 1 CPU 코어를 요청하도록 설정
- replicas: 0: 초기에는 파드를 생성하지 않고, 나중에 스케일링하여 테스트
# pause 파드 1개에 CPU 1개 최소 보장 할당할 수 있게 디플로이먼트 배포
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 0
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
terminationGracePeriodSeconds: 0
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
resources:
requests:
cpu: 1
securityContext:
allowPrivilegeEscalation: false
EOF
# 노드 상태 모니터링 (EKS Node Viewer 사용)
eks-node-viewer --resources cpu,memory
eks-node-viewer --resources cpu,memory --node-selector "karpenter.sh/registered=true" --extra-labels eks-node-viewer/node-age
inflate 파드를 30개까지 증가시켜 노드가 카펜터에 의해 스케일 업이 되는지 확인
# 워크로드 스케일 업 (30개 레플리카로 증가)
kubectl get pod
kubectl scale deployment inflate --replicas 30
# Karpenter 로그 확인
kubectl logs -f -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller
kubectl logs -f -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller | jq '.'
kubectl logs -n "${KARPENTER_NAMESPACE}" -l app.kubernetes.io/name=karpenter -c controller | grep 'launched nodeclaim'
노드 프로비저닝 시간 (일반적으로 CA보다 훨씬 빠름) - 선택된 인스턴스 유형 (NodePool 요구사항에 따라 결정됨)



aws 콘솔에서 프로비저닝 된 EC2 인스턴스의 태그를 확인해 보면 karpenter 태그가 태깅되어 있음을 확인할 수 있습니다.

카펜터 pod의 로그 확인

scale out 확인 - 노드 증가

스케일 인(deprovosioning)
반대로, 리소스를 삭제하고 프로비저닝 된 노드가 줄어드는지 확인합니다.
리소스 삭제
kubectl delete deployment inflate && date
deployment.apps "inflate" deleted
Wed Mar 5 17:17:22 KST 2025
노드 정보 확인

karpenter 파드 로그 확인

scale-in 확인 - 노드 감소

4. Karpenter Distruption
Karpenter의 Disruption(중단) 기능은 클러스터 최적화를 위한 핵심 메커니즘으로, 노드를 적극적으로 관리하여 비용 효율성과 클러스터 안정성을 향상 시킵니다.
Disruption은 Karpenter가 클러스터 내 노드를 교체하거나 제거하는 프로세스입니다.
Disruption 작동 방식
Karpenter의 Disruption 프로세스는 다음과 같은 단계로 진행됩니다:
- 모니터링: Karpenter는 지속적으로 클러스터 상태를 모니터링합니다.
- Cordon 설정: Disruption 조건이 충족되면 해당 노드에 cordon을 설정하여 새 파드 스케줄링을 방지합니다.
- Drain 수행: 노드에서 실행 중인 파드를 안전하게 다른 노드로 이동(drain)합니다.
- 노드 종료: 빈 노드를 종료하고 필요시 새 노드를 프로비저닝 합니다.

- 설정 예시
Disruption 유형
Karpenter는 주요 3가지 유형의 Disruption을 제공합니다.
- Expiration(만료)
- 목적: 노드가 특정 시간(TTL) 이후 자동으로 교체되도록 설정
- 설정: expireAfter 파라미터 (이전 버전: ttlSecondsUntilExpired)
- 기본값: 720시간(30일)
- 장점:
- 노드를 주기적으로 교체하여 최신 상태 유지
- 보안 패치 및 업데이트 적용 보장
- 장기 실행 노드의 안정성 문제 방지
- Drift(드리프트)
- 목적: 노드가 원하는 상태(Desired State)에서 벗어났을 때 자동 교체
- 트리거 조건:
- NodePool 또는 EC2NodeClass 구성 변경
- AMI 업데이트
- 보안 그룹 변경
- 장점:
- 클러스터 구성 일관성 유지
- 보안 및 컴플라이언스 요구사항 충족
- 인프라 변경사항 자동 적용
- Consolidation(통합)
- 목적: 여러 개의 저활용 노드에서 실행 중인 파드들을 더 적은 수의 노드로 통합
- 설정: consolidationPolicy 및 consolidateAfter 파라미터
- 장점:
- 클러스터 리소스 활용도 향상
- 불필요한 노드 비용 절감
- 자동화된 클러스터 최적화
Disruption 설정 예시
consolidationPolicy: Karpenter가 노드를 대체하는 조건을 정의
WhenEmpty
- 모든 워크로드가 노드에서 제거된 경우에만 노드를 종료합니다.
- 리소스 활용도보다 워크로드 안정성이 더 중요한 경우에 적합합니다.
WhenUnderutilized
- 노드의 리소스 사용률이 낮고 워크로드를 다른 노드로 이동할 수 있는 경우 노드를 종료합니다.
- 비용 최적화가 중요한 환경에 적합합니다.
WhenEmptyOrUnderutilized
- 가장 적극적인 통합 정책으로, 노드가 비어있거나 충분히 활용되지 않을 때 통합합니다.
- 비용 효율성이 최우선인 환경에 적합합니다.
consolidateAfter: 1m
- 노드가 비어있거나 충분히 활용되지 않는 상태로 1분이 지나면 통합 작업을 시작합니다.
- 이 시간 설정은 일시적인 워크로드 변동에 너무 민감하게 반응하지 않도록 합니다
# Create a Karpenter NodePool and EC2NodeClass
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/os
operator: In
values: ["linux"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-size
operator: NotIn
values: ["nano","micro","small","medium"]
- key: karpenter.k8s.aws/instance-hypervisor
operator: In
values: ["nitro"]
expireAfter: 1h # nodes are terminated automatically after 1 hour
limits:
cpu: "1000"
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized # policy enables Karpenter to replace nodes when they are either empty or underutilized
consolidateAfter: 1m
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: "KarpenterNodeRole-${CLUSTER_NAME}" # replace with your cluster name
amiSelectorTerms:
- alias: "al2023@latest"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}" # replace with your cluster name
EOF
Reference
'AWS > EKS' 카테고리의 다른 글
AWS EKS 업그레이드, In-place부터 Blue/Green 마이그레이션까지 (1) | 2025.04.02 |
---|---|
EKS 서버리스 서비스 간략히 알아보기(Fargate & EKS AutoMode) (0) | 2025.03.23 |
EKS 기본 스토리지(EBS + EFS CSI Driver, Instance Store) (0) | 2025.02.23 |
EKS 기본 네트워크(AWS VPC CNI + AWS LoadBalancer Controller) (0) | 2025.02.16 |
EKS 설치 및 클러스터 엔드포인트(EKS Cluster Endpoint) (2) | 2025.02.09 |