Karpenter의 아키텍처, Cluster Autoscaler와의 비교, NodePool/EC2NodeClass CRD, 통합과 중단 관리, 스팟 인스턴스 전략, GPU 노드 프로비저닝을 다룹니다.
5장에서 Kubernetes 컨트롤러 패턴의 원리를 살펴보았습니다. 이번 장에서 다룰 Karpenter는 바로 이 컨트롤러 패턴을 노드 프로비저닝에 적용한 도구입니다. 기존 클러스터 오토스케일러(Cluster Autoscaler)의 한계를 극복하고, 워크로드 요구사항에 맞는 최적의 노드를 빠르게 프로비저닝하는 차세대 노드 오토스케일링 솔루션입니다.
Cluster Autoscaler는 Kubernetes의 전통적인 노드 오토스케일링 도구입니다. 하지만 근본적인 아키텍처 제약이 있습니다.
Cluster Autoscaler의 제약사항:
Karpenter의 접근 방식:
Karpenter는 원래 AWS에서 개발했지만, 2023년에 CNCF에 기부되었습니다. 현재 AWS EKS에서 가장 완성도가 높지만, Azure AKS 프로바이더도 활발히 개발 중입니다. 클라우드에 종속되지 않는 표준화된 노드 프로비저닝을 목표로 합니다.
Karpenter는 두 가지 주요 CRD로 동작합니다. NodePool은 프로비저닝 정책을, EC2NodeClass는 AWS 특화 설정을 정의합니다.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general-purpose
spec:
template:
metadata:
labels:
workload-type: general
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge", "2xlarge"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
expireAfter: 720h # 30일 후 자동 교체
limits:
cpu: "1000"
memory: 2000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
weight: 50 # 여러 NodePool 중 우선순위apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: KarpenterNodeRole
amiSelectorTerms:
- alias: al2023@latest # Amazon Linux 2023 최신 AMI
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
network: private
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
iops: 3000
throughput: 125
encrypted: true
deleteOnTermination: true
userData: |
#!/bin/bash
echo "Custom node initialization"
tags:
managed-by: karpenter
environment: production
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 2
httpTokens: required # IMDSv2 강제Karpenter의 가장 강력한 기능 중 하나는 노드 통합(Node Consolidation)입니다. 클러스터의 노드 사용률을 지속적으로 분석하여 비용을 최적화합니다.
통합은 세 가지 전략으로 동작합니다.
consolidationPolicy: WhenEmpty로 설정하면 완전히 빈 노드만 삭제합니다프로덕션 환경에서는 노드 통합이 서비스에 영향을 주지 않도록 중단 예산을 설정해야 합니다.
spec:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
budgets:
# 평상시: 전체 노드의 10%까지만 동시 중단 허용
- nodes: "10%"
# 업무 시간에는 중단 비활성화
- nodes: "0"
schedule: "0 9 * * 1-5" # 월~금 09:00
duration: 8h # 8시간 동안통합이 활성화된 상태에서 PodDisruptionBudget(PDB)을 설정하지 않으면, 중요한 워크로드가 예기치 않게 중단될 수 있습니다. 모든 프로덕션 워크로드에는 적절한 PDB를 반드시 설정하십시오.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
spec:
minAvailable: "80%"
selector:
matchLabels:
app: api-serverKarpenter는 스팟 인스턴스(Spot Instance) 관리에 특히 뛰어납니다. 다양한 인스턴스 타입 풀에서 자동으로 최적의 스팟 인스턴스를 선택하고, 중단(Interruption) 시 자동으로 대응합니다.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-workloads
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
# 다양한 사이즈를 허용하여 스팟 풀 확대
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge", "2xlarge", "4xlarge"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 0s # 스팟 노드는 즉시 통합Karpenter는 EC2 스팟 중단 알림을 감시하여 선제적으로 워크로드를 이동시킵니다. 이를 위해 SQS 큐와 EventBridge 규칙이 필요합니다.
# CloudFormation/CDK로 생성
Resources:
KarpenterInterruptionQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: karpenter-interruption
MessageRetentionPeriod: 300
SpotInterruptionRule:
Type: AWS::Events::Rule
Properties:
EventPattern:
source: ["aws.ec2"]
detail-type:
- "EC2 Spot Instance Interruption Warning"
- "EC2 Instance Rebalance Recommendation"
- "EC2 Instance State-change Notification"
Targets:
- Arn: !GetAtt KarpenterInterruptionQueue.Arn
Id: KarpenterInterruptionTarget스팟 인스턴스를 효과적으로 사용하려면 워크로드를 두 가지로 분류하십시오. 상태 비저장(Stateless) 워크로드(API 서버, 웹 프론트엔드 등)는 스팟에 적합하고, 상태 저장(Stateful) 워크로드(데이터베이스, 메시지 큐 등)는 온디맨드에 배치해야 합니다. nodeAffinity와 tolerations를 활용하여 분리합니다.
AI/ML 워크로드를 위한 GPU 노드도 Karpenter로 관리할 수 있습니다.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-workloads
spec:
template:
metadata:
labels:
workload-type: gpu
spec:
requirements:
- key: karpenter.k8s.aws/instance-family
operator: In
values: ["g5", "g6", "p4d", "p5"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"] # GPU는 온디맨드 권장
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
taints:
- key: nvidia.com/gpu
effect: NoSchedule
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodes
limits:
cpu: "200"
memory: 800Gi
nvidia.com/gpu: "16"
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 5m
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: gpu-nodes
spec:
role: KarpenterNodeRole
amiSelectorTerms:
- alias: al2023@latest
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 200Gi
volumeType: gp3
iops: 6000
throughput: 250
encrypted: true
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-clusterGPU 워크로드를 해당 노드에 스케줄링하려면 toleration을 설정합니다.
apiVersion: v1
kind: Pod
metadata:
name: ml-training
spec:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
containers:
- name: trainer
image: org/ml-trainer:latest
resources:
limits:
nvidia.com/gpu: "1"
memory: 32Gi
requests:
nvidia.com/gpu: "1"
memory: 16GiKarpenter를 활용한 비용 최적화 전략을 정리합니다.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: mixed-capacity
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
# 온디맨드 우선, 부족하면 스팟
# Pod topology spread와 조합하여 가용성 확보Karpenter의 NodePool과 EC2NodeClass는 Kubernetes CRD이므로 GitOps로 자연스럽게 관리됩니다.
infrastructure/
karpenter/
base/
nodepool-general.yaml
nodepool-spot.yaml
nodepool-gpu.yaml
ec2nodeclass-default.yaml
ec2nodeclass-gpu.yaml
overlays/
production/
kustomization.yaml # 프로덕션 limits 조정
staging/
kustomization.yaml # 스테이징 limits 축소
Karpenter는 Kubernetes 노드 관리의 패러다임을 바꾸는 도구입니다. 노드 그룹이라는 기존의 제약을 벗어나 워크로드 요구사항에 최적화된 인스턴스를 자동으로 선택하고, 지속적인 통합으로 비용을 최적화합니다. 특히 5장에서 배운 컨트롤러 패턴이 실제로 어떻게 적용되는지 잘 보여주는 사례이기도 합니다.
다음 장에서는 Karpenter를 포함한 전반적인 Kubernetes 비용 최적화와 리소스 관리 전략을 다루겠습니다. VPA/HPA, Goldilocks, Kubecost, FinOps 실천법 등을 살펴봅니다.
이 글이 도움이 되셨나요?
Kubernetes 리소스 requests/limits 모범 사례, VPA/HPA 전략, Goldilocks, Kubecost/OpenCost, 스팟 인스턴스, 네임스페이스 쿼터, FinOps 실천법을 다룹니다.
Kubernetes 컨트롤러 패턴의 원리, 조정 루프, controller-runtime과 Kubebuilder를 활용한 오퍼레이터 개발, CRD 설계 모범 사례를 다룹니다.
Crossplane의 아키텍처, Provider와 Managed Resource, XRD와 Composition을 활용한 인프라 추상화, GitOps 통합, Terraform과의 비교를 다룹니다.