Published on

EKS 노드그룹 vs Karpenter - 비용 40% 절감 실전

Authors

서버리스가 아닌 이상, EKS 비용의 대부분은 결국 EC2(노드)에서 발생합니다. 같은 워크로드라도 노드를 어떻게 늘리고(스케일 아웃) 어떻게 줄이느냐(스케일 인) 에 따라 월 비용이 크게 달라집니다. 이 글에서는 EKS 관리형 노드그룹(Managed Node Group, 이하 MNG)Karpenter 를 비용 관점에서 비교하고, “40% 절감”이 현실적으로 가능한 조건과 구현 포인트를 정리합니다.

아래 내용은 단순히 Karpenter가 더 싸다는 주장에 그치지 않고, 왜 절감이 생기는지(메커니즘), 어떤 환경에서 절감이 깨지는지(함정), 그리고 바로 적용 가능한 설정 예시까지 포함합니다.

운영 중 파드가 반복 재시작되며 스케일 전략을 망치는 경우가 많습니다. 노드 스케일링과 별개로 애플리케이션 안정성이 선행되어야 하므로, 필요하면 EKS CrashLoopBackOff 진단 - Pod 재시작 원인 추적도 함께 점검하세요.

결론부터: 40% 절감이 나오는 전형적 패턴

다음 조건 중 2개 이상에 해당하면 Karpenter로 30~50% 절감이 현실적입니다.

  • 트래픽이 시간대별로 출렁이고, 피크 대비 평균 부하가 낮다
  • 노드그룹이 2~3개로 고정되어 있고, 인스턴스 타입이 제한적(예: m5.large만)
  • HPA는 잘 되는데 노드는 늦게 줄어 유휴 노드가 오래 남는다
  • 워크로드가 섞여 있어 binpack이 잘 안 되고 리소스 단편화가 심하다
  • 온디맨드만 사용 중이며, Spot을 안전하게 섞을 여지가 있다

반대로 아래라면 절감 폭이 작거나, 오히려 운영비가 올라갈 수 있습니다.

  • 항상 일정한 고정 부하(24x7)이며 이미 예약 인스턴스나 Savings Plans 최적화가 잘 됨
  • 노드가 거의 꽉 차게 운영되고 단편화가 적음
  • 규제/컴플라이언스로 Spot 사용 불가, 인스턴스 타입 제한이 매우 강함

EKS 노드그룹(MNG) 비용 구조와 한계

MNG는 결국 ASG 기반의 “정해진 박스” 전략

MNG는 내부적으로 Auto Scaling Group(ASG)을 사용합니다. 장점은 단순함입니다.

  • 운영이 쉽고, AWS 표준 기능과 궁합이 좋음
  • 노드 업데이트(AMI 롤링) 등 관리형 기능 제공

하지만 비용 관점의 약점이 명확합니다.

  • 인스턴스 타입이 노드그룹 단위로 고정되기 쉬움
  • 스케일 인이 보수적으로 동작해 유휴 노드가 오래 남는 경우가 많음
  • 파드 요구사항이 다양해질수록 노드그룹을 쪼개야 하고, 그 결과 리소스 단편화가 증가

예를 들어 m5.xlarge 노드에 1.2 vCPU, 3Gi만 쓰는 파드가 여러 개 떠 있으면, 남는 자원이 있어도 스케줄링 제약(affinity, taint, topology spread 등) 때문에 못 채워서 비용이 새는 일이 흔합니다.

Cluster Autoscaler의 구조적 제약

MNG에서 흔히 쓰는 Cluster Autoscaler(CA)는 “노드그룹 단위”로 스케일 결정을 내립니다.

  • 어떤 노드그룹을 늘릴지 결정할 때, 미리 정의된 인스턴스 타입/크기 안에서만 선택
  • 스케일 인은 안전을 위해 느리게 동작하거나, PDB/daemonset/지역 분산 정책 때문에 막히는 경우가 많음

즉, CA는 “정해진 박스 중 하나를 더 사는” 모델에 가깝고, 워크로드가 다양할수록 비용 최적화에 불리해집니다.

Karpenter가 비용을 줄이는 핵심 메커니즘

Karpenter는 한 문장으로 요약하면 파드 요구사항을 기준으로 인스턴스를 즉시 조달하는 프로비저너입니다. 노드그룹의 경계를 약화시키고, 더 많은 인스턴스 타입/구성을 동적으로 선택해 비용을 줄입니다.

1) 더 촘촘한 binpack과 단편화 감소

