이코에코(Eco²) Knowledge Base/Applied
Karpenter: Kubernetes Node Autoscaling
mango_fr
2025. 12. 26. 20:42

참고: Karpenter Documentation, AWS Karpenter GitHub, CNCF Karpenter
들어가며
Kubernetes에서 Pod 스케일링(HPA, KEDA)은 잘 작동하지만, 노드 리소스가 부족하면 Pod는 Pending 상태에 머문다. 기존 Cluster Autoscaler는 ASG(Auto Scaling Group)에 의존하여 스케일업이 느리고 인스턴스 타입 선택이 제한적이다.
┌─────────────────────────────────────────────────────────────┐
│ 노드 스케일링의 필요성 │
├─────────────────────────────────────────────────────────────┤
│ │
│ KEDA: "RabbitMQ 큐에 100개 메시지! Pod 10개로 스케일업!" │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ scan-worker Pod 1 ✓ Running │ │
│ │ scan-worker Pod 2 ✓ Running │ │
│ │ scan-worker Pod 3 ✓ Running │ │
│ │ scan-worker Pod 4 ⏳ Pending (Insufficient CPU) │ │
│ │ scan-worker Pod 5 ⏳ Pending (Insufficient CPU) │ │
│ │ scan-worker Pod 6 ⏳ Pending (Insufficient CPU) │ │
│ │ ... │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ 문제: worker-ai 노드(t3.medium)가 3개 Pod만 수용 가능 │
│ 해결: 노드 자동 추가 → Karpenter │
│ │
└─────────────────────────────────────────────────────────────┘
Karpenter는 AWS에서 개발하고 CNCF에 기증한 노드 오토스케일러로, EC2 Fleet API를 직접 호출하여 30-60초 내에 최적의 인스턴스를 프로비저닝한다.
Cluster Autoscaler vs Karpenter
┌─────────────────────────────────────────────────────────────┐
│ Cluster Autoscaler vs Karpenter │
├─────────────────────────────────────────────────────────────┤
│ │
│ Cluster Autoscaler Karpenter │
│ ────────────────── ───────── │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Scheduler │ │ Scheduler │ │
│ │ (Pending Pod) │ │ (Pending Pod) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Cluster │ │ Karpenter │ │
│ │ Autoscaler │ │ Controller │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Auto Scaling │ │ EC2 Fleet API │ │
│ │ Group (ASG) │ │ (직접 호출) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ EC2 Instance │ │ EC2 Instance │ │
│ │ (ASG Template) │ │ (최적 선택) │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ 스케일업 시간: 2-5분 스케일업 시간: 30-60초 │
│ 인스턴스 타입: ASG에 사전 정의 인스턴스 타입: 실시간 선택│
│ Bin Packing: 제한적 Bin Packing: 최적화 │
│ Node Group 관리 필요 Node Group 불필요 │
│ │
└─────────────────────────────────────────────────────────────┘
비교 요약
| 항목 | Cluster Autoscaler | Karpenter |
|---|---|---|
| 스케일업 시간 | 2-5분 | 30-60초 |
| 인스턴스 선택 | ASG Launch Template | 실시간 최적 선택 |
| Bin Packing | 제한적 | 고급 최적화 |
| 비용 최적화 | 수동 설정 | 자동 (Consolidation) |
| Spot 지원 | ASG 설정 | 네이티브 Fallback |
| 관리 복잡도 | ASG + Node Group | NodePool CR만 |
| CNCF 상태 | - | Graduated (2024) |
Karpenter 아키텍처
핵심 컴포넌트
┌─────────────────────────────────────────────────────────────┐
│ Karpenter 아키텍처 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Kubernetes API Server │ │
│ └─────────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────────┼──────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌──────────┐ ┌──────────┐ │
│ │NodePool│ │EC2Node │ │NodeClaim │ │
│ │ CR │ │Class CR │ │ CR │ │
│ └────────┘ └──────────┘ └──────────┘ │
│ │ │ ▲ │
│ │ 정책 정의 │ AWS 설정 │ 생성 │
│ │ (인스턴스 타입, │ (AMI, Subnet, │ │
│ │ limits, labels) │ SecurityGroup) │ │
│ │ │ │ │
│ └──────────────────────┼──────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Karpenter Controller │ │
│ │ ┌───────────────┐ ┌───────────────┐ │ │
│ │ │ Provisioner │ │ Disruption │ │ │
│ │ │ (스케일업) │ │ (스케일다운)│ │ │
│ │ └───────┬───────┘ └───────┬───────┘ │ │
│ │ │ │ │ │
│ │ └────────┬─────────┘ │ │
│ │ │ │ │
│ └───────────────────┼──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ AWS EC2 Fleet API │ │
│ │ • RunInstances (최적 인스턴스 타입 선택) │ │
│ │ • TerminateInstances (노드 제거) │ │
│ │ • DescribeInstances (상태 모니터링) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
프로비저닝 흐름
┌─────────────────────────────────────────────────────────────┐
│ Karpenter 프로비저닝 흐름 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Pending Pod 감지 │
│ ───────────────────── │
│ Scheduler: "이 Pod를 스케줄할 노드가 없음" │
│ Karpenter: (Watch) "Pending Pod 발견!" │
│ │
│ 2. NodeClaim 생성 │
│ ────────────────── │
│ Karpenter → NodeClaim CR 생성 │
│ • Pending Pod들의 리소스 요구사항 집계 │
│ • NodePool 정책에 따른 제약 조건 적용 │
│ │
│ 3. 인스턴스 타입 선택 │
│ ───────────────────── │
│ Karpenter: │
│ • 가격, 가용성, 리소스 fit 고려 │
│ • Bin Packing: 최소 비용으로 최대 Pod 수용 │
│ • 예: 4 vCPU 필요 → t3.medium × 2 vs t3.xlarge × 1 │
│ │
│ 4. EC2 인스턴스 생성 │
│ ───────────────────── │
│ EC2 Fleet API: │
│ • RunInstances 호출 │
│ • userData로 kubelet 부트스트랩 │
│ • 30-60초 내 노드 Ready │
│ │
│ 5. Pod 스케줄링 │
│ ──────────────── │
│ Scheduler: 새 노드에 Pending Pod 스케줄 │
│ Pod: Running 상태로 전환 │
│ │
└─────────────────────────────────────────────────────────────┘
CRD 분석
1. NodePool (정책 정의)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: worker-scalable
spec:
# 노드 템플릿
template:
metadata:
labels:
role: worker
managed-by: karpenter
spec:
# EC2NodeClass 참조
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
# 인스턴스 요구사항
requirements:
# 인스턴스 타입 제한
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["t3.medium", "t3.large", "t3.xlarge"]
# On-Demand vs Spot
- key: "karpenter.sh/capacity-type"
operator: In
values: ["on-demand"] # 또는 ["spot", "on-demand"]
# 아키텍처
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
# Availability Zone
- key: "topology.kubernetes.io/zone"
operator: In
values: ["ap-northeast-2a", "ap-northeast-2c"]
# Taints (선택적)
taints:
- key: "workload"
value: "ai"
effect: "NoSchedule"
# 리소스 한도 (vCPU Quota 초과 방지)
limits:
cpu: 20 # 최대 20 vCPU
memory: 40Gi # 최대 40GB 메모리
# 노드 축소 정책
disruption:
# WhenEmpty: 노드가 비면 즉시 제거
# WhenEmptyOrUnderutilized: 비거나 활용도 낮으면 제거
consolidationPolicy: WhenEmpty
consolidateAfter: 30s
# 예산: 동시에 중단할 수 있는 노드 수
budgets:
- nodes: "10%" # 전체의 10%까지
- nodes: "1" # 또는 최소 1개
2. EC2NodeClass (AWS 설정)
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
# AMI 선택
amiFamily: Ubuntu # AL2023, Bottlerocket, Ubuntu
# 또는 특정 AMI 지정
# amiSelectorTerms:
# - id: ami-0123456789abcdef0
# IAM Instance Profile
instanceProfile: karpenter-node-profile
# 네트워크 설정
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "true"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "true"
# 블록 디바이스
blockDeviceMappings:
- deviceName: /dev/sda1
ebs:
volumeSize: 40Gi
volumeType: gp3
encrypted: true
# 메타데이터 옵션
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 2
httpTokens: required # IMDSv2 필수
# 사용자 데이터 (kubeadm join 등)
userData: |
#!/bin/bash
set -ex
# Kubernetes 패키지 설치
apt-get update
apt-get install -y containerd kubelet kubeadm kubectl
# containerd 설정
containerd config default > /etc/containerd/config.toml
systemctl restart containerd
# kubeadm join 실행
kubeadm join ${CLUSTER_ENDPOINT}:6443 \
--token ${BOOTSTRAP_TOKEN} \
--discovery-token-ca-cert-hash sha256:${CA_CERT_HASH}
# 태그
tags:
Environment: dev
ManagedBy: karpenter
3. NodeClaim (자동 생성됨)
# Karpenter가 자동 생성하는 CR - 직접 생성하지 않음
apiVersion: karpenter.sh/v1
kind: NodeClaim
metadata:
name: worker-scalable-abc123
ownerReferences:
- apiVersion: karpenter.sh/v1
kind: NodePool
name: worker-scalable
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["t3.large"]
status:
# 인스턴스 정보
providerID: aws:///ap-northeast-2a/i-0abc123def456
nodeName: ip-10-0-1-123.ap-northeast-2.compute.internal
capacity:
cpu: "2"
memory: 8Gi
conditions:
- type: Registered
status: "True"
- type: Initialized
status: "True"
- type: Ready
status: "True"
AWS IAM 권한
Karpenter Controller 권한
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2NodeProvisioning",
"Effect": "Allow",
"Action": [
"ec2:RunInstances",
"ec2:CreateFleet",
"ec2:TerminateInstances",
"ec2:DescribeInstances",
"ec2:DescribeInstanceTypes",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeImages",
"ec2:DescribeSpotPriceHistory"
],
"Resource": "*"
},
{
"Sid": "EC2TagManagement",
"Effect": "Allow",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:CreateAction": ["RunInstances", "CreateFleet"]
}
}
},
{
"Sid": "IAMPassRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::*:role/KarpenterNodeRole-*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
},
{
"Sid": "SSMGetParameter",
"Effect": "Allow",
"Action": "ssm:GetParameter",
"Resource": "arn:aws:ssm:*:*:parameter/aws/service/*"
},
{
"Sid": "PricingAPI",
"Effect": "Allow",
"Action": "pricing:GetProducts",
"Resource": "*"
},
{
"Sid": "SQSInterruption",
"Effect": "Allow",
"Action": [
"sqs:DeleteMessage",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage"
],
"Resource": "arn:aws:sqs:*:*:Karpenter-*"
}
]
}
Node Instance Profile 권한
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster"
],
"Resource": "*"
}
]
}
Disruption (노드 축소)
Consolidation 정책
┌─────────────────────────────────────────────────────────────┐
│ Karpenter Consolidation │
├─────────────────────────────────────────────────────────────┤
│ │
│ WhenEmpty (기본) │
│ ─────────────── │
│ 노드에 Pod가 하나도 없으면 즉시 제거 │
│ │
│ [Node A] [Node B] [Node C] │
│ Pod1 Pod2 (empty) Pod3 │
│ ✓ ✗ 제거 ✓ │
│ │
│ WhenEmptyOrUnderutilized │
│ ───────────────────────── │
│ 비어있거나 활용도가 낮으면 재배치 후 제거 │
│ │
│ Before: │
│ [Node A: 20%] [Node B: 30%] [Node C: 10%] │
│ │
│ After Consolidation: │
│ [Node A: 60%] (terminated) (terminated) │
│ Pod들이 Node A로 재배치됨 │
│ │
└─────────────────────────────────────────────────────────────┘
Disruption Budgets
spec:
disruption:
budgets:
# 언제나 최소 90%는 유지
- nodes: "10%"
# 업무 시간에는 중단 금지
- nodes: "0"
schedule: "0 9-17 * * mon-fri" # 평일 9-17시
duration: 8h
# 주말에는 자유롭게 통합
- nodes: "100%"
schedule: "0 0 * * sat,sun"
duration: 48h
Bin Packing 최적화
┌─────────────────────────────────────────────────────────────┐
│ Karpenter Bin Packing │
├─────────────────────────────────────────────────────────────┤
│ │
│ 시나리오: 5개 Pod 필요 (각 1 vCPU, 2GB) │
│ │
│ Cluster Autoscaler (ASG: t3.medium 고정) │
│ ─────────────────────────────────────── │
│ t3.medium (2 vCPU, 4GB) × 3 = 6 vCPU, 12GB │
│ 비용: $0.0416 × 3 = $0.1248/hr │
│ │
│ [Node 1] [Node 2] [Node 3] │
│ Pod1 Pod2 Pod3 Pod4 Pod5 (빈 공간) │
│ │
│ Karpenter (최적 선택) │
│ ──────────────────── │
│ t3.xlarge (4 vCPU, 16GB) × 1 + t3.small (2 vCPU, 2GB) × 1 │
│ 또는 │
│ t3.large (2 vCPU, 8GB) × 2 + t3.micro × 1 │
│ │
│ 실시간으로 가격, 가용성, fit을 계산하여 최적 조합 선택 │
│ │
└─────────────────────────────────────────────────────────────┘
KEDA + Karpenter 통합
┌─────────────────────────────────────────────────────────────┐
│ KEDA + Karpenter 통합 아키텍처 │
├─────────────────────────────────────────────────────────────┤
│ │
│ RabbitMQ Queue Length: 100 │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ KEDA │ ScaledObject: scan-worker │
│ │ ScaledObject│ threshold: 10 messages/pod │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ HPA │ desiredReplicas: 10 │
│ │ (KEDA 생성) │ currentReplicas: 3 │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Scheduler │ 7개 Pod → Pending (리소스 부족) │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Karpenter │ Pending Pod 감지 │
│ │ Controller │ NodeClaim 생성 │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ EC2 Fleet │ t3.large × 2 프로비저닝 │
│ │ API │ 30-60초 내 Ready │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Scheduler │ 7개 Pending Pod → Running │
│ └──────────────┘ │
│ │
│ Queue 비면: │
│ KEDA → HPA → Pod 수 감소 → Node 빔 → Karpenter 제거 │
│ │
└─────────────────────────────────────────────────────────────┘
kubeadm 클러스터 호환성
EKS vs kubeadm
| 항목 | EKS | kubeadm |
|---|---|---|
| 노드 부트스트랩 | EKS Managed | userData 직접 작성 |
| 인증 | aws-iam-authenticator | Bootstrap Token |
| AMI | EKS Optimized AMI | Ubuntu/직접 준비 |
| CNI | VPC CNI | Calico/Flannel/Cilium |
| userData | 간단 | 복잡 (kubeadm join) |
kubeadm용 userData 템플릿
#!/bin/bash
set -ex
# 변수 설정 (Karpenter가 주입)
CLUSTER_ENDPOINT="${CLUSTER_ENDPOINT}"
BOOTSTRAP_TOKEN="${BOOTSTRAP_TOKEN}"
CA_CERT_HASH="${CA_CERT_HASH}"
# 1. OS 설정
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
# 커널 모듈
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# sysctl
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
# 2. containerd 설치
apt-get update
apt-get install -y containerd
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd
# 3. Kubernetes 패키지 설치
apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | \
gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | \
tee /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
# 4. kubeadm join
kubeadm join ${CLUSTER_ENDPOINT}:6443 \
--token ${BOOTSTRAP_TOKEN} \
--discovery-token-ca-cert-hash sha256:${CA_CERT_HASH}
Bootstrap Token 관리
┌─────────────────────────────────────────────────────────────┐
│ Bootstrap Token 관리 전략 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 문제: Bootstrap Token은 기본 24시간 후 만료 │
│ │
│ 해결 방안: │
│ │
│ 1. Long-lived Token (비권장) │
│ kubeadm token create --ttl 0 │
│ 보안 위험, 운영 환경에서 사용 금지 │
│ │
│ 2. Token 자동 갱신 CronJob │
│ - CronJob이 주기적으로 새 Token 생성 │
│ - AWS SSM Parameter Store에 저장 │
│ - EC2NodeClass userData가 SSM에서 조회 │
│ │
│ 3. Node Authorizer (권장) │
│ - Bootstrap Token 대신 Node Authorizer 사용 │
│ - kubelet TLS bootstrapping │
│ - 노드가 CSR 자동 승인 │
│ │
└─────────────────────────────────────────────────────────────┘
모니터링
Prometheus 메트릭
# Karpenter 메트릭
# 노드 프로비저닝
karpenter_nodes_created_total{nodepool, provisioner}
karpenter_nodes_terminated_total{nodepool, reason}
karpenter_provisioner_scheduling_duration_seconds{nodepool}
# 비용
karpenter_nodes_total_pod_requests{resource_type, nodepool}
karpenter_nodes_total_pod_limits{resource_type, nodepool}
karpenter_nodes_allocatable{resource_type, nodepool}
# Disruption
karpenter_disruption_actions_performed_total{action, nodepool}
karpenter_disruption_pods_disrupted_total{nodepool}
# 예시 쿼리
# 현재 Karpenter가 관리하는 노드 수
count(karpenter_nodes_created_total) - count(karpenter_nodes_terminated_total)
# 프로비저닝 latency p99
histogram_quantile(0.99, karpenter_provisioner_scheduling_duration_seconds_bucket)
대시보드 패널
┌─────────────────────────────────────────────────────────────┐
│ Karpenter Dashboard │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Active Nodes │ │ Pending Pods │ │
│ │ 5 │ │ 0 │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ CPU Utilization │ │ Memory Util │ │
│ │ 65% │ │ 48% │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Node Provisioning Timeline │ │
│ │ ─────────────────────────────────────────────────── │ │
│ │ 10:00 +2 nodes (t3.large) │ │
│ │ 10:30 -1 node (consolidation) │ │
│ │ 11:00 +1 node (t3.medium) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Instance Type Distribution │ │
│ │ [████████████ t3.medium (3) ████████ t3.large (2)] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Eco² 적용
현재 상태
┌─────────────────────────────────────────────────────────────┐
│ Eco² 현재 노드 구성 (Terraform) │
├─────────────────────────────────────────────────────────────┤
│ │
│ 고정 노드 (18개): │
│ ───────────────── │
│ │
│ Control Plane: │
│ • k8s-master (t3.xlarge) │
│ │
│ API Nodes (Taint: domain=xxx:NoSchedule): │
│ • k8s-api-auth, my, scan, character, location (t3.small) │
│ • k8s-api-image, chat (t3.medium) │
│ │
│ Worker Nodes: │
│ • k8s-worker-ai (t3.medium) ← 스케일 필요! │
│ • k8s-worker-storage (t3.medium) │
│ │
│ Infrastructure (Taint: domain=xxx:NoSchedule): │
│ • k8s-postgresql, redis-*, rabbitmq, monitoring, logging │
│ │
│ Network: │
│ • k8s-ingress-gateway (t3.medium) │
│ │
└─────────────────────────────────────────────────────────────┘
Karpenter 도입 로드맵
┌─────────────────────────────────────────────────────────────┐
│ Eco² Karpenter 도입 후 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Terraform (Base Capacity) - 고정 │
│ ──────────────────────────────── │
│ • 모든 Infrastructure 노드 (변경 없음) │
│ • Control Plane (변경 없음) │
│ • k8s-worker-ai (Base 1개) │
│ • k8s-worker-storage (Base 1개) │
│ │
│ Karpenter (Scale Out) - 동적 │
│ ───────────────────────────── │
│ • worker-ai-xxx (KEDA가 Pod 늘리면 자동 생성) │
│ • worker-storage-yyy (필요 시 자동 생성) │
│ • api-scan-zzz (API 부하 증가 시) │
│ │
│ NodePool 설정: │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ NodePool: worker-scalable │ │
│ │ • instance-types: t3.medium, t3.large │ │
│ │ • capacity-type: on-demand │ │
│ │ • limits: 20 vCPU, 40Gi memory │ │
│ │ • consolidation: WhenEmpty, 30s │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
- Karpenter의 경우 EKS를 전제로 구성된 기능이 많음
- 현재 Self-managed K8s Cluster이기에 도입 보류 중
- KEDA로 파드 단위의 이벤트 기반 수평확장이 도입된 상태니 Karpenter의 노드 단위 오토스케일링 기능은 매력적
- Terraform userData를 활용하면 적용 가능 여지는 존재
References
공식 문서
AWS 블로그
CNCF
버전 정보
| 항목 | 버전 |
|---|---|
| 작성일 | 2025-12-26 |
| Karpenter | 1.1.0 |
| Kubernetes | 1.28+ |
| AWS Provider | aws/karpenter-provider-aws |