13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 노드 오토스케일링

  • [k8s] Cluster Autoscaler에서 Karpenter로 마이그레이션 결정 기준 및 전환 전략

    [k8s] Cluster Autoscaler에서 Karpenter로 마이그레이션 결정 기준 및 전환 전략

    [Kubernetes] Cluster Autoscaler에서 Karpenter로 마이그레이션: 언제, 어떻게 전환할까요?

    안녕하세요, 13년차 서버실 지킴이입니다. 오늘은 Kubernetes(쿠버네티스) 환경에서 노드 오토스케일링(Auto Scaling)을 고민하는 분들을 위한 이야기를 해볼까 합니다. 특히 EKS (Amazon Elastic Kubernetes Service)를 운영하면서 Cluster Autoscaler (CA)의 한계를 느끼고 Karpenter로의 마이그레이션을 고민하는 분들이라면, 제가 직접 겪었던 경험과 삽질 끝에 얻은 노하우가 도움이 될 거예요.

    클라우드 환경에서 Kubernetes 클러스터를 운영하다 보면, 워크로드(Workload)의 변화에 따라 노드를 유연하게 늘리고 줄이는 것이 정말 중요합니다. 비용 최적화는 물론이고, 서비스 안정성에도 직결되거든요. 처음에는 Cluster Autoscaler(클러스터 오토스케일러)가 만능인 줄 알았는데, 막상 써보니 아쉬운 점들이 꽤 있더라고요. 특히 급작스러운 트래픽 증가나 스팟 인스턴스(Spot Instance) 활용 시 Karpenter가 보여주는 퍼포먼스는 저를 깜짝 놀라게 했습니다.

    오늘은 Cluster Autoscaler에서 Karpenter로의 전환을 언제 고려해야 하는지, 그리고 실제 전환은 어떻게 진행해야 하는지에 대한 저만의 결정 기준과 전략을 솔직하게 공유해 드릴게요. 삽질 과정도 가감 없이 보여드릴 테니, 함께 살펴보시죠!

    Karpenter가 도입된 Kubernetes 클러스터의 노드 오토스케일링 아키텍처 개요도

    Cluster Autoscaler와 Karpenter: 핵심 개념 차이

    본격적인 마이그레이션 이야기를 하기 전에, 두 오토스케일링 도구가 어떻게 다른지 간단히 짚고 넘어갈게요. 쉽게 말해 접근 방식 자체가 다릅니다.

    Cluster Autoscaler (CA): 그룹 기반 오토스케일링

    • 작동 방식: Cluster Autoscaler는 AWS Auto Scaling Group (ASG)을 기반으로 작동합니다. 즉, 미리 정의된 ASG의 최소/최대 인스턴스 개수 범위 내에서 노드를 추가하거나 줄이죠.
    • 장점: 비교적 설정이 간단하고, 오랫동안 사용되어 안정성이 검증되었습니다. 기존 EC2 인스턴스 관리 방식에 익숙하다면 접근하기 쉽습니다.
    • 단점:
      • 느린 스케일 아웃(Scale Out) 속도: ASG가 새 인스턴스를 프로비저닝(Provisioning)하는 데 시간이 걸립니다. 워크로드 요청이 급증할 때 노드 부족 현상이 생길 수 있어요.
      • 비효율적인 리소스 활용: 특정 파드(Pod)에 필요한 리소스 타입을 정확히 맞추기 어렵습니다. ASG는 특정 인스턴스 타입이나 몇 가지 인스턴스 타입 묶음으로 구성되니까요. 이 때문에 kube-scheduler (쿠베 스케줄러)가 파드를 노드에 배치하지 못하는 ‘스케줄링 불가(unschedulable)’ 상태가 발생할 수 있습니다.
      • 스팟 인스턴스 활용 제약: 스팟 인스턴스를 활용하더라도, ASG의 인스턴스 풀(Pool)이 제한적이라 유연성이 떨어집니다.

    Karpenter: 파드 기반 오토스케일링

    • 작동 방식: Karpenter는 스케줄링되지 않은 파드를 직접 감지하고, 해당 파드에 가장 적합한 EC2 인스턴스를 직접 프로비저닝합니다. ASG를 거치지 않고 EC2 RunInstances API를 직접 호출해서 노드를 띄우는 거죠.
    • 장점:
      • 압도적인 스케일 아웃 속도: 필요한 노드를 거의 실시간으로 생성하기 때문에 워크로드 변화에 매우 빠르게 대응합니다. 제가 직접 써보니 CA보다 훨씬 빨랐습니다.
      • 최적의 리소스 활용: 파드가 요구하는 CPU, 메모리, GPU 등 리소스에 맞춰 가장 효율적인 EC2 인스턴스 타입을 선택합니다. 스팟 인스턴스 활용도 극대화해서 비용 절감 효과가 커요.
      • 단순한 관리: ASG를 직접 관리할 필요 없이, Karpenter의 Provisioner (프로비저너) 설정 하나로 노드 프로비저닝 정책을 관리할 수 있습니다.
    • 단점:
      • 초기 학습 곡선: 새로운 개념과 설정이 필요해서 처음에는 좀 낯설 수 있습니다.
      • 클라우드 종속성: 현재는 AWS EKS에 특화되어 있습니다 (다른 클라우드 지원도 개발 중이지만, 현재로선 AWS가 주력입니다).

    Karpenter로의 마이그레이션 결정 기준: 언제 전환해야 할까요?

    제가 13년차 인프라 엔지니어로서 여러 환경을 경험해보니, 마이그레이션은 항상 신중해야 하더라고요. 무조건 좋다고 따라가는 것보다, 우리 서비스에 어떤 이점이 있을지 명확히 파악하는 게 중요합니다. 다음 질문들에 해당한다면 Karpenter로의 전환을 적극적으로 고려해볼 때입니다.

    • 잦은 스케일링 이벤트와 느린 노드 확장 속도에 불만이 있다:

      특히 이벤트 기반(Event-driven) 서비스나 예측 불가능한 트래픽 패턴을 가진 서비스라면 CA의 스케일 아웃 속도가 병목이 될 수 있습니다. "파드가 Pending(대기) 상태인데 노드가 왜 이렇게 늦게 뜨지?" 라는 질문을 자주 하셨다면 Karpenter가 답이 될 수 있습니다.

    • 클라우드 비용 최적화가 시급하다:

      CA는 ASG가 정해준 인스턴스 타입 내에서만 노드를 띄우다 보니, 파드의 리소스 요구사항과 정확히 일치하는 인스턴스를 찾기 어렵습니다. Karpenter는 파드에 딱 맞는 최적의 인스턴스를 찾아 스팟 인스턴스까지 적극적으로 활용하기 때문에, 불필요한 리소스 낭비를 줄여줍니다. 저희 홈랩에서도 스팟 인스턴스 활용률이 훨씬 높아지면서 비용이 꽤 절감됐습니다.

    • 노드 타입 관리가 복잡하다고 느낀다:

      CA를 사용하면 다양한 워크로드를 위해 여러 ASG를 만들고 관리해야 할 때가 많습니다. Karpenter는 Provisioner (프로비저너) 하나로 다양한 인스턴스 타입을 유연하게 관리할 수 있어 운영 부담이 줄어듭니다.

    • 특정 리소스(GPU, 고성능 CPU 등) 요구사항이 있는 파드가 많다:

      머신러닝(Machine Learning) 워크로드처럼 특정 GPU나 고성능 CPU를 요구하는 파드들이 있다면, Karpenter가 해당 파드에 맞는 노드를 즉시 프로비저닝해서 스케줄링 효율을 극대화할 수 있습니다.

    Karpenter로의 전환 전략: 실전 구현

    이제 Karpenter로 마이그레이션하는 실제 과정을 단계별로 살펴보겠습니다. 저는 EKS 환경을 기준으로 설명드릴게요.

    단계 1: Karpenter 설치 및 IAM 권한 설정

    Karpenter는 AWS API를 직접 호출해서 EC2 인스턴스를 생성하고 관리해야 하므로, 적절한 IAM(Identity and Access Management) 권한이 필수입니다. 공식 문서에 따라 IAM Role과 Service Account를 생성하고, Karpenter 컨트롤러를 설치합니다. 이 부분은 공식 문서가 워낙 잘 되어 있어서 그대로 따라가시면 됩니다. 핵심은 Karpenter가 EC2, IAM, SSM 등의 리소스에 접근할 수 있는 권한을 부여하는 것입니다.

    설치 후에는 Karpenter Controller Pod가 잘 뜨는지 확인해야 합니다.

    kubectl get pods -n karpenter
    # 예시 출력:
    # NAME                         READY   STATUS    RESTARTS   AGE
    # karpenter-controller-xxxxx   1/1     Running   0          5m
    

    단계 2: Provisioner 설정

    Karpenter의 핵심은 바로 Provisioner 리소스입니다. 어떤 종류의 노드를, 어떤 조건으로 생성할지 여기에 정의합니다. 처음에는 너무 복잡하게 생각하지 마시고, 가장 기본적인 설정으로 시작하는 것을 추천합니다.

    Karpenter Provisioner YAML 설정 예시와 주요 파라미터 설명

    Karpenter Provisioner YAML 설정 예시와 주요 파라미터 설명

    apiVersion: karpenter.sh/v1beta1
    kind: Provisioner
    metadata:
      name: default
    spec:
      # Karpenter가 사용할 AMI Family를 정의합니다. EKS 최신 Optimized AMI를 사용하세요.
      # (예: AL2, AL2023, Bottlerocket, Ubuntu)
      # Karpenter는 여기에 지정된 AMI Family의 최신 EKS Optimized AMI를 자동으로 선택합니다.
      # official EKS AMIs: https://docs.aws.amazon.com/eks/latest/userguide/retrieve-ami-id.html
      amiFamily: AL2 # Amazon Linux 2 (EKS Optimized AMI) 또는 AL2023
    
      # 인스턴스 프로비저닝에 대한 요구사항을 정의합니다.
      # 여기서는 amd64 아키텍처의 온디맨드 또는 스팟 인스턴스를 사용하도록 설정했습니다.
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand", "spot"] # 스팟 인스턴스 활용을 적극 권장합니다!
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m", "r"] # 컴퓨팅, 메모리, 범용 인스턴스 카테고리
        - key: karpenter.k8s.aws/instance-family
          operator: In
          values: ["c5", "c6i", "m5", "m6i", "r5", "r6i"] # 자주 사용하는 인스턴스 패밀리
        - key: karpenter.k8s.aws/instance-size
          operator: NotIn
          values: ["nano", "micro"] # 너무 작은 인스턴스는 제외
    
      # 노드가 어떤 서브넷(Subnet)에 생성될지 태그(Tag)로 정의합니다.
      # EKS 클러스터가 사용하는 서브넷 태그와 일치해야 합니다.
      subnetSelector:
        karpenter.sh/discovery: "your-eks-cluster-name" # EKS 클러스터 이름으로 교체
    
      # 노드가 어떤 보안 그룹(Security Group)을 사용할지 태그로 정의합니다.
      securityGroupSelector:
        karpenter.sh/discovery: "your-eks-cluster-name" # EKS 클러스터 이름으로 교체
    
      # 노드에 적용될 테인츠(Taints)를 정의합니다.
      # 여기에 테인트가 있으면, 해당 테인트를 허용하는 파드만 스케줄링됩니다.
      # - key: my-app
      #   effect: NoSchedule
    
      # 노드 템플릿입니다. SSH 키페어, IAM 인스턴스 프로파일 등을 지정할 수 있습니다.
      providerRef:
        name: default
    
      # 노드 삭제 정책 (consolidation).
      # 기본적으로 파드가 없거나, 더 효율적인 노드로 대체될 수 있으면 노드를 삭제합니다.
      consolidation:
        enabled: true
        # consolidateAfter: 5m # 노드 생성 후 최소 5분은 유지 (선택 사항)
    
      # 노드 TTL(Time To Live) 설정. 노드가 일정 시간 동안 유휴 상태이거나
      # 최대 수명을 넘으면 삭제됩니다.
      ttlSecondsAfterEmpty: 300 # 노드에 파드가 없으면 300초(5분) 후 삭제
      ttlSecondsUntilExpired: 604800 # 노드는 최대 7일(604800초)까지만 유지 (수명 관리)
    
    ---
    apiVersion: karpenter.k8s.aws/v1beta1
    kind: AWSNodeTemplate
    metadata:
      name: default
    spec:
      # Karpenter가 사용할 IAM 인스턴스 프로파일을 지정합니다.
      # EKS 노드에 필요한 권한이 포함된 프로파일이어야 합니다.
      # 보통 `eksctl create iamserviceaccount` 등으로 생성됩니다.
      instanceProfile: "KarpenterNodeInstanceProfile-your-cluster-name" # 실제 프로파일 이름으로 교체
    
      # SSH 키페어를 지정하여 노드에 SSH 접속이 가능하도록 합니다. (선택 사항)
      # sshName: your-ssh-key-name
    
      # 노드에 추가적인 태그를 붙일 수 있습니다.
      tags:
        environment: production
        managed-by: karpenter
        karpenter.sh/cluster-name: "your-eks-cluster-name" # 클러스터 이름으로 교체
    

    위 YAML을 적용하면 Karpenter가 이제 파드를 감지하고 노드를 프로비저닝할 준비가 됩니다. 여기서 중요한 포인트는 requirements 섹션입니다. 어떤 인스턴스 타입을 사용할지, 스팟(Spot)을 쓸지 온디맨드(On-Demand)를 쓸지 등 Karpenter의 동작 방식을 결정하는 핵심 설정입니다. 저는 스팟 인스턴스를 적극적으로 활용해서 비용을 절감하는 방향으로 설정했습니다.

    단계 3: Cluster Autoscaler (CA) 노드 그룹 점진적 비활성화

    Karpenter가 잘 작동하는지 확인하면서, 기존 CA가 관리하던 노드 그룹(ASG)을 점진적으로 스케일 다운(Scale Down)해야 합니다. 한 번에 모든 노드 그룹을 비활성화하면 서비스 중단 위험이 있으니, 워밍업(Warm-up) 기간을 두는 것이 좋습니다.

    1. 새로운 파드를 배포하거나 기존 파드를 재시작하여 Karpenter가 새 노드를 잘 띄우는지 관찰합니다.
    2. Karpenter가 프로비저닝한 노드가 충분히 확보되었다고 판단되면, CA가 관리하는 ASG의 desired capacity를 0으로 설정합니다.
    3. ASG의 최소/최대 인스턴스 수도 0으로 설정하여 CA가 더 이상 노드를 관리하지 않도록 합니다.
    # EKS 노드 그룹 목록 확인 (eksctl 사용 예시)
    eksctl get nodegroup --cluster your-eks-cluster-name
    
    # 특정 노드 그룹의 desired capacity를 0으로 설정
    # (eksctl 명령은 ASG도 함께 조정합니다)
    eksctl scale nodegroup --cluster your-eks-cluster-name --name your-nodegroup-name --nodes 0 --nodes-min 0 --nodes-max 0
    
    # 또는 AWS CLI로 ASG 직접 수정 (ASG 이름 확인 필요)
    # aws autoscaling update-auto-scaling-group --auto-scaling-group-name your-asg-name --desired-capacity 0 --min-size 0 --max-size 0
    

    이렇게 하면 CA가 관리하던 노드들은 서서히 드레인(Drain)되고 종료되며, Karpenter가 그 역할을 완전히 넘겨받게 됩니다. 이 과정에서 파드들이 새로운 Karpenter 노드로 잘 재스케줄링되는지 꼼꼼히 확인해야 합니다.

    주의사항 및 트러블슈팅: 삽질 경험

    제가 Karpenter를 도입하면서 겪었던 몇 가지 삽질 경험과 주의사항을 공유합니다. 이걸 미리 아셨다면 여러분은 저보다 훨씬 적게 고생하실 거예요. 😅

    • ⚠️ IAM 권한은 정말 중요합니다!

      Karpenter가 EC2 인스턴스를 직접 다루기 때문에 IAM 권한이 조금만 잘못되어도 노드가 뜨지 않습니다. 특히 ec2:RunInstances, ec2:TerminateInstances, iam:PassRole 등의 권한이 제대로 부여되었는지 반드시 확인하세요. 저는 iam:PassRole을 빼먹어서 한참 헤맸습니다. Karpenter Controller 로그를 확인하면 어떤 권한이 부족한지 명확하게 나옵니다.

      # Karpenter Controller 로그 확인
      kubectl logs -f -n karpenter $(kubectl get pods -n karpenter -l app.kubernetes.io/name=karpenter -o name)
      
    • Pod Disruption Budget (PDB) 고려:

      Karpenter는 노드 통합(Consolidation) 기능을 통해 불필요한 노드를 효율적으로 제거합니다. 이때 PDB (Pod Disruption Budget)가 설정된 파드들은 Karpenter의 노드 종료 작업을 방해할 수 있습니다. PDB가 너무 엄격하면 Karpenter가 노드를 줄이지 못하고 비용이 낭비될 수 있으니, 워크로드의 특성에 맞춰 PDB를 적절히 설정해야 합니다.

    • Initial Scale-up Delay (초기 스케일업 지연) 착시:

      Karpenter는 ASG를 사용하지 않고 바로 EC2 인스턴스를 띄우기 때문에, 처음 노드가 올라올 때까지의 시간이 CA보다 오히려 길게 느껴질 수 있습니다. 하지만 이는 인스턴스 부팅 및 EKS 클러스터 조인(Join) 과정이 포함되기 때문이고, 실제 “스케줄링되지 않은 파드”를 “노드에 할당”하는 과정은 훨씬 빠릅니다. 이 차이를 이해하고 인내심을 가져야 합니다. 🙂

    • Spot Instance Interruptions (스팟 인스턴스 중단) 대비:

      Karpenter는 스팟 인스턴스를 적극 활용하여 비용을 절감하지만, 스팟 인스턴스는 언제든지 AWS에 의해 중단될 수 있습니다. 중요한 스테이트풀(Stateful) 워크로드에는 스팟 인스턴스를 사용하지 않거나, 중단에 강한 아키텍처(예: 분산 시스템, 재시작 가능한 작업)를 구성하는 것이 중요합니다.

    검증 및 결과 확인

    Karpenter 마이그레이션이 성공적으로 이루어졌는지 확인하는 방법은 다음과 같습니다.

    1. 노드 상태 확인: kubectl get nodes 명령으로 노드가 잘 뜨고 준비(Ready) 상태인지 확인합니다. Karpenter가 띄운 노드에는 특정 레이블(Label)이나 태그가 붙어있으니 쉽게 구분할 수 있습니다.
      kubectl get nodes -l karpenter.sh/provisioner-name=default
      # 예시 출력:
      # NAME                                           STATUS   ROLES    AGE   VERSION
      # ip-10-0-x-x.ap-northeast-2.compute.internal    Ready    <none>   5m    v1.28.x
      
    2. 파드 스케줄링 확인: 새로운 파드를 배포하거나, 기존 파드의 리소스 요청을 늘려서 Karpenter가 노드를 빠르게 프로비저닝하고 파드를 스케줄링하는지 확인합니다.
    3. Karpenter Provisioner 상태 확인:
      kubectl describe provisioner default
      # 이 명령을 통해 Karpenter가 어떤 노드를 프로비저닝하고 있는지,
      # 그리고 어떤 이벤트가 발생했는지 상세히 볼 수 있습니다.
      
    4. AWS EC2 콘솔 확인: EC2 콘솔에서 인스턴스가 Karpenter에 의해 생성되고 종료되는 것을 직접 관찰합니다. 태그를 통해 Karpenter가 관리하는 인스턴스인지 쉽게 알 수 있습니다.
    5. 비용 모니터링: AWS Cost Explorer를 통해 마이그레이션 전후의 비용 변화를 모니터링합니다. 특히 스팟 인스턴스 활용률이 높아지면서 비용이 얼마나 절감되었는지 확인하는 것이 중요합니다.
    Karpenter 도입 후 EKS 클러스터의 노드 및 파드 스케일링 성능 대시보드

    Karpenter 도입 후 EKS 클러스터의 노드 및 파드 스케일링 성능 대시보드

    Cluster Autoscaler vs. Karpenter: 비교 및 선택 기준

    제가 경험한 바를 바탕으로 두 오토스케일러의 핵심 차이점을 표로 정리해봤습니다. 어떤 상황에서 어떤 도구가 더 유리한지 판단하는 데 도움이 될 거예요.

    구분 Cluster Autoscaler (CA) Karpenter
    작동 방식 Auto Scaling Group (ASG) 기반 스케줄링되지 않은 파드 직접 감지, EC2 API 호출
    노드 프로비저닝 속도 상대적으로 느림 (ASG의 인스턴스 생성 시간) 매우 빠름 (파드 요구사항에 맞춰 즉시 생성)
    리소스 효율성 ASG 인스턴스 타입 내에서 선택, 비효율 가능성 파드 요구사항에 가장 적합한 인스턴스 선택, 높은 효율성
    비용 최적화 ASG 설정에 의존, 스팟 활용 제한적 스팟 인스턴스 적극 활용, 비용 절감 효과 큼
    관리 복잡성 여러 ASG 관리 필요 Provisioner 리소스 하나로 관리, 단순함
    주요 사용 사례 워크로드 변동이 적고 안정적인 환경, 온디맨드 위주 잦은 스케일링, 비용 최적화, 스팟 인스턴스 적극 활용 환경
    트러블슈팅 난이도 ASG 문제, CA 로그 Karpenter Controller 로그, IAM 권한, Provisioner 설정
    Kubernetes Cluster Autoscaler와 Karpenter의 주요 특징 및 마이그레이션 결정 기준 비교

    Kubernetes Cluster Autoscaler와 Karpenter의 주요 특징 및 마이그레이션 결정 기준 비교

    마무리하며: 더 나은 클러스터 운영을 위한 선택

    Cluster Autoscaler에서 Karpenter로의 마이그레이션은 단순히 도구를 바꾸는 것을 넘어, Kubernetes 클러스터의 리소스 관리 효율성과 비용 최적화를 한 단계 끌어올리는 중요한 결정입니다. 제가 직접 경험해보니, 특히 워크로드 변동성이 크고 스팟 인스턴스 활용을 통해 비용을 절감하고자 하는 환경이라면 Karpenter가 단연코 훌륭한 선택지였습니다.

    물론 새로운 도구를 도입하는 데는 초기 설정과 학습 비용이 따릅니다. 하지만 Karpenter가 제공하는 유연성과 효율성을 고려하면 충분히 투자할 가치가 있다고 생각합니다. 이 글이 여러분의 Karpenter 마이그레이션 여정에 작은 등불이 되었기를 바랍니다. 혹시 더 궁금한 점이나 제가 겪지 못했던 다른 삽질 경험이 있다면 댓글로 공유해주세요. 함께 배우고 성장하는 것이 인프라 엔지니어의 숙명이 아니겠습니까! 다음번에는 Karpenter의 고급 기능이나 다른 클라우드 환경에서의 활용 방안에 대해서도 이야기해볼 수 있으면 좋겠네요. 🎉

  • [k8s] Karpenter로 EKS 비용 절감: 실전 운영 사례와 최적화 전략

    [k8s] Karpenter로 EKS 비용 절감: 실전 운영 사례와 최적화 전략

    [인프라] Karpenter 비용 절감: EKS 중심 운영 사례와 AKS 적용 포인트

    Karpenter 비용 절감 이야기는 요즘 EKS 운영하시는 분들이라면 한 번쯤은 꼭 부딪히는 주제입니다. 저도 처음엔 단순히 노드 수만 줄이면 되겠지 싶었는데, 실제로 써보니까 그렇게 단순한 문제가 아니더라고요. 특히 트래픽이 출렁이는 서비스에서는 오토스케일링 비용이 눈에 잘 안 띄게 새고 있었습니다. 월말 청구서를 보고 나서야 “아, 이거 손봐야겠네요” 싶었던 적이 꽤 있었거든요.

    먼저 중요한 점부터 짚고 갈게요. Karpenter는 AWS EKS 환경에서 실제 많이 쓰이는 오픈소스 노드 프로비저닝(Node Provisioning) 도구입니다. 반면 AKS에서는 보통 Cluster Autoscaler(클러스터 오토스케일러)나 노드풀 전략으로 비슷한 비용 최적화를 접근합니다. 그래서 이 글은 제가 직접 많이 다뤄본 EKS + Karpenter 운영 사례를 중심으로 설명하고, 마지막에 AKS 비용 최적화에 어떻게 같은 원칙을 가져갈 수 있는지 연결해서 정리해보겠습니다.

    Karpenter 비용 절감 구조를 보여주는 EKS 전체 아키텍처 다이어그램

    이미지 설명: EKS 환경에서 Karpenter가 스케줄링 수요를 보고 노드를 빠르게 생성하고, 유휴 노드를 정리하는 흐름을 한눈에 보여주는 아키텍처입니다.

    Karpenter 최적화가 왜 비용 절감으로 바로 이어질까요?

    쉽게 말해 Karpenter는 “필요한 순간에 필요한 크기의 노드를 빠르게 붙여주는 사람”입니다. 기존 Cluster Autoscaler(클러스터 오토스케일러)는 이미 만들어둔 노드 그룹(Node Group) 안에서 증감을 고민하는 느낌이 강한데요, Karpenter는 좀 더 유연하게 인스턴스 타입(Instance Type) 선택 폭을 가져갈 수 있는 게 장점입니다.

    실제로 운영해보면 비용이 새는 지점은 대체로 비슷합니다.

    • 과하게 큰 인스턴스를 기본값처럼 쓰는 경우
    • 야간이나 비업무 시간에도 노드가 그대로 살아 있는 경우
    • Pod requests/limits 설정이 보수적으로 너무 큰 경우
    • 온디맨드(On-Demand)만 고집해서 Spot(스팟) 기회를 놓치는 경우
    • DaemonSet(데몬셋)과 시스템 파드 때문에 작은 노드가 비효율적으로 배치되는 경우

    이건 꽤 중요한데요. Karpenter 비용 절감은 단순히 “노드를 줄인다”가 아니라, 워크로드에 맞는 노드를 더 잘 고른다에 가깝습니다. 저도 처음엔 이 차이를 잘 몰라서 인스턴스 수만 보고 있었는데, 결국 핵심은 빈 시간, 빈 공간, 잘못 잡은 요청치(requests)를 줄이는 쪽이더라고요.

    EKS 비용을 줄이는 Karpenter 핵심 개념

    1. Provisioner 대신 최신 문서 기준 NodePool/EC2NodeClass 흐름 이해하기

    Karpenter는 버전이 올라가면서 리소스 모델이 바뀐 적이 있습니다. 운영 중인 버전에 따라 리소스 이름이 다를 수 있는데, 실무에서는 현재 사용 중인 차트와 CRD(Custom Resource Definition) 버전을 먼저 확인하시는 게 중요합니다. 저도 예전 예제만 보고 적용했다가 CRD mismatch(정의 불일치)로 삽질 좀 했습니다 ㅎㅎ

    2. Consolidation(통합)과 Expiration(만료) 전략

    이 기능이 꽤 큽니다. 유휴 노드가 생기면 더 적은 수의 노드로 재배치하고 남는 노드를 정리하는 식인데요. 이걸 켜두지 않으면 Karpenter를 써도 생각보다 절감폭이 안 나옵니다.

    3. 다양한 인스턴스 타입 허용

    특정 타입 하나만 고정하면 스케줄링도 경직되고 단가 최적화도 어렵습니다. 저는 CPU 아키텍처, 세대, 크기 범위를 조금 넓게 허용했을 때 훨씬 안정적이었습니다. 물론 워크로드가 특정 아키텍처에 종속되지 않는지 확인은 먼저 해야 합니다.

    4. Spot과 On-Demand 혼합

    상태 비저장(Stateless) 워크로드는 Spot을 적극 검토할 만합니다. 다만 모든 걸 Spot으로 몰면 중단(interruption)에 취약해지니, 핵심 서비스는 On-Demand 기반으로 남겨두고 배치나 비핵심 API 계층만 분리하는 식이 현실적입니다.

    항목 기존 고정 노드 그룹 Karpenter 최적화 후
    인스턴스 선택 미리 정한 몇 개 타입 위주 조건 기반으로 유연하게 선택
    유휴 노드 정리 느리거나 보수적 통합 정책으로 적극 정리
    비용 대응력 트래픽 급변 시 비효율 가능 수요 기반 대응이 쉬움
    Spot 활용 노드 그룹 설계에 묶임 워크로드별 분리 전략 수월

    실전 구현: EKS에서 Karpenter 최적화 적용한 흐름

    이제 제가 실제로 자주 쓰는 흐름으로 가보겠습니다. 아래 예시는 개념을 보여주기 위한 형태이고, 계정 구조나 네트워크 설계에 따라 이름과 태그는 바꾸셔야 합니다.

    1. EKS 클러스터 버전과 Karpenter 호환성 확인
    2. IAM 역할과 IRSA(IAM Roles for Service Accounts) 구성
    3. 서브넷/보안그룹 태그 점검
    4. EC2NodeClass와 NodePool 분리 설계
    5. 온디맨드/스팟 워크로드 분리
    6. consolidation 정책 활성화
    7. 요청치(requests) 재조정 후 실제 절감률 측정

    1. Helm(헬름)으로 Karpenter 설치

    helm repo add karpenter https://charts.karpenter.sh
    helm repo update
    
    helm upgrade --install karpenter karpenter/karpenter \
      --namespace karpenter \
      --create-namespace \
      --set settings.clusterName=my-eks-cluster \
      --set serviceAccount.create=true

    여기서 많이 놓치는 게 IAM 권한입니다. 컨트롤러는 떠 있는데 실제 인스턴스 생성이 안 되는 경우가 꽤 많거든요. 저는 처음에 “왜 파드만 Pending(대기)이지?” 싶었는데, 알고 보니 IAM 정책 누락이었습니다.

    2. EC2NodeClass 예시

    apiVersion: karpenter.k8s.aws/v1beta1
    kind: EC2NodeClass
    metadata:
      name: default
    spec:
      amiFamily: AL2
      role: KarpenterNodeRole-my-eks-cluster
      subnetSelectorTerms:
        - tags:
            karpenter.sh/discovery: my-eks-cluster
      securityGroupSelectorTerms:
        - tags:
            karpenter.sh/discovery: my-eks-cluster
      tags:
        intent: apps

    서브넷과 보안그룹 태그는 정말 중요합니다. 자동 검색이 안 되면 노드가 안 뜹니다. 로그만 보면 애매하게 보여서 시간을 꽤 잡아먹더라고요.

    3. NodePool 예시

    apiVersion: karpenter.sh/v1beta1
    kind: NodePool
    metadata:
      name: general
    spec:
      disruption:
        consolidationPolicy: WhenUnderutilized
        expireAfter: 720h
      template:
        spec:
          nodeClassRef:
            name: default
          requirements:
            - key: kubernetes.io/arch
              operator: In
              values: ["amd64"]
            - key: karpenter.sh/capacity-type
              operator: In
              values: ["on-demand", "spot"]
            - key: node.kubernetes.io/instance-type
              operator: In
              values: ["m5.large", "m5.xlarge", "m6i.large", "m6i.xlarge"]

    실제로 써보니까 인스턴스 타입을 너무 좁게 잡으면 오히려 스케줄링이 꼬입니다. 반대로 너무 넓히면 운영자가 예상하지 못한 조합이 나올 수 있으니, 워크로드 특성에 맞는 범위를 정하는 게 좋습니다.

    Karpenter 최적화 설정과 온디맨드 스팟 분리를 보여주는 구성도

    이미지 설명: NodePool, EC2NodeClass, IAM, 서브넷 태그가 어떻게 연결되는지와 온디맨드/스팟 분리 구조를 보여주는 구성도입니다.

    4. 스팟 전용 워크로드 분리

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: batch-worker
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: batch-worker
      template:
        metadata:
          labels:
            app: batch-worker
        spec:
          nodeSelector:
            karpenter.sh/capacity-type: spot
          containers:
            - name: worker
              image: public.ecr.aws/docker/library/busybox:latest
              command: ["sh", "-c", "sleep 3600"]
              resources:
                requests:
                  cpu: "250m"
                  memory: "256Mi"

    배치성 작업이나 재시도가 쉬운 서비스라면 이런 식으로 분리하는 게 꽤 잘 먹힙니다. 다만 데이터베이스 연결을 오래 붙잡는 작업이나 세션 민감한 서비스는 신중하셔야 합니다.

    ⚠️ Karpenter 운영에서 자주 겪는 문제와 해결법

    이 섹션은 진짜 경험 기반입니다. 문서만 보면 금방 될 것 같은데, 현장에서는 꼭 어딘가에서 막히더라고요.

    1. 파드는 Pending인데 노드가 생성되지 않는 경우

    • IAM 권한 누락 여부 확인
    • 서브넷/보안그룹 discovery 태그 확인
    • NodePool requirements가 너무 빡빡하지 않은지 확인
    • 리전에서 해당 인스턴스 타입 공급이 가능한지 확인

    특히 requirements 조건을 여러 개 겹치면 스케줄링 후보가 거의 사라집니다. 저는 아키텍처, 세대, capacity-type, zone까지 한꺼번에 강하게 제한했다가 노드가 안 뜬 적이 있었습니다.

    2. 절감이 기대보다 안 나오는 경우

    이건 거의 항상 requests 과다 설정이 원인이었습니다. Karpenter는 요청된 리소스를 기준으로 판단하니까, 애플리케이션 팀이 CPU 1core, 메모리 2Gi를 습관적으로 박아둔 상태면 빈 공간이 많아져도 노드를 줄이기 어렵습니다.

    kubectl top pods -A
    kubectl get pods -A -o wide
    kubectl describe node

    이 명령어로 실제 사용량과 요청치를 같이 보시면 감이 옵니다. 처음엔 귀찮아도 이 작업을 해두면 EKS 비용 줄이는 데 체감 차이가 큽니다.

    3. DaemonSet 때문에 작은 노드가 오히려 손해인 경우

    로깅 에이전트, 모니터링 에이전트, CNI 관련 파드가 노드마다 붙잖아요. 그래서 무조건 작은 노드가 좋은 게 아닙니다. 너무 잘게 쪼개면 시스템 오버헤드가 늘어납니다. 이 부분은 홈랩에서도 실험해봤는데, 작은 노드 여러 개보다 중간 크기 몇 개가 효율적인 구간이 분명히 있더라고요.

    4. Spot interruption 대응 부족

    스팟은 싸지만 공짜는 아닙니다. 중단 알림(interruption notice)을 고려한 설계가 없으면 장애 대응 비용이 더 커질 수 있어요. 오토스케일링 비용만 볼 게 아니라 운영 리스크까지 같이 보셔야 합니다.

    검증: 비용이 실제로 얼마나 줄었는지 어떻게 보나요?

    제가 직접 해보니 “30% 절감” 같은 숫자는 환경에 따라 차이가 큽니다. 다만 공통적으로는 아래 항목을 같이 봐야 의미가 있습니다.

    • 노드 총 가동 시간 감소 여부
    • 평균 노드 활용률 상승 여부
    • 스팟 비중 증가 여부
    • 배포 실패나 재시작 증가 여부
    • 응답 시간과 에러율 변화 여부

    저는 대시보드를 볼 때 단순 인프라 비용만 보지 않고, 서비스 안정성까지 같이 체크합니다. 비용은 줄었는데 장애가 늘면 그건 실패거든요.

    kubectl get node
    kubectl get pods -A
    kubectl logs -n karpenter deploy/karpenter

    추가로 클라우드 비용 분석 도구에서 노드 사용 추이를 월간으로 비교해보면 좋습니다. 같은 트래픽 수준에서 유휴 시간이 줄고, 피크 시간 확장 속도가 좋아졌다면 방향을 잘 잡은 겁니다.

    Karpenter 비용 절감 결과를 보여주는 노드 사용률 및 비용 대시보드

    이미지 설명: 비용 분석 대시보드에서 최적화 전후 노드 수, 활용률, 유휴 시간 변화를 비교하는 예시입니다.

    AKS 비용 최적화는 어떻게 연결하면 될까요?

    많이들 헷갈리시는데요. AKS 비용 최적화라는 관점은 분명히 중요하지만, 실무적으로는 Karpenter 자체보다 Cluster Autoscaler, 노드풀 분리, Spot VM, 요청치 정리 같은 방식으로 접근하는 게 일반적입니다. 즉, 도구는 달라도 원칙은 거의 같습니다.

    최적화 원칙 EKS AKS
    수요 기반 노드 증감 Karpenter Cluster Autoscaler 중심
    워크로드 분리 NodePool/taint/toleration Node Pool/taint/toleration
    저비용 인스턴스 활용 Spot Spot VM
    리소스 요청 최적화 필수 필수

    그러니까 “EKS는 Karpenter, AKS는 다른 도구”라고 외우기보다, 워크로드를 세분화하고 유휴 자원을 줄이며 저비용 노드를 안전하게 섞는 전략이 핵심이라고 보시면 됩니다. 이 관점으로 보면 클라우드가 달라도 사고방식이 꽤 통일됩니다.

    실무 체크리스트: 제가 마지막에 꼭 보는 항목

    1. requests/limits가 실제 사용량과 크게 어긋나지 않는가
    2. 온디맨드와 스팟 워크로드가 명확히 분리되어 있는가
    3. NodePool 조건이 과도하게 제한적이지 않은가
    4. 유휴 노드 정리 정책이 활성화되어 있는가
    5. 비용 절감 후에도 SLO(Service Level Objective)에 영향이 없는가

    이 체크리스트만 꾸준히 봐도 Karpenter 최적화 방향을 크게 벗어나지 않습니다. 사실 화려한 기능보다 이런 기본기가 더 중요하더라고요.

    EKS 비용과 AKS 비용 최적화 원칙을 비교한 요약 인포그래픽

    이미지 설명: EKS와 AKS 각각에서 적용 가능한 비용 절감 원칙을 비교 정리한 요약 인포그래픽입니다.

    정리와 다음 단계

    정리해보면 이렇습니다. Karpenter 비용 절감은 EKS에서 꽤 강력한 선택지이고, 제대로 설정하면 체감이 분명히 옵니다. 다만 만능은 아닙니다. 요청치가 엉망이거나 워크로드 분리가 안 되어 있으면 기대만큼 안 줄어듭니다. 저도 처음엔 “설치만 하면 끝나는 거 아닌가?” 싶었는데, 실제로는 관찰과 조정이 더 중요했습니다.

    그리고 AKS 쪽은 Karpenter를 억지로 끼워 맞추기보다, 같은 최적화 원칙을 AKS 네이티브 방식으로 적용하는 게 현실적입니다. 이건 꽤 중요한데요. EKS 비용, AKS 비용, 오토스케일링 비용 모두 결국은 워크로드 이해도가 좌우합니다.

    혹시 지금 클러스터 비용이 생각보다 많이 나오고 계신가요? 그렇다면 제일 먼저 requests/limits부터 다시 보세요. 그다음 노드 풀 전략, 그리고 마지막으로 자동화 정책을 손보시면 됩니다. 이전 글에서 다룬 Kubernetes 리소스 요청치 튜닝 내용이 있다면 같이 보시면 도움이 되고, 다음 글에서는 HPA(Horizontal Pod Autoscaler)와 Karpenter를 함께 쓸 때 생기는 상호작용도 정리해볼 예정입니다.

    자주 묻는 질문

    Karpenter만 설치하면 바로 비용이 줄어드나요?

    아닙니다. 요청치 설정, 워크로드 분리, 유휴 노드 정리 정책이 같이 맞아야 효과가 납니다.

    스팟만 많이 쓰면 무조건 유리한가요?

    아닙니다. 중단 가능성이 있어서 서비스 특성에 따라 온디맨드와 섞어야 합니다.

    AKS에도 같은 전략을 적용할 수 있나요?

    네, 가능합니다. 다만 도구는 다를 수 있고, 원칙은 비슷하다고 보시면 됩니다.

  • [Kubernetes] Karpenter vs Cluster Autoscaler 비교 분석

    [Kubernetes] Karpenter vs Cluster Autoscaler 비교 분석

    [Kubernetes] Karpenter vs Cluster Autoscaler 비교 분석

    Karpenter vs Cluster Autoscaler 이야기는 Kubernetes(쿠버네티스) 운영하시는 분들이 한 번쯤 꼭 부딪히는 주제입니다. 파드(Pod)가 늘어나는데 노드(Node)가 제때 안 붙으면 서비스가 밀리고, 반대로 너무 빨리 늘어나면 비용이 튀거든요. 저도 처음엔 HPA(Horizontal Pod Autoscaler, 파드 수평 확장)만 잘 걸어두면 끝인 줄 알았는데, 실제로 운영해보니 워크로드 확장과 노드 확장은 완전히 다른 문제더라고요. 특히 EKS 같은 클라우드 환경에서 직접 써보니까 Karpenter와 Cluster Autoscaler는 비슷해 보여도 철학이 꽤 다릅니다.

    이번 글에서는 Karpenter vs Cluster Autoscaler를 실무 관점에서 비교해보겠습니다. 단순히 기능 목록만 나열하는 게 아니라, 어떤 워크로드에서 무엇이 더 잘 맞는지, 설치할 때 어디서 삽질하는지, 검증은 어떻게 해야 하는지까지 정리해보겠습니다. 혹시 지금 Kubernetes 오토스케일링 구성을 만지시는 중이라면 꽤 바로 도움이 되실 겁니다.

    Cluster Autoscaler와 Karpenter가 각각 어떤 방식으로 노드를 늘리고 줄이는지 한눈에 보여주는 개요 다이어그램이 들어갈 자리입니다.

    Kubernetes 오토스케일링이 왜 생각보다 어렵냐면요

    쉽게 말해, Kubernetes 오토스케일링은 두 층으로 나뉩니다. 하나는 파드 수를 늘리는 것이고, 다른 하나는 그 파드를 올릴 노드를 확보하는 것입니다. HPA가 앞단이라면, Karpenter나 Cluster Autoscaler는 뒷단이라고 보시면 됩니다.

    • HPA: CPU, 메모리, 커스텀 메트릭 기준으로 파드 수를 늘리고 줄립니다.
    • Cluster Autoscaler: 기존 노드 그룹(Node Group, 노드 묶음)의 크기를 늘리거나 줄입니다.
    • Karpenter: 스케줄링되지 못한 파드를 보고, 필요한 조건에 맞는 노드를 더 직접적으로 프로비저닝(Provisioning, 자원 생성)합니다.

    여기서 중요한 포인트가 하나 있습니다. Cluster Autoscaler는 미리 정의된 노드 그룹 중심으로 생각하고, Karpenter는 파드 요구사항 중심으로 생각합니다. 이 차이가 운영 난이도, 비용 최적화, 확장 속도에 꽤 큰 영향을 줍니다.

    Karpenter vs Cluster Autoscaler: 핵심 개념 차이

    처음 문서를 보면 둘 다 자동으로 노드를 늘려주는 도구라서 별 차이 없어 보이는데요, 실제로 써보면 운영 감각이 다릅니다. 제가 직접 비교하면서 느낀 건 아래 표 하나로 많이 정리되더라고요.

    항목 Cluster Autoscaler Karpenter
    기본 동작 방식 기존 노드 그룹 크기 조절 파드 요구사항에 맞춰 노드 직접 생성
    확장 기준 스케줄 불가 파드를 보고 적절한 노드 그룹 선택 스케줄 불가 파드의 리소스 조건을 바로 계산
    노드 유연성 노드 그룹 설계에 크게 의존 인스턴스 타입 선택 폭이 넓음
    운영 모델 ASG/Managed Node Group 중심 Provisioner/NodePool 성격의 선언적 관리
    장점 구조가 익숙하고 보수적 운영에 적합 유연성, 속도, 비용 최적화 측면에서 강점
    주의점 노드 그룹이 많아지면 복잡도 증가 초기 설계와 제약조건 관리가 중요

    정리하면 이렇습니다. Cluster Autoscaler는 전통적인 방식입니다. 이미 만들어 둔 노드 그룹이 있고, 그 그룹의 min/max 범위 안에서 증감시키죠. 반면 Karpenter는 필요한 자원을 그때그때 맞춰 뽑아내는 쪽에 가깝습니다. 그래서 워크로드 패턴이 자주 바뀌거나, 다양한 인스턴스 타입을 섞어 쓰고 싶을 때 체감이 꽤 납니다.

    언제 Karpenter가 유리하고, 언제 Cluster Autoscaler가 편한가

    이건 솔직히 정답이 하나는 아닙니다. 운영팀 성향, 클러스터 규모, 클라우드 의존도에 따라 달라지거든요. 저도 처음엔 무조건 신형이 좋아 보였는데, 몇 번 굴려보니 케이스가 나뉘더라고요.

    Cluster Autoscaler가 잘 맞는 경우

    • 이미 Managed Node Group 기반 운영 체계가 안정적으로 잡혀 있는 경우
    • 보안, 승인, 변경 관리 때문에 노드 타입을 엄격히 통제해야 하는 경우
    • 여러 팀이 공용으로 쓰는 클러스터라서 예측 가능한 증설 패턴이 중요한 경우
    • 기존 운영팀이 노드 그룹 기반 모델에 익숙한 경우

    Karpenter가 잘 맞는 경우

    • 워크로드 확장 패턴이 들쭉날쭉해서 빠른 대응이 필요한 경우
    • 다양한 인스턴스 타입 조합으로 비용 최적화를 하고 싶은 경우
    • 스케줄링 요구사항이 세밀해서 노드 그룹을 많이 쪼개기 싫은 경우
    • 빈번한 배치 작업, CI 러너, 이벤트성 트래픽처럼 탄력성이 중요한 경우

    제 경험상 노드 그룹이 많아질수록 Cluster Autoscaler는 운영 피로도가 올라갑니다. 반대로 Karpenter는 초반 설계만 잘못 잡으면 예상치 못한 노드 생성 패턴 때문에 당황하게 되더라고요. 그러니까 둘 중 뭐가 무조건 더 좋다기보다, 운영 모델에 맞는 선택이 더 중요합니다.

    실전 구현 1: Cluster Autoscaler 구성 흐름

    먼저 Cluster Autoscaler부터 보겠습니다. 예시는 EKS 환경 기준으로 적겠습니다. 다른 클라우드에서도 개념은 비슷합니다. 핵심은 오토스케일 대상 노드 그룹이 먼저 존재해야 한다는 점입니다.

    1. 오토스케일 가능한 노드 그룹을 준비합니다.
    2. 노드 그룹의 최소/최대 크기를 정합니다.
    3. Cluster Autoscaler를 클러스터에 배포합니다.
    4. 스케줄 불가 파드가 생기면 해당 노드 그룹 크기를 늘립니다.
    helm repo add autoscaler https://kubernetes.github.io/autoscaler
    helm repo update
    
    helm upgrade --install cluster-autoscaler autoscaler/cluster-autoscaler \
      --namespace kube-system \
      --set autoDiscovery.clusterName=my-cluster \
      --set awsRegion=ap-northeast-2 \
      --set rbac.serviceAccount.create=true

    설치 자체는 그렇게 복잡하지 않습니다. 근데 실제로는 IAM(Role, 권한 역할), 오토디스커버리 태그, 노드 그룹 min/max 값 같은 주변 설정에서 삽질을 많이 하게 됩니다. 특히 노드 그룹 태그가 안 맞으면 파드가 Pending(펜딩, 스케줄 대기) 상태로 남아 있는데도 노드가 안 늘어납니다. 저도 처음엔 로그만 한참 봤네요.

    kubectl -n kube-system logs deploy/cluster-autoscaler
    kubectl get pods -A
    kubectl describe pod <pending-pod-name>

    여기서 보는 포인트는 간단합니다. 파드가 왜 스케줄링되지 않았는지, 그리고 Cluster Autoscaler가 어떤 노드 그룹을 확장 후보로 판단했는지입니다.

    실전 구현 2: Karpenter 구성 흐름

    Karpenter는 접근 방식이 다릅니다. 미리 노드 그룹을 세세하게 많이 만들기보다, 어떤 종류의 노드를 허용할지 정책으로 정의하는 느낌에 가깝습니다. 그래서 처음엔 구조가 낯선 감이 있더라고요. 저도 처음엔 이게 뭔가 싶었는데, 한번 감을 잡고 나니 꽤 편하더라고요.

    1. Karpenter 컨트롤러를 설치합니다.
    2. 클라우드 권한과 네트워크 조건을 연결합니다.
    3. 어떤 노드를 만들 수 있는지 정책을 정의합니다.
    4. 스케줄 불가 파드가 생기면 그 요구사항을 기반으로 노드를 생성합니다.
    helm repo add karpenter https://charts.karpenter.sh
    helm repo update
    
    helm upgrade --install karpenter karpenter/karpenter \
      --namespace karpenter \
      --create-namespace
    apiVersion: karpenter.sh/v1alpha5
    kind: Provisioner
    metadata:
      name: default
    spec:
      requirements:
        - key: kubernetes.io/arch
          operator: In
          values:
            - amd64
        - key: kubernetes.io/os
          operator: In
          values:
            - linux
      limits:
        resources:
          cpu: "1000"
      ttlSecondsAfterEmpty: 30

    요즘 Karpenter 관련 리소스 모델은 환경과 시점에 따라 구성이 조금씩 달라질 수 있어서, 실제 배포 전에는 현재 사용하는 배포 가이드와 CRD(Custom Resource Definition, 사용자 정의 리소스 정의)를 반드시 맞춰보셔야 합니다. 여기서는 비교 분석이 핵심이라, 파드 요구사항 기반으로 노드를 뽑아낸다는 운영 개념에 집중해서 보시면 됩니다.

    Karpenter 정책 기반 노드 생성 흐름을 보여주는 Kubernetes 오토스케일링 이미지

    Karpenter가 파드의 요구 리소스를 읽고 적절한 노드를 동적으로 생성하는 흐름을 설명하는 구성 이미지 자리입니다.

    워크로드 확장 테스트: 직접 확인하는 방법

    설치보다 중요한 게 검증입니다. 오토스케일링은 붙어 있다고 끝이 아니거든요. 원하는 타이밍에, 원하는 방식으로, 과하지 않게 확장되는지를 봐야 합니다. 저는 보통 부하 테스트용 디플로이먼트(Deployment)를 하나 띄워두고 확인합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: inflate
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: inflate
      template:
        metadata:
          labels:
            app: inflate
        spec:
          containers:
            - name: inflate
              image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
              resources:
                requests:
                  cpu: "1"
                  memory: "1Gi"
                limits:
                  cpu: "1"
                  memory: "1Gi"
    kubectl apply -f inflate.yaml
    kubectl scale deployment inflate --replicas=20
    kubectl get pods -w
    kubectl get nodes -w

    이 테스트에서 봐야 할 건 세 가지입니다.

    • 확장 속도: Pending 파드가 얼마나 빨리 해소되는지
    • 적합성: 필요한 크기의 노드가 제대로 붙는지
    • 정리 속도: 부하가 끝난 뒤 빈 노드가 얼마나 깔끔하게 제거되는지

    실제로 써보니까 Karpenter는 워크로드 확장에 좀 더 민감하게 반응하는 느낌이 있었고, Cluster Autoscaler는 노드 그룹 구조를 잘 짜놨을 때 안정감이 있었습니다. 드디어 됐다! 싶은 순간이 오긴 오는데, 그 전에 로그와 이벤트를 많이 보게 됩니다 ㅎㅎ

    워크로드 확장 과정에서 Pending 파드가 노드 증설로 해결되는 Kubernetes 오토스케일링 이미지

    파드가 Pending 상태가 되었다가 새 노드가 생성되고 Running으로 전환되는 과정을 단계별로 보여주는 이미지 자리입니다.

    ⚠️ 제가 실제로 자주 겪었던 트러블슈팅 포인트

    이 섹션이 제일 중요할 수도 있습니다. 문서대로만 보면 금방 될 것 같지만, 현실은 그렇지 않더라고요.

    1. 파드는 Pending인데 노드가 안 늘어나는 경우

    • 리소스 요청값(requests)이 비현실적으로 큰지 확인합니다.
    • 노드 선택 조건(nodeSelector, affinity, taint/toleration)이 너무 빡빡한지 봅니다.
    • Cluster Autoscaler라면 대상 노드 그룹 태그와 범위를 확인합니다.
    • Karpenter라면 허용된 인스턴스 조건과 서브넷/보안 그룹 연결을 확인합니다.

    처음엔 저도 컨트롤러 문제인 줄 알았는데, 알고 보니 파드 스펙 자체가 너무 까다로운 경우가 꽤 있었습니다. 특히 GPU나 특정 아키텍처를 요구하는 워크로드는 더 그렇습니다.

    2. 노드는 늘어나는데 생각보다 비효율적인 경우

    이건 비용 문제로 바로 이어집니다. Cluster Autoscaler는 노드 그룹 단위로 움직이기 때문에, 작은 파드 몇 개 때문에 상대적으로 큰 노드가 붙는 상황이 생기곤 합니다. Karpenter도 제약 조건을 널널하게 열어두면 예상보다 다양한 노드가 만들어지곤 해요. 그래서 요청 리소스(requests) 튜닝이 정말 중요합니다.

    3. 축소(scale down)가 너무 늦거나 안 되는 경우

    • PodDisruptionBudget(PDB, 파드 중단 예산) 때문에 축소가 막힐 수 있습니다.
    • DaemonSet(데몬셋)과 로컬 스토리지 사용 여부도 확인해야 합니다.
    • 노드가 비어 보여도 eviction(축출) 조건 때문에 남아 있을 수 있습니다.

    이 부분은 진짜 많이 놓칩니다. 저도 한동안 왜 비용이 안 줄지 봤더니, 특정 시스템 파드가 노드 정리를 막고 있더라고요.

    검증과 결과: 무엇을 기준으로 비교해야 하나

    Karpenter vs Cluster Autoscaler를 비교할 때 단순히 “누가 더 빠르냐”만 보면 아쉽습니다. 운영에서는 아래 기준으로 보시는 걸 추천드립니다.

    검증 항목 확인 포인트
    확장 지연 시간 Pending 파드 발생 후 Running까지 걸리는 체감 시간
    리소스 적합도 워크로드 요구사항에 맞는 노드가 붙는지 여부
    운영 복잡도 노드 그룹/정책 관리 난이도, 변경 영향 범위
    비용 효율성 불필요한 큰 노드가 자주 붙는지, 축소가 잘 되는지
    장애 대응성 예외 상황에서 로그와 원인 파악이 쉬운지

    제가 여러 번 테스트하면서 느낀 결론은 이렇습니다.

    • 보수적이고 예측 가능한 운영이 중요하면 Cluster Autoscaler가 편합니다.
    • 유연한 워크로드 확장과 세밀한 자원 최적화가 중요하면 Karpenter가 매력적입니다.
    • 둘 다 잘 쓰려면 결국 파드 스펙, 요청 리소스, 스케줄링 제약조건을 먼저 정리해야 합니다.
    kubectl top pods -A
    kubectl top nodes
    kubectl get events --sort-by=.lastTimestamp
    kubectl describe node <node-name>

    이 명령어들만 잘 봐도 현재 Kubernetes 오토스케일링이 어디에서 막히는지 감이 꽤 옵니다. 대시보드만 보지 마시고 이벤트(event)와 describe 출력도 꼭 같이 보세요. 진짜 차이가 여기서 보이거든요.

    Karpenter vs Cluster Autoscaler 검증 결과를 보여주는 Kubernetes 대시보드 이미지

    노드 수 변화, 파드 Pending 해소, 리소스 사용률 등을 한눈에 보여주는 결과 검증용 대시보드 이미지 자리입니다.

    실무 선택 가이드: 그래서 무엇을 고르면 되냐

    질문을 많이 받는 부분이라 아주 현실적으로 정리해보겠습니다.

    1. 기존에 노드 그룹 체계가 잘 잡혀 있고 변경 리스크를 줄이고 싶다면 Cluster Autoscaler부터 가는 게 안전합니다.
    2. 새 클러스터를 설계하거나, 워크로드 종류가 다양하고 변동폭이 크다면 Karpenter를 적극 검토할 만합니다.
    3. 어떤 도구를 쓰든 HPA, requests/limits, affinity 정책을 먼저 정리하지 않으면 효과가 반감됩니다.
    4. 운영팀이 디버깅하기 쉬운 구조인지도 꼭 보셔야 합니다. 기술적으로 좋아 보여도 팀이 못 다루면 오래 못 갑니다.

    여기서 중요한 포인트! Karpenter vs Cluster Autoscaler의 승부는 기능표가 아니라 운영 방식에서 갈립니다. 홈랩에서 실험할 때도 그렇고 실제 서비스에서도 그렇고, 결국 오래 버티는 건 팀이 이해하고 통제할 수 있는 구조였습니다.

    정리와 FAQ

    정리하자면, Cluster Autoscaler는 익숙하고 보수적인 선택지입니다. Karpenter는 더 유연하고 워크로드 중심적인 선택지이고요. 어느 쪽이든 워크로드 확장의 핵심은 파드와 노드의 관계를 제대로 이해하는 데 있습니다. 저도 처음엔 단순히 “자동으로 늘려준다” 정도로 생각했었는데, 실제로 써보니까 오토스케일링은 설계의 문제더라고요.

    다음 글에서는 HPA와 VPA(Vertical Pod Autoscaler, 수직 오토스케일러)를 함께 붙였을 때 어떤 점을 조심해야 하는지 다뤄볼 예정입니다. 이전 글에서 다뤘던 Ingress(인그레스, 외부 트래픽 진입점)와 서비스 분리 구조를 같이 보시면 더 이해가 잘 되실 겁니다.

    자주 묻는 질문

    • Q. 둘을 동시에 써도 되나요?
      A. 환경과 목적에 따라 가능은 하지만, 노드 프로비저닝 책임이 겹치지 않도록 설계를 분명히 나누는 게 중요합니다.
    • Q. Kubernetes 오토스케일링에서 가장 먼저 봐야 할 건 뭔가요?
      A. 파드 requests/limits와 스케줄링 제약조건입니다. 여기서 꼬이면 어떤 오토스케일러를 써도 답답합니다.
    • Q. 초보 운영자에게는 뭐가 더 쉬운가요?
      A. 이미 노드 그룹 개념이 익숙하다면 Cluster Autoscaler가 더 이해하기 쉬운 편입니다. 다만 장기적으로는 Karpenter의 유연성이 매력적일 수 있습니다.
    Karpenter vs Cluster Autoscaler 핵심 차이를 요약한 비교 인포그래픽

    두 오토스케일러의 장단점, 추천 시나리오, 선택 기준을 한 장으로 정리한 마무리용 인포그래픽 자리입니다.

    ✅ 결론만 짧게 말하면 이렇습니다. 안정성과 익숙함이면 Cluster Autoscaler, 유연성과 최적화면 Karpenter입니다. 다만 둘 다 만능은 아니고, 결국 좋은 오토스케일링은 좋은 워크로드 설계에서 시작합니다. 이거 진짜 중요합니다.