13년차의 서버실

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

[태그:] 쿠버네티스 비용 최적화

  • [k8s] Karpenter 오토스케일로 EKS 비용 절감 검증하는 방법

    [k8s] Karpenter 오토스케일로 EKS 비용 절감 검증하는 방법

    Karpenter 오토스케일로 EKS 비용 절감 검증하는 방법

    Karpenter 오토스케일을 검토하시는 분들은 비슷한 지점에서 막히곤 합니다. HPA로 파드 수는 잘 늘고 줄어드는데, 월말 청구서를 보면 노드가 생각보다 오래 남아 있어서 클라우드 비용 절감 체감이 약하거든요. 특히 AWS EKS를 운영하다 보면 파드 오토스케일링과 노드 비용 최적화가 완전히 같은 문제가 아니라는 점을 금방 느끼게 됩니다.

    저도 초반에는 “HPA만 잘 잡으면 끝나는 거 아닌가?” 싶었는데, 실제로는 노드 단위 빈 공간이 더 큰 병목이었습니다. 이럴 때 Karpenter 오토스케일은 파드 요구사항에 맞춰 노드를 더 유연하게 만들고, 유휴 노드를 정리하는 데 강점이 있습니다. 이번 글에서는 Kubernetes 오토스케일링 관점에서 Karpenter가 왜 비용 최적화에 유리한지, 그리고 AWS EKS 비용 최적화 효과를 어떤 지표로 검증해야 하는지 정리해보겠습니다.

    Karpenter 오토스케일 기반 EKS 아키텍처 개요 이미지

    Karpenter가 스케줄링되지 못한 파드를 감지하고 적절한 EC2 노드를 만들고, 유휴 노드를 정리하는 흐름을 보여주는 이미지입니다.

    Karpenter 오토스케일이 비용 절감에 유리한 이유

    쉽게 말해 Karpenter는 파드가 실제로 필요로 하는 리소스에 맞춰 노드를 바로 만들어주는 도구입니다. 기존 Cluster Autoscaler도 노드 수를 늘리고 줄일 수 있지만, 보통 미리 정의한 노드 그룹을 중심으로 확장하다 보니 리소스가 남는 구간이 생기기 쉽습니다.

    반면 Karpenter는 Pending 상태의 파드를 보고 CPU, 메모리, 아키텍처, 용량 유형(온디맨드/스팟) 같은 조건에 맞는 인스턴스를 더 유연하게 고릅니다. 운영에서 보면 이 차이가 꽤 큽니다. 특정 인스턴스 몇 개만 반복해서 늘리는 대신, 워크로드 특성에 맞춰 c 계열, m 계열, r 계열을 섞고 스팟까지 활용하기 쉬워지거든요.

    항목 Cluster Autoscaler Karpenter
    확장 기준 기존 노드 그룹 중심 파드 요구사항 중심
    인스턴스 선택 유연성 상대적으로 제한적 높음
    빈 리소스 최소화 노드 그룹 크기에 영향 받음 상황별 최적화에 유리
    스팟 활용 구성 복잡도 있음 정책 설계가 비교적 직관적
    비용 절감 포인트 노드 수 축소 노드 크기와 종류까지 최적화

    핵심은 단순히 노드를 빨리 만드는 데 있지 않습니다. Karpenter 오토스케일의 진짜 장점은 불필요하게 큰 노드를 오래 붙잡고 있지 않게 만드는 구조에 있습니다. 결국 비용은 시간당 단가와 실행 시간의 곱이라서, 둘을 같이 줄여야 체감이 나더라고요.

    Karpenter 오토스케일 도입 전에 먼저 봐야 할 비용 지표

    Karpenter를 붙였는데도 “그래서 얼마가 절감됐지?”를 설명하지 못하면 운영팀 설득이 어렵습니다. 감으로 보면 꼭 해석이 꼬입니다. 최소한 아래 지표는 같은 기간 기준으로 같이 보는 편이 좋습니다.

    • 노드 평균 사용률: CPU와 메모리 요청량 대비 실제 사용률
    • 유휴 시간: 야간 또는 비업무 시간에 노드가 얼마나 오래 남는지
    • 파드 Pending 빈도: 확장 지연이 발생하는지
    • 인스턴스 타입 다양성: 특정 타입에 과도하게 묶여 있는지
    • 스팟 비중: 안정성과 비용 균형이 맞는지

    메트릭은 CloudWatch, Prometheus, Grafana 조합으로 많이 보고, 비용은 AWS Cost Explorer 또는 CUR로 맞춰보면 됩니다. 포인트는 하나입니다. 메트릭과 비용 데이터를 반드시 같은 기간으로 맞춰서 비교해야 한다는 점입니다.

    Kubernetes 오토스케일링 구성, 이렇게 잡으면 시작이 편합니다

    실전 구현 자체는 아주 복잡하지 않습니다. 다만 EKS 클러스터가 이미 있어야 하고, IRSA 또는 EKS Pod Identity 같은 AWS 권한 구성이 가능해야 합니다. 그리고 Karpenter가 파드 요청값을 기준으로 판단하므로 워크로드의 resources.requests가 비어 있으면 기대한 최적화가 잘 나오지 않습니다. 이 부분은 정말 중요합니다.

    1. EKS 클러스터 이름과 리전을 환경 변수로 설정합니다.
    2. Karpenter 컨트롤러용 IAM 역할과 중단 이벤트용 큐를 준비합니다.
    3. Helm으로 Karpenter를 설치합니다.
    4. NodePool과 EC2NodeClass를 정의합니다.
    5. 워크로드의 requests/limits를 다시 점검합니다.
    export CLUSTER_NAME=my-eks
    export AWS_DEFAULT_REGION=ap-northeast-2
    export KARPENTER_NAMESPACE=karpenter
    export KARPENTER_VERSION=1.14.0
    export KARPENTER_IAM_ROLE_ARN=arn:aws:iam::123456789012:role/KarpenterControllerRole
    
    aws eks update-kubeconfig --name $CLUSTER_NAME --region $AWS_DEFAULT_REGION
    kubectl config current-context
    kubectl get nodes
    

    클러스터 연결부터 먼저 확인해두세요. 여기서 컨텍스트가 꼬이면 다른 클러스터에 배포하는 사고가 의외로 자주 납니다. 한 번만 겪어도 이 단계가 왜 중요한지 바로 느껴지더라고요.

    Karpenter 설치 예시

    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 serviceAccount.annotations.eks\.amazonaws\.com/role-arn=$KARPENTER_IAM_ROLE_ARN \
      --wait
    
    kubectl -n $KARPENTER_NAMESPACE get pods
    

    설치가 끝나면 컨트롤러 파드가 정상 기동하는지 먼저 확인합니다. 여기서 CrashLoopBackOff가 보이면 IAM 권한, 서브넷 태그, 보안 그룹 태그, 이벤트 큐 설정부터 보는 게 빠릅니다.

    Karpenter 오토스케일 설정과 NodePool 연결 구조 이미지

    Karpenter 컨트롤러, NodePool, EC2NodeClass, 워크로드 파드가 어떻게 연결되는지 보여주는 구성 다이어그램입니다.

    NodePool과 EC2NodeClass 예시

    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/arch
              operator: In
              values: ["amd64"]
            - key: kubernetes.io/os
              operator: In
              values: ["linux"]
            - key: karpenter.sh/capacity-type
              operator: In
              values: ["spot", "on-demand"]
            - key: node.kubernetes.io/instance-type
              operator: In
              values: ["c6i.large", "m6i.large", "r6i.large"]
          expireAfter: 720h
      disruption:
        consolidationPolicy: WhenEmptyOrUnderutilized
        consolidateAfter: 5m
      limits:
        cpu: "200"
    ---
    apiVersion: karpenter.k8s.aws/v1
    kind: EC2NodeClass
    metadata:
      name: default
    spec:
      role: KarpenterNodeRole-my-eks
      amiSelectorTerms:
        - alias: al2023@latest
      subnetSelectorTerms:
        - tags:
            karpenter.sh/discovery: my-eks
      securityGroupSelectorTerms:
        - tags:
            karpenter.sh/discovery: my-eks
    

    여기서 핵심은 세 가지입니다. 첫째, NodePool에는 nodeClassRef가 필요합니다. 둘째, 최근 EKS 기준으로는 AL2보다 AL2023 계열 AMI 선택이 더 자연스럽습니다. 셋째, consolidation을 켜야 유휴 노드 정리가 제대로 일어납니다. 실제 비용 절감은 스케일 아웃보다 이 정리 단계에서 더 크게 체감되는 경우가 많습니다.

    테스트용 워크로드 배포

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

    이렇게 테스트하면 Pending 상태였던 파드 수요를 Karpenter가 보고 새 노드를 띄우는 흐름을 확인할 수 있습니다. 이후 replicas를 다시 줄이거나 배포를 삭제해보면 노드 통합 정리까지 관찰할 수 있습니다. 작은 워크로드부터 붙여보는 방식이 운영 리스크도 낮고 결과도 해석하기 편합니다.

    AWS EKS 비용 최적화를 위한 운영 포인트

    이 섹션은 꼭 짚고 넘어가야 합니다. Karpenter를 도입했다고 자동으로 클라우드 비용 절감이 되진 않습니다. 정책을 어떻게 잡느냐에 따라 결과가 꽤 다르게 나옵니다.

    • requests를 현실적으로 작성: 과장된 요청값은 큰 노드를 계속 부릅니다.
    • 스팟과 온디맨드 혼합: 서비스 성격에 따라 풀을 나누는 편이 안정적입니다.
    • 워크로드 분리: API 서버 계열과 배치 계열을 같은 NodePool에 몰지 않는 게 좋습니다.
    • 스케일 인 여유 시간 확인: 너무 공격적으로 줄이면 재기동이 잦아질 수 있습니다.
    • PodDisruptionBudget 검토: 축소가 막혀 노드가 안 내려가는 경우가 생각보다 많습니다.

    처음부터 모든 워크로드를 하나의 NodePool에 넣으면 정책 충돌이 생기기 쉽습니다. 최소한 안정성 우선 풀과 비용 우선 풀 정도는 분리해두면 운영이 훨씬 편합니다. 이거 진짜 편하더라고요.

    ⚠️ 실제로 많이 겪는 문제와 해결법

    문서만 보면 금방 될 것 같아도 운영 환경에서는 자잘한 함정이 많습니다. 특히 권한, 태그, 요청값 같은 기본 설정에서 많이 막힙니다.

    1. 노드가 아예 생성되지 않는 경우

    대부분은 IAM 또는 태그 문제입니다. 서브넷과 보안 그룹에 karpenter.sh/discovery 태그가 빠져 있으면 인프라 리소스를 찾지 못합니다.

    kubectl describe nodepool default
    kubectl -n karpenter logs deploy/karpenter
    

    로그에서 subnet, security group, instance profile, access denied 관련 메시지를 먼저 확인하면 원인이 빨리 보입니다.

    2. 노드는 생기는데 비용이 생각보다 안 줄어드는 경우

    이 경우도 자주 나옵니다. 원인은 대개 세 가지입니다.

    • 파드 requests가 과하게 큼
    • PodDisruptionBudget 때문에 빈 노드를 못 비움
    • 스팟 허용 범위가 너무 좁음

    Karpenter가 덜 똑똑해서가 아니라 입력값이 비효율적인 경우가 많습니다. 결국 스케줄러와 오토스케일러도 선언된 요청값을 기준으로 움직이니까요.

    3. 스팟 중단 대응이 불안한 경우

    스팟은 비용 면에서 매력적이지만 서비스 성격에 따라 조심해야 합니다. 중단 알림을 받았을 때 드레이닝과 재스케줄링이 자연스럽게 되도록 준비가 필요합니다. 중요한 서비스는 무조건 스팟으로 몰기보다 온디맨드와 섞는 편이 안전합니다.

    Karpenter 오토스케일 비용 절감 결과 대시보드 이미지

    파드 수 증가에 따라 노드가 늘고, 유휴 시간대에 통합 정리로 노드 수가 줄어드는 메트릭 대시보드 예시입니다.

    Karpenter 오토스케일 비용 절감 효과, 어떻게 검증해야 할까

    여기서 중요한 건 “노드 수가 줄었다”로 끝내지 않는 겁니다. 노드 수는 줄었는데 더 비싼 타입을 오래 썼다면 의미가 없거든요. 저는 아래 순서로 비교하면 결과 해석이 가장 깔끔했습니다.

    1. 도입 전 2주와 도입 후 2주를 비교합니다.
    2. 같은 요일, 같은 시간대 기준으로 워크로드 패턴을 맞춥니다.
    3. EC2 비용, 노드 평균 개수, 평균 vCPU 사용률을 함께 봅니다.
    4. 배포 실패, Pending 시간, 재스케줄링 지연이 늘지 않았는지 확인합니다.
    5. 스팟 비중 증가가 장애로 이어지지 않았는지 점검합니다.

    특히 비용 / 요청 처리량 같은 지표가 설명력이 좋습니다. 같은 트래픽을 처리하는데 필요한 EC2 비용이 줄었는지 보면, 단순 총액보다 훨씬 설득력이 있습니다. 팀 내 공유 문서에도 이 지표를 같이 적어두면 의사결정이 빨라집니다.

    kubectl top nodes
    kubectl top pods -A
    aws ce get-cost-and-usage \
      --time-period Start=2026-07-01,End=2026-07-15 \
      --granularity DAILY \
      --metrics UnblendedCost \
      --group-by Type=DIMENSION,Key=SERVICE
    

    위 명령은 비용 추세를 보는 기본 예시입니다. 참고로 Cost Explorer의 종료일은 보통 마지막 날짜 다음 날로 잡아야 비교가 깔끔합니다. 운영에서는 CUR를 Athena로 조회하거나 Grafana에 연결해 시계열로 보는 쪽이 더 편합니다.

    해석할 때 주의할 점

    • 도입 직후 며칠은 캐시, 배포 주기, 스팟 수급 영향으로 흔들릴 수 있습니다.
    • 트래픽 자체가 줄어서 비용이 감소한 것을 Karpenter 효과로 착각하면 안 됩니다.
    • RI나 Savings Plans 영향도 함께 봐야 합니다.

    결국 비교 기준은 같은 부하 조건이어야 합니다. 이 기준만 지켜도 해석 오류가 꽤 줄어듭니다.

    정리: 이런 환경이라면 Karpenter 도입 가치가 큽니다

    다음 조건에 해당하면 Karpenter 도입 효과가 비교적 잘 나옵니다.

    • 트래픽 변동폭이 크다
    • 워크로드 종류가 다양하다
    • EKS에서 인스턴스 타입 선택 폭을 넓게 가져갈 수 있다
    • 스팟 활용 여지가 있다
    • 현재 노드 유휴 시간이 길다

    반대로 워크로드가 매우 단순하고 부하가 거의 고정되어 있다면 체감 효과가 크지 않을 수도 있습니다. 그래서 무조건 도입부터 하기보다, 현재 비효율이 어디서 생기는지 먼저 확인하는 편이 맞습니다. 그다음 작은 서비스에 시범 적용하고 결과를 비교하면 훨씬 덜 위험합니다.

    Karpenter 오토스케일과 기존 오토스케일링 비교 인포그래픽

    노드 그룹 기반 확장과 파드 요구사항 기반 확장의 차이를 한눈에 요약한 비교 이미지입니다.

    마무리

    이번 글의 핵심은 간단합니다. Karpenter 오토스케일은 단순한 증설 도구라기보다, AWS EKS 비용 최적화를 운영 레벨에서 밀어주는 도구에 가깝습니다. 다만 효과는 설치 여부보다 requests 품질, NodePool 정책, 스팟 전략, 검증 방식에 더 크게 좌우됩니다.

    지금 EKS 비용이 애매하게 새고 있다고 느끼신다면, 전면 도입부터 하기보다 작은 워크로드에 먼저 붙여보세요. 그리고 이전 글의 HPA/VPA 튜닝 가이드도 함께 보시면 파드 스케일링과 노드 스케일링을 한 흐름으로 이해하는 데 도움이 됩니다. 다음 글에서는 스팟과 온디맨드 혼합 정책을 어떻게 설계해야 장애 없이 비용을 줄일 수 있는지 이어서 다뤄보겠습니다.

    자주 묻는 질문

    Karpenter만 도입하면 비용이 바로 줄어드나요?

    아닙니다. requests 값, NodePool 정책, 스팟 허용 범위가 같이 맞아야 의미 있는 절감이 나옵니다.

    Cluster Autoscaler를 꼭 버려야 하나요?

    꼭 그렇진 않습니다. 다만 인스턴스 선택 유연성과 운영 단순성이 중요하다면 Karpenter가 더 잘 맞는 환경이 많습니다.

    비용 절감 효과는 무엇으로 확인하나요?

    총 EC2 비용만 보지 말고, 같은 트래픽 대비 비용, 노드 평균 사용률, 유휴 시간, Pending 감소 여부를 함께 보시면 됩니다.

  • [K8s] 쿠버네티스 비용 최적화 5가지 핵심 전략 – 클라우드 비용 폭탄 방지

    쿠버네티스 비용 최적화 5가지 핵심 전략: 클라우드 비용 폭탄 방지 완벽 가이드

    안녕하세요, 13년차 인프라 엔지니어 ’13년차의 서버실’입니다. 클라우드 인프라를 운영하다 보면 정말 다양한 경험을 하게 되죠. 그중에서도 클라우드 비용만큼 심장을 철렁하게 만드는 것도 없을 겁니다. 특히 쿠버네티스(Kubernetes, K8s)를 도입하고 나서 ‘비용 폭탄’을 맞았다는 이야기를 참 많이 듣더라고요. 제가 직접 홈랩에서 다양한 기술을 실험하고 실제 프로덕션 환경에서 쿠버네티스를 운영하면서 겪었던 경험과 노하우를 바탕으로, 클라우드 비용을 효과적으로 최적화하는 5가지 핵심 전략을 오늘 아낌없이 풀어보려고 합니다.

    혹시 지금 여러분의 클라우드 청구서가 예상보다 많이 나왔거나, 쿠버네티스 비용 최적화에 어려움을 겪고 있다면 이 글이 분명 큰 도움이 될 거예요. 저도 처음엔 이게 뭔가 싶었는데, 하나하나 적용해보니 정말 확실한 차이가 나더라고요. 자, 그럼 함께 클라우드 비용 폭탄을 막으러 떠나볼까요?

    쿠버네티스 클라우드 비용 구조 개요 다이어그램

    클라우드 비용, 정말 폭탄 맞기 쉬워요

    사실 클라우드 환경에서는 리소스를 유연하게 쓸 수 있다는 게 큰 장점이에요. 근데 그만큼 자원 사용량을 예측하고 관리하기가 쉽지 않거든요. 특히 쿠버네티스는 컨테이너 오케스트레이션이라는 강력한 기능을 제공하지만, 그 복잡성 때문에 비용 최적화가 더 어렵게 느껴지기도 합니다. 파드(Pod)들이 알아서 스케일 업/다운되고, 워커 노드(Worker Node)들도 자동으로 늘었다 줄었다 하니, 대체 어디서 돈이 나가는지 파악하기가 여간 어려운 게 아니거든요. 저도 처음엔 그냥 잘 돌아가면 됐지 싶었는데, 월말에 청구서 보고 깜짝 놀란 적이 한두 번이 아니었습니다. 😅

    왜 쿠버네티스에서 비용 관리가 어려울까요?

    쿠버네티스는 다양한 추상화 계층(Abstraction Layer)을 가지고 있어서, 실제 물리적인 자원 사용량과 애플리케이션이 요구하는 자원량 사이의 괴리가 쉽게 발생합니다. 예를 들어, 파드에 필요한 CPU와 메모리를 정확히 예측하기 어렵고, 노드에 남는 자원이 있어도 파드가 스케줄링되지 않는 경우가 생기기도 하죠. 또한, 멀티 테넌시(Multi-tenancy) 환경에서는 여러 팀이 하나의 클러스터를 공유하기 때문에, 어떤 팀이 얼마나 비용을 소모하고 있는지 추적하기도 힘들어집니다. 이런 점들이 K8s 비용 절감을 어렵게 만드는 주된 이유입니다.

    쿠버네티스 비용 최적화 5가지 핵심 전략

    그럼 이제 제가 직접 해보고 효과를 본 5가지 핵심 전략을 소개해 드릴게요. 이 방법들을 잘 활용하면 클라우드 비용 관리의 새로운 지평을 열 수 있을 겁니다.

    1. 리소스 요청(Requests)과 제한(Limits) 정확히 설정하기

    이건 정말 기본 중의 기본이지만, 가장 많이 간과되기도 하는 부분입니다. 쿠버네티스에서 파드를 배포할 때, 각 컨테이너가 사용할 CPU와 메모리 양을 resources.requests와 resources.limits로 명시해줘야 합니다. Requests(요청)는 파드가 스케줄링될 때 필요한 최소 자원이고, Limits(제한)는 파드가 최대로 사용할 수 있는 자원량이에요.

    이 값을 너무 높게 설정하면 노드에 자원이 남아돌아도 다른 파드가 스케줄링되지 않아 불필요하게 노드를 증설하게 되고, 너무 낮게 설정하면 파드가 갑자기 죽거나 성능 저하가 발생해요. 제가 처음엔 그냥 대충 설정했었는데, 결국 자원이 부족해서 파드가 툭툭 죽는 바람에 며칠 밤낮을 고생했었죠. 😭

    애플리케이션의 실제 사용량을 모니터링해서 적절한 값을 찾아야 합니다. Prometheus(프로메테우스)나 Grafana(그라파나) 같은 툴로 사용량을 꾸준히 확인하면서 최적의 값을 찾아가는 과정이 정말 중요해요.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          containers:
          - name: my-container
            image: my-image:latest
            resources:
              requests:
                cpu: "200m"     # 0.2 CPU 코어 요청
                memory: "256Mi"  # 256 MiB 메모리 요청
              limits:
                cpu: "500m"     # 0.5 CPU 코어 제한
                memory: "512Mi"  # 512 MiB 메모리 제한
    

    여기서 200m은 0.2 CPU 코어, 256Mi는 256 메가바이트를 의미합니다. 애플리케이션의 특성을 잘 파악해서 이 값을 정교하게 설정하는 것이 쿠버네티스 비용 최적화의 첫걸음입니다.

    2. 효율적인 워커 노드(Worker Node) 관리하기 (클러스터 오토스케일링)

    쿠버네티스 클러스터에서 가장 큰 비용을 차지하는 부분은 바로 워커 노드입니다. 사용량이 적을 때는 노드를 줄이고, 많을 때는 늘려주는 클러스터 오토스케일러(Cluster Autoscaler)를 활용해야 합니다. 클라우드 제공업체(AWS, GCP, Azure 등)마다 자체적인 오토스케일링 기능을 제공하며, 쿠버네티스에서는 Cluster Autoscaler가 이를 연동하여 노드 수를 자동으로 조절해줍니다.

    이걸 적용하면 피크 타임에는 충분한 자원을 제공하고, 유휴 시간에는 불필요한 노드를 종료시켜 비용을 확실히 절감할 수 있습니다. 제가 처음엔 수동으로 노드를 늘렸다 줄였다 했는데, 이게 정말 비효율적이더라고요. Cluster Autoscaler를 도입하고 나서는 야간이나 주말에 노드 수가 자동으로 줄어드는 걸 보고 속으로 쾌재를 불렀습니다. 🎉

    3. 스팟 인스턴스(Spot Instances) 적극 활용하기

    클라우드 환경에서는 일반 온디맨드(On-demand) 인스턴스보다 훨씬 저렴하게 쓸 수 있는 스팟 인스턴스(Spot Instances)라는 게 있습니다. AWS의 Spot Instances, GCP의 Preemptible VMs, Azure의 Spot VMs 등이 여기에 해당하죠. 이 인스턴스들은 클라우드 제공업체의 여유 자원을 활용하는 방식이라 가격이 정말 저렴해요.

    물론, 클라우드 제공업체에 자원이 부족해지면 언제든지 회수될 수 있다는 단점이 있지만, Stateless(무상태)하고 Fault-tolerant(장애 허용)한 워크로드(예: 배치 처리, 개발/테스트 환경, 일부 백엔드 서비스)에는 정말 안성맞춤입니다. 저도 개발 환경이나 CI/CD 파이프라인에는 스팟 인스턴스를 적극적으로 활용해서 비용을 많이 아끼고 있어요. 중요한 건, 애플리케이션이 스팟 인스턴스가 회수되더라도 문제없이 동작하도록 잘 설계해야 한다는 점이에요.

    4. 비용 모니터링 및 분석 도구 활용하기 (Kubecost)

    눈에 보이지 않는 건 관리할 수 없습니다. 쿠버네티스 환경에서 비용을 정확하게 추적하고 분석하려면 전용 도구가 필수적이에요. 제가 여러 도구를 써봤지만, 그중에서도 Kubecost(쿠베코스트)는 정말 강력한 툴이더라고요. Kubecost는 클러스터 내의 리소스 사용량과 클라우드 제공업체의 비용 데이터를 연동하여, 파드, 디플로이먼트(Deployment), 네임스페이스(Namespace) 등 쿠버네티스 오브젝트(Object)별로 상세한 비용 분석 정보를 제공해줍니다.

    설치도 Helm(헬름) 차트(Chart)로 정말 간단하게 할 수 있어요.

    helm repo add kubecost https://kubecost.github.io/cost-analyzer/
    helm install kubecost kubecost/cost-analyzer --namespace kubecost --create-namespace
    

    이렇게 설치하고 나면 웹 UI에 접속해서 우리 클러스터에서 어떤 리소스가 얼마나 비용을 잡아먹고 있는지 한눈에 확인할 수 있습니다. 저도 Kubecost 덕분에 특정 네임스페이스에서 불필요하게 많은 리소스를 쓰고 있다는 걸 파악하고 바로 조치할 수 있었어요. FinOps(파인옵스) Kubernetes를 실현하는 데 핵심적인 도구라고 할 수 있습니다. 💡

    Kubecost 대시보드 예시: 쿠버네티스 비용 분석 화면

    5. 네임스페이스(Namespace) 및 라벨(Label) 기반 비용 할당

    클라우드 비용을 효과적으로 관리하려면, 누가 얼마나 쓰고 있는지 명확히 아는 것이 정말 중요합니다. 쿠버네티스에서는 네임스페이스(Namespace)와 라벨(Label)을 활용하여 비용을 할당하고 추적할 수 있어요. 예를 들어, 각 팀이나 프로젝트별로 별도의 네임스페이스를 사용하고, 모든 리소스에 team: frontend, project: my-service와 같은 라벨을 붙이는 거죠.

    이렇게 하면 Kubecost 같은 도구를 활용했을 때, 특정 팀이나 프로젝트가 사용하는 자원과 그에 따른 비용을 정확히 파악할 수 있습니다. 이는 FinOps(Financial Operations)의 핵심 원칙 중 하나인데, 개발팀이 자신의 서비스가 사용하는 클라우드 비용을 인지하고 책임감을 가지도록 유도할 수 있어요. 저도 처음엔 라벨링이 귀찮았는데, 나중에 비용 분석할 때 라벨이 잘 되어 있으면 정말 편하더라고요.

    ⚠️ 삽질 경험: 과도한 리소스 할당과 스팟 인스턴스 주의사항

    제가 겪었던 삽질 중 하나는 파드에 limits를 너무 낮게 설정해서 OOMKilled(Out Of Memory Killed)로 파드가 계속 죽어나갔던 경험입니다. 처음엔 왜 죽는지 몰라서 밤늦게까지 삽질하다가 겨우 limits 부족인 걸 알아냈죠. 너무 아끼려다가 오히려 서비스 장애를 유발한 셈이에요. 🤦‍♂️

    또 다른 삽질은 너무 많은 핵심 서비스를 스팟 인스턴스에 올렸다가 클라우드 제공업체의 자원 부족으로 인스턴스가 회수되면서 서비스가 일시적으로 마비되었던 경험입니다. 스팟 인스턴스는 분명 비용 절감에 효과적이지만, 안정성이 중요한 서비스에는 온디맨드 인스턴스를 쓰는 것이 현명합니다. 항상 워크로드의 특성을 고려해서 적절한 인스턴스 유형을 선택해야 해요. 이 경험을 통해 내결함성(Fault Tolerance) 설계의 중요성을 다시 한번 깨달았습니다.

    최적화 효과 확인하기

    이런 전략들을 적용하고 나면, 반드시 그 효과를 측정해야겠죠? 클라우드 제공업체의 비용 청구서를 정기적으로 확인하고, Kubecost 같은 도구에서 제공하는 월별 비용 보고서를 분석해보세요. 시간이 지남에 따라 비용이 어떻게 변화하는지 추이를 보는 것이 정말 중요합니다. 저희 팀도 최적화 전략 적용 후 약 3개월 만에 클라우드 비용을 20% 이상 절감하는 성과를 거두었습니다. ✅

    쿠버네티스 비용 최적화 후 월별 비용 절감 효과 그래프

    마무리하며: FinOps는 선택이 아닌 필수

    오늘 쿠버네티스 비용 최적화를 위한 5가지 핵심 전략에 대해 이야기해 봤습니다. 정리하자면, 리소스 요청/제한 정확히 설정하기, 클러스터 오토스케일링 활용하기, 스팟 인스턴스 적극 활용하기, Kubecost 같은 비용 모니터링 도구 사용하기, 그리고 네임스페이스/라벨 기반 비용 할당입니다.

    클라우드 환경, 특히 쿠버네티스 환경에서의 비용 관리는 더 이상 개발이나 운영팀만의 문제가 아닙니다. FinOps(파인옵스)는 재무(Finance)와 개발/운영(DevOps)의 결합으로, 클라우드 비용을 효율적으로 관리하고 최적화하기 위한 문화와 실천을 의미합니다. 클라우드 비용 관리는 이제 선택이 아니라 필수가 된 거죠.

    제가 알려드린 전략들을 적용해보면서 여러분만의 최적화 방법을 찾아나가시길 바랍니다. 처음엔 어렵고 복잡하게 느껴질 수 있지만, 꾸준히 노력하면 분명 좋은 결과를 얻을 수 있을 거예요. 다음번에는 Kubecost를 활용한 좀 더 심화된 분석 방법에 대해 다뤄볼까 합니다. 기대해주세요! 다음 글에서 만나요! 👋

    FinOps 쿠버네티스 비용 관리 워크플로우 인포그래픽