Karpenter는 pending 파드를 보고, 그 파드들이 들어갈 “가장 적절한” 노드를 생성합니다.

  • 다양한 인스턴스 타입을 후보로 두고
  • CPU/메모리뿐 아니라 아키텍처, AZ, 용량 타입(Spot/On-Demand), 디스크, ENI 제한 등 조건을 만족하면서
  • 가장 비용 효율적인 조합을 선택

결과적으로 “남는 자원”이 줄어들어 비용이 내려갑니다.

2) 빠른 스케일 인과 Consolidation

Karpenter의 강력한 기능 중 하나가 Consolidation(통합) 입니다.

  • 여러 노드에 흩어진 파드를 재배치해 더 적은 노드로 합치고
  • 불필요해진 노드를 종료

트래픽이 빠르게 떨어지는 서비스(예: 점심 피크, 이벤트성 트래픽)에서 이 기능이 비용 절감에 크게 기여합니다.

3) Spot을 “현실적으로” 섞기 쉬움

Spot은 비용 절감의 치트키지만, 운영 리스크(중단)가 있습니다. Karpenter는 다음을 쉽게 구성하게 해줍니다.

  • Spot 우선 + On-Demand 폴백
  • 다양한 인스턴스 타입을 풀로 묶어 Spot 중단 확률 감소
  • 워크로드별로 Spot 허용/불허를 분리

40% 절감을 만드는 설계 체크리스트

여기서부터는 “Karpenter 설치”가 아니라 “절감이 실제로 나오게 하는 설계”에 집중합니다.

1) 워크로드를 최소 2계층으로 나누기

  • 기반 시스템(코어): CoreDNS, CNI, 모니터링, 인그레스 컨트롤러 등
    • 안정성이 중요하므로 On-Demand 고정(MNG 유지 권장)
  • 애플리케이션(가변): API, 배치, 워커, 크론잡 등
    • Karpenter로 탄력 운영(Spot 혼합)

현실적으로는 “전부 Karpenter”보다 코어는 MNG, 가변은 Karpenter 조합이 운영 난이도 대비 효과가 좋습니다.

2) requests/limits를 현실화하기

Karpenter는 파드의 resources.requests를 기반으로 노드를 잡습니다. requests가 과대면 단편화가 다시 생깁니다.

  • requests를 실제 사용량에 맞추고
  • HPA/VPA(또는 Goldilocks 같은 도구)로 지속 튜닝

requests 최적화만으로도 절감이 크게 나오는 경우가 많습니다.

3) PDB와 disruption 정책 정리

Consolidation으로 노드를 줄이려면 파드가 안전하게 이동할 수 있어야 합니다.

  • PDB가 너무 빡빡하면 노드를 못 줄입니다
  • topologySpreadConstraints가 과도하면 재배치가 막힙니다

Karpenter 도입 전에 “왜 스케줄링이 빡빡한가”를 문서화해두면 절감 효과가 안정적으로 나옵니다.

4) 이미지 풀 오류 같은 운영 이슈를 먼저 제거

노드가 빨리 늘어나는 환경에서 ImagePullBackOff가 자주 나면, 스케일 아웃이 비용만 증가시키고 처리량은 안 오릅니다. 프라이빗 레지스트리 인증/IRSA/이미지 풀 시크릿을 점검하세요.

Karpenter 설정 예시(핵심만)

아래 예시는 Karpenter v1 계열을 가정한 “개념용” 예시입니다. 환경에 따라 API 버전/필드가 다를 수 있으니 적용 전 문서를 확인하세요.

NodePool: Spot 우선 + On-Demand 폴백

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: apps
spec:
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    expireAfter: 720h
  template:
    metadata:
      labels:
        workload: apps
    spec:
      requirements:
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"]
        - key: node.kubernetes.io/instance-type
          operator: In
          values:
            - m6a.large
            - m6a.xlarge
            - c6a.large
            - c6a.xlarge
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: apps
      taints:
        - key: dedicated
          value: apps
          effect: NoSchedule

포인트는 다음입니다.

  • karpenter.sh/capacity-typespoton-demand를 함께 넣어 Spot 부족 시 자동 폴백
  • 인스턴스 타입을 1개가 아니라 여러 개로 둬서 가격/수급 변동에 강하게
  • taints로 앱 워크로드만 이 풀을 쓰게 분리

EC2NodeClass: 서브넷/보안그룹/스토리지

apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: apps
spec:
  amiFamily: AL2023
  role: eks-node-role-apps
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-eks
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-eks
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 50Gi
        volumeType: gp3
        deleteOnTermination: true

