Scaling Application

Update : 2025.01.30

1. 애플리케이션 확장 (Scaling Application)

Karpenter는 스케일링이 필요한 unscheduled pods를 감지하여 자동으로 노드를 확장하는 기능을 제공합니다. Kubernetes에서 새로운 Pod이 생성되면, Kubernetes 스케줄러는 해당 Pod을 클러스터 내 노드에 배치합니다. 하지만 적절한 노드가 없을 경우, 해당 Pod은 Pending 상태로 남아있게 됩니다. Karpenter는 이러한 Pending 상태의 Pod을 감지하고, 요구 사항을 충족하는 새로운 노드를 프로비저닝하여 클러스터를 자동으로 확장합니다. 이 실습에서는 Karpenter가 애플리케이션 Pod을 스케일링할 때 새로운 노드를 생성하는 과정을 실습해 보겠습니다.


1.1 애플리케이션 배포 (Deploy Application)

① 애플리케이션 배포 (0개의 Replica)

먼저, Replica 수가 0인 상태에서 애플리케이션을 배포합니다. 아래 Deployment 스펙을 확인하면 다음과 같은 설정이 포함되어 있습니다.

  • 컨테이너의 CPU 요청 값이 1로 설정됨

  • NodePool을 생성할 때 추가한 "eks-team: my-team" 레이블을 nodeSelector에 추가 → 이렇게 설정하면, 생성된 Pod이 항상 Karpenter NodePool에서 생성한 노드에 할당됩니다.

아래 명령어를 실행하여 애플리케이션을 배포합니다.

# Karpenter 관련 작업 디렉토리로 이동
cd ~/environment/karpenter
kubectl create namespace karpenter-test

# basic-deploy.yaml 파일을 생성
cat <<EoF> ~/environment/karpenter/basic-deploy.yaml
apiVersion: apps/v1  # API 버전 (Kubernetes에서 사용되는 앱 관련 리소스 정의)
kind: Deployment  # 배포(Deployment) 리소스 정의
metadata:
  name: inflate  # Deployment 이름 지정
  namespace: karpenter-test  # Deployment가 배포될 네임스페이스 지정
spec:
  replicas: 0  # 초기 Pod 개수를 0으로 설정 (추후 스케일링할 예정)
  selector:
    matchLabels:
      app: inflate  # 이 Deployment가 관리할 Pod의 label 지정
  template:  # Pod 템플릿 정의
    metadata:
      labels:
        app: inflate  # Pod에 부여될 label (Deployment의 selector와 일치해야 함)
    spec:
      terminationGracePeriodSeconds: 0  # Pod 종료 대기 시간을 0으로 설정 (즉시 종료)
      containers:
        - name: inflate  # 컨테이너 이름
          image: public.ecr.aws/eks-distro/kubernetes/pause:3.7  # 컨테이너 이미지 지정 (pause 컨테이너 사용)
          resources:
            requests:
              cpu: 1  # 이 컨테이너가 요청하는 CPU 리소스 (1 vCPU)
      nodeSelector:
        eks-team: my-team  # 특정 노드 그룹(eks-team: my-team)에서만 실행되도록 지정
EoF

# 위에서 생성한 Deployment를 Kubernetes 클러스터에 적용
kubectl apply -f ~/environment/karpenter/basic-deploy.yaml

실행 결과

② 현재 클러스터의 노드 확인

현재 EKS 클러스터에 존재하는 노드를 확인하기 위해 새로운 터미널을 열어 eks-node-viewer를 실행합니다. 아래 명령어를 실행하여 현재 클러스터에 몇 개의 노드가 있는지 확인합니다.

앞서 생성한 eks-node-viewer, kube-ops-view, k9s 등을 활용합니다.


1.2 애플리케이션 확장 (Scale Application)

① Deployment 스케일링 (0 → 5 Replicas)

이제 Deployment를 5개의 Replica로 확장합니다.

실행 결과

② Karpenter 로그 확인

이제 Karpenter가 새로운 노드를 프로비저닝하는지 확인하기 위해 로그를 조회합니다. 아래 명령어를 실행하여 karpenter controller Pod의 로그에서 launched nodeclaim 메시지를 확인합니다.

로그 예시 (출력 결과)


③ 새로운 노드 생성 확인

eks-node-viewer를 실행 중인 터미널을 보면, 5세대 이상의 c6a.2xlarge 인스턴스 타입의 새로운 노드가 생성된 것을 확인할 수 있습니다. 또한 아래 명령어를 실행하여 Karpenter NodePool에서 관리하는 노드 목록을 조회할 수 있습니다.

출력 예시

이제 Karpenter가 새롭게 프로비저닝한 노드가 추가되었음을 확인할 수 있습니다.

④ 새롭게 추가된 노드에 Pod이 배치됨 확인

아래 k9s 또는 kubectl을 사용하여 새롭게 생성된 노드에 몇 개의 Pod이 배치되었는지 확인할 수 있습니다.

새롭게 생성된 노드에는 5개의 Pod이 배치된 것을 확인할 수 있습니다.

⑤ Karpenter가 생성한 노드의 메타데이터 확인

아래 명령어를 실행하여 Karpenter가 생성한 노드에 추가된 메타데이터(레이블)를 조회할 수 있습니다.

출력 예시

1.4 Node 축출

생성된 Pod를 replica를 0으로 축소합니다.

① Node 축출 확인

위의 로그를 통해 Karpenter에 의해 생성된 Node가 축출 되었는지 확인합니다. 아래는 예시입니다.

② 왜 노드는 삭제 되었는가?

아래에서 처럼 Node 삭제 만료기간이 "Never" 이므로 삭제 되지 않도록 설정되어 있습니다.

하지만 consolidationPolicy가 설정되어 있습니다.

📌 현재 설정

  • consolidationPolicy: WhenEmptyOrUnderutilized노드가 비어있거나 활용률이 낮으면 자동 축소

  • consolidateAfter: 30s30초 후 즉시 축소

📌 동작 방식

  1. Pod이 제거됨 → 해당 노드에 실행 중인 Pod이 없거나, 활용률이 낮아짐.

  2. Karpenter가 자동 축소 실행 (consolidationPolicy: WhenEmptyOrUnderutilized)

  3. 30초 후 노드 삭제됨 (consolidateAfter: 30s)

  4. 로그에서 확인되는 이벤트

    • disrupting nodeclaim(s) via delete → Karpenter가 노드 삭제 결정

    • deleted node → 노드 삭제 완료

    • deleted nodeclaim → NodeClaim 삭제 완료

🚀 즉, consolidationPolicy가 활성화되어 있기 때문에, Pod이 없어지면 자동으로 노드를 삭제하는 것입니다.

③ 노드 축출 방법은 아래에서 처럼 Karpenter 에서 활용 가능합니다.

방법
설정 변경

자동 축출 (expireAfter)

expireAfter: 30s (30초 후 자동 제거)

비활성 노드 자동 제거 (consolidation)

consolidation: enabled: true

즉시 특정 노드 제거

kubectl delete node <NODE_NAME>

Pod이 없는 노드 자동 삭제 (ttlSecondsAfterEmpty)

ttlSecondsAfterEmpty: 60 (비어있으면 60초 후 제거)

위 설정을 적용하면 Karpenter가 더 빠르게 노드를 축출할 수 있습니다. 🚀


1.5 정리

이번 실습을 통해 Karpenter가 Pending 상태의 Pod을 감지하여 새로운 노드를 자동으로 생성하는 과정을 확인하였습니다. 이를 통해 Karpenter를 활용한 Kubernetes 클러스터의 자동 확장 기능을 효과적으로 운영할 수 있습니다. 🚀

Last updated

Was this helpful?