앱 디플로이먼트: Spot 허용 워크로드 예시

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      tolerations:
        - key: dedicated
          operator: Equal
          value: apps
          effect: NoSchedule
      containers:
        - name: api
          image: 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/api:2026-02-01
          resources:
            requests:
              cpu: "300m"
              memory: "512Mi"
            limits:
              cpu: "1000m"
              memory: "1024Mi"

여기서 requests가 핵심입니다. requests가 과도하면 Karpenter가 더 큰 노드를 뽑아 비용이 증가합니다.

“노드그룹 vs Karpenter” 비용 비교 프레임

비용을 비교할 때는 단순히 노드 시간당 단가가 아니라 아래 항목을 함께 봐야 합니다.

1) 유휴 비용(Idle)과 단편화(Fragmentation)

  • MNG: 스케일 인 지연, 고정 인스턴스 타입으로 유휴가 누적
  • Karpenter: consolidation으로 유휴를 줄이기 쉬움

2) 피크 대응 비용(Overprovision)

  • MNG: 피크를 대비해 minSize를 높게 잡는 순간 고정비가 됨
  • Karpenter: 피크에만 늘리고 빠르게 회수 가능

3) Spot 활용률과 중단 대응 비용

  • Spot을 무작정 늘리면 장애 비용이 커집니다
  • Karpenter는 타입 다양화로 중단 리스크를 낮추지만, PDB/재시도/큐잉 같은 앱 설계가 받쳐줘야 합니다

4) 운영 복잡도 비용

  • Karpenter는 강력하지만, “노드가 왜 생겼는지/왜 줄지 않는지”를 관측해야 합니다
  • 이벤트, 스케줄링 제약, PDB, daemonset 오버헤드 등으로 consolidation이 막히는 케이스가 자주 나옵니다

절감이 깨지는 흔한 함정 7가지

  1. requests 과대: 실제 사용량보다 2~5배로 잡혀 노드가 커짐
  2. PDB 과보호: minAvailable이 높아 노드 축소가 불가
  3. DaemonSet 오버헤드: 노드당 고정 비용이 커서 작은 노드가 비효율적
  4. 인스턴스 타입 풀 부족: 1~2개 타입만 허용해 Spot 수급이 불안정
  5. AZ 제약 과도: 특정 AZ에만 묶여 가격/수급 최적화가 어려움
  6. 스토리지/네트워크 요구 과도: 큰 루트볼륨, 높은 ENI 요구로 후보가 줄어듦
  7. 스케줄링 정책 과도: anti-affinity, topology spread가 과도해 binpack이 깨짐

단계별 마이그레이션 전략(운영 안정성 우선)

1단계: 코어는 MNG 유지, 앱만 Karpenter로 분리

  • 코어 MNG는 on-demand 고정
  • 앱 네임스페이스에만 tolerations를 붙여 Karpenter 노드로 스케줄

2단계: Spot 혼합 비율을 점진적으로 확대

  • 처음에는 On-Demand 비중을 높게
  • 안정성 확인 후 Spot 확대
  • 중단 내성 없는 워크로드는 계속 On-Demand에 유지

3단계: consolidation 최적화

  • PDB/스프레드/affinity를 재점검
  • 노드가 “왜 안 줄어드는지”를 이벤트로 추적

비용 40% 절감 예시 시나리오(현실적인 계산 감각)

  • 기존: m5.xlarge 중심 MNG 20대 상시 유지(피크 대비)
  • 실제 평균 부하: 피크의 45~55%
  • 문제: 스케일 인이 느리고, 단편화로 평균 노드 사용률이 35~45% 수준

Karpenter 전환 후:

  • 피크 때는 비슷한 총 vCPU를 확보하되
  • 평시에는 consolidation으로 노드 수를 20대에서 10~12대로 회수
  • Spot을 전체 앱 노드의 50~70%까지 안전하게 섞음

이 조합이 흔히 30~50% 절감 구간을 만듭니다. 핵심은 “평시 회수”와 “Spot 혼합”이 동시에 성립하는지입니다.

마무리: 어떤 팀에 Karpenter가 특히 잘 맞나

  • 트래픽 변동이 크고, 배치/워커처럼 탄력적인 워크로드가 많으며
  • 인스턴스 타입을 유연하게 가져갈 수 있고
  • PDB/requests/스케줄링 정책을 꾸준히 다듬을 수 있는 팀

이라면 Karpenter는 단순한 오토스케일러가 아니라 클러스터 비용 구조를 바꾸는 도구가 됩니다.

다만, “설치만 하면 절감”은 아닙니다. requests 현실화, PDB/스케줄링 제약 정리, Spot 내성 설계까지 함께 가야 40% 절감이 재현됩니다.