HPA를 사용하여 GKE 워크로드를 0으로 또는 0에서 확장

이 튜토리얼에서는 유휴 상태일 때 복제본이 0으로 자동 확장되고 수요가 증가하면 다시 확장되도록 워크로드를 구성하여 Google Kubernetes Engine (GKE)에서 리소스 사용률을 최적화하는 방법을 보여줍니다. 이 접근 방식은 수평형 포드 자동 확장 처리(HPA)를 GKE의 관리형 자동 확장 인프라와 통합하여 외부 측정항목을 기반으로 확장을 관리합니다.

minReplicas 필드 값을 0로 설정하고 HPA 매니페스트 내에서 External 또는 Object 유형으로 측정항목을 정의하여 0으로 확장되도록 배포를 구성합니다. GKE는 AutoscalingMetric 커스텀 리소스를 통해 이러한 측정항목을 모니터링하여 애플리케이션의 효율적인 리소스 관리를 지원합니다.

이 구성을 사용하면 KEDA와 같은 서드 파티 측정항목 어댑터를 사용하여 GKE 워크로드를 확장하지 않아도 됩니다. 이 솔루션은 GKE 컨트롤 플레인에서 직접 측정항목 수집 및 확장 권장사항을 관리하여 클러스터 관리 오버헤드를 줄입니다.

이 튜토리얼에서는 Pub/Sub 큐에서 메시지를 처리하는 비동기 작업자 애플리케이션을 배포합니다. AutoscalingMetric 커스텀 리소스를 사용하여 대기열 깊이 (pubsub.googleapis.com:num_undelivered_messages)를 모니터링하도록 수평형 포드 자동 확장 처리기를 구성합니다.

  • 메시지가 구독에 도착하는 경우: GKE는 큐를 처리하기 위해 작업자 포드를 확장합니다.
  • 큐가 비어 있는 경우: GKE는 작업자 배포를 복제본 0개로 자동 확장합니다.

이 튜토리얼은 워크로드가 유휴 상태일 때 0으로 확장하여 GKE에서 리소스 사용량을 최적화하려는 애플리케이션 개발자, 플랫폼 관리자 및 운영자, DevOps를 대상으로 합니다.

고려사항

워크로드가 0으로 확장되도록 구성하기 전에 다음 고려사항을 검토하세요.

  • HPA를 사용하여 워크로드를 0으로 확장하거나 0에서 확장하려면 신규 클러스터와 업그레이드된 기존 클러스터 모두에서 GKE 클러스터 컨트롤 플레인과 노드가 버전 1.37 이상을 실행해야 합니다. 기존 클러스터를 사용하는 경우 버전을 확인하거나 클러스터 또는 노드를 버전 1.37 이상으로 업그레이드합니다.
  • HPA 매니페스트는 minReplicas: 0 설정과 외부 측정항목을 지원하기 위해 apiVersion: autoscaling/v2 구성을 사용해야 합니다.
  • 1.37 이전 버전으로 노드 풀을 다운그레이드하기 전에 minReplicas 필드를 1 이상으로 설정하여 0으로 확장하거나 0에서 확장하도록 구성된 HPA 매니페스트를 업데이트하세요. 1.37 이전 버전에서는 minReplicas: 0 설정을 지원하지 않으므로 워크로드가 복제본 0개로 멈출 수 있습니다.
  • 수평형 포드 자동 확장 처리에서 하나 이상의 External 또는 Object 측정항목 (예: 대기열 깊이)을 구성해야 합니다. 워크로드에 포드가 0개인 경우 GKE는 CPU 또는 메모리 (Resource) 측정항목을 수집할 수 없으므로 리소스 측정항목만으로는 0에서 수직 확장을 트리거할 수 없습니다.
  • AutoscalingMetric, HorizontalPodAutoscaler, 대상 배포는 동일한 Kubernetes 네임스페이스에 있어야 합니다.

시작하기 전에

  1. Google Cloud CLI를 설치합니다.

  2. gcloud CLI에서 제휴 ID를 사용하도록 구성합니다.

    자세한 내용은 제휴 ID로 gcloud CLI에 로그인을 참고하세요.

  3. gcloud CLI를 초기화하려면, 다음 명령어를 실행합니다.

    gcloud init
  4. Google Cloud 프로젝트를 만들거나 선택합니다.

    프로젝트를 선택하거나 만드는 데 필요한 역할

    • 프로젝트 선택: 프로젝트를 선택하는 데는 특정 IAM 역할이 필요하지 않습니다. 역할이 부여된 프로젝트를 선택하면 됩니다.
    • 프로젝트 만들기: 프로젝트를 만들려면 resourcemanager.projects.create 권한이 포함된 프로젝트 생성자 역할(roles/resourcemanager.projectCreator)이 필요합니다. 역할 부여 방법 알아보기
    • Google Cloud 프로젝트를 만듭니다.

      gcloud projects create PROJECT_ID

      PROJECT_ID를 만들려는 Google Cloud 프로젝트의 이름으로 바꿉니다.

    • 만든 Google Cloud 프로젝트를 선택합니다.

      gcloud config set project PROJECT_ID

      PROJECT_ID을 Google Cloud 프로젝트 이름으로 바꿉니다.

  5. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  6. GKE 및 Pub/Sub API를 사용 설정합니다.

    API 사용 설정에 필요한 역할

    API를 사용 설정하려면 serviceusage.services.enable 권한이 필요합니다. 프로젝트를 만든 경우 소유자 역할 (roles/owner)을 통해 이 권한이 이미 있을 수 있습니다. 그렇지 않으면 서비스 사용량 관리자 역할 (roles/serviceusage.serviceUsageAdmin)을 통해 이 권한을 얻을 수 있습니다. 역할을 부여하는 방법 알아보기

    gcloud services enable container.googleapis.com pubsub.googleapis.com

필요한 역할

튜토리얼을 완료하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 다음 IAM 역할을 부여해 달라고 요청하세요.

역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.

커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.

환경 설정

간단하게 하기 위해 이 튜토리얼의 명령어는 단일 Google Cloud 프로젝트 (PROJECT_ID) 내에서 모든 리소스(GKE 클러스터, Pub/Sub 주제 및 구독)를 만듭니다.

환경을 설정하려면 다음 단계를 수행합니다.

  1. 환경 변수를 설정합니다.

    export PROJECT_ID=PROJECT_ID
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
    export LOCATION=LOCATION
    

    다음을 바꿉니다.

    • PROJECT_ID: Google Cloud프로젝트 ID
    • LOCATION: GKE 클러스터를 만들 리전 또는 영역입니다(예: us-central1). Autopilot 클러스터의 경우 리전을 지정합니다.
  2. 버전 1.37 이상을 실행하고 GKE용 워크로드 아이덴티티 제휴가 사용 설정된 GKE 클러스터를 만듭니다. 완전 관리형 Kubernetes 환경을 위해서는 Autopilot 클러스터를 사용하는 것이 좋으며, 워크로드가 0으로 확장될 때 비용 절감을 극대화할 수 있습니다. 워크로드에 가장 적합한 작업 모드를 선택하려면 GKE 작업 모드 선택을 참고하세요.

    Autopilot

    Autopilot 클러스터를 만듭니다.

    gcloud container clusters create-auto scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

    GKE용 워크로드 아이덴티티 제휴는 기본적으로 Autopilot 클러스터에서 사용 설정됩니다.

    표준

    GKE용 워크로드 아이덴티티 제휴가 사용 설정된 Standard 클러스터를 만듭니다.

    gcloud container clusters create scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION} \
        --workload-pool=${PROJECT_ID}.
    
  3. 클러스터와 통신하도록 kubectl을 구성합니다.

    gcloud container clusters get-credentials scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

Pub/Sub 리소스 만들기

이 튜토리얼에서는 Pub/Sub 큐 깊이를 외부 측정항목 소스의 예로 사용합니다.

Pub/Sub 주제 및 구독을 만들려면 다음 단계를 따르세요.

  1. Pub/Sub 주제를 만듭니다.

    gcloud pubsub topics create my-worker-topic \
        --project=${PROJECT_ID}
    
  2. 주제에 연결된 구독을 만듭니다.

    gcloud pubsub subscriptions create my-worker-subscription \
        --topic=my-worker-topic \
        --project=${PROJECT_ID}
    

GKE용 워크로드 아이덴티티 제휴 설정

작업자 애플리케이션이 Google Cloud API로 인증하고 Pub/Sub에서 메시지를 사용할 수 있도록 GKE용 워크로드 아이덴티티 제휴를 구성합니다.

GKE는 동일한 프로젝트의 AutoscalingMetric 리소스에 대한 Cloud Monitoring과의 인증을 자동으로 처리합니다. 자동 확장을 위한 측정항목 정의에 대해 자세히 알아보려면 Cloud Monitoring에서 커스텀 또는 외부 측정항목 가져오기를 참고하세요.

작업자 워크로드에 GKE용 워크로드 아이덴티티 제휴를 구성하려면 다음 단계를 따르세요.

  1. default 네임스페이스에서 작업자 애플리케이션의 Kubernetes 서비스 계정을 만듭니다.

    kubectl create serviceaccount async-worker-sa \
        --namespace default
    
  2. 애플리케이션이 Pub/Sub 구독에서 메시지를 수신할 수 있도록 Kubernetes 서비스 계정에 roles/pubsub.subscriber 역할을 부여합니다.

    gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
        --role=roles/pubsub.subscriber \
        --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}./subject/ns/default/sa/async-worker-sa
    

자세한 내용은 GKE용 워크로드 아이덴티티 제휴를 사용하도록 애플리케이션 구성을 참고하세요.

배포 예시 만들기

HPA 객체를 만들려면 먼저 모니터링할 워크로드를 만들어야 합니다.

예시 배포를 만들려면 다음 단계를 따르세요.

  1. 다음 매니페스트를 async-worker.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: async-worker
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: async-worker
      template:
        metadata:
          labels:
            app: async-worker
        spec:
          containers:
          - name: async-worker
            image: nginx:latest
            ports:
            - containerPort: 80
            resources:
              limits:
                memory: 100Mi
              requests:
                cpu: 50m
                memory: 100Mi
    
  2. async-worker.yaml 배포를 적용합니다.

    kubectl apply -f async-worker.yaml
    

0으로 확장 및 축소되도록 워크로드 구성

이 섹션에서는 Pub/Sub 대기열이 비어 있을 때 0으로 축소하고 새 메시지가 도착하면 다시 확장하도록 async-worker 배포를 구성합니다.

AutoscalingMetric 리소스 만들기

GKE에서 모니터링하는 외부 신호를 정의하려면 AutoscalingMetric 커스텀 리소스를 만드세요. 다음 예시 매니페스트에서 측정항목은 my-worker-subscription 구독에서 전달되지 않은 Pub/Sub 메시지 수를 Cloud Monitoring에 쿼리합니다.

AutoscalingMetric 리소스를 만들려면 다음 단계를 따르세요.

  1. 다음 매니페스트를 pubsub-metric.yaml 파일로 저장합니다.

    apiVersion: autoscaling.gke.io/v1beta1
    kind: AutoscalingMetric
    metadata:
      name: pubsub-queue-depth
      namespace: default
    spec:
      metrics:
      - promql:
          name: pubsub-undelivered
          query: >
              {
                "pubsub.googleapis.com/subscription/num_undelivered_messages",
                subscription_id="my-worker-subscription"
              }
    
  2. pubsub-metric.yaml 매니페스트를 적용합니다.

    kubectl apply -f pubsub-metric.yaml
    
  3. 측정항목 상태를 확인하고 측정항목 식별자를 가져옵니다.

    kubectl describe autoscalingmetric pubsub-queue-depth
    

    출력의 Status 섹션에서 오류가 나열되지 않았는지 확인하고 autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME 형식의 Hpa Name 값을 기록해 둡니다. 다음 섹션에서 HorizontalPodAutoscaler 객체를 만들 때 이 외부 측정항목 식별자를 참조합니다. Status 섹션에 구성 오류가 보고되거나 측정항목이 예상대로 가져오지 않으면 자동 확장용으로 가져온 측정항목 문제 해결을 참고하세요.

수평형 포드 자동 확장 처리 구성

자동 확장 동작을 구성하려면 배포를 타겟팅하는 HorizontalPodAutoscaler 리소스를 만듭니다.

수평형 포드 자동 확장 처리기를 구성하려면 다음 단계를 따르세요.

  1. 다음 매니페스트를 worker-hpa.yaml 파일로 저장합니다.

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: async-worker-hpa
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: async-worker
      minReplicas: 0
      maxReplicas: 20
      metrics:
      - type: External
        external:
          metric:
            name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered
          target:
            type: AverageValue
            averageValue: "10"
    

    이 매니페스트는 다음 주요 필드를 구성합니다.

    • minReplicas: 0: 수요가 0으로 떨어지면 컨트롤러가 배포를 0 복제본으로 축소할 수 있도록 하여 scale-to-zero를 사용 설정합니다.
    • type: External: 워크로드에 포드가 0개일 때 HPA가 스케일 업을 트리거할 수 있도록 외부 측정항목 소스를 구성합니다.
    • name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered: autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME 식별자 형식을 사용하여 HPA를 이전 단계에서 생성된 AutoscalingMetric 리소스에 직접 매핑합니다.
  2. worker-hpa.yaml 매니페스트를 적용합니다.

    kubectl apply -f worker-hpa.yaml
    

제로 스케일 동작 및 조건 확인

Pub/Sub 구독의 모든 메시지가 처리되면 수평형 포드 자동 확장 처리기가 수요가 0임을 평가하고 배포를 0 복제본으로 축소합니다.

수평형 포드 자동 확장 처리기가 0 상태를 작동시켰는지 확인하려면 다음 명령어를 실행하여 async-worker-hpa 리소스의 상태 조건을 검사합니다.

kubectl describe hpa async-worker-hpa

출력은 다음과 비슷합니다.

Name:             async-worker-hpa
Namespace:        default
Reference:        Deployment/async-worker
Metrics:          ( current / target )
  "autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered" (external metric):  0 / 10
Min replicas:     0
Max replicas:     20
Deployment pods:  0 current / 0 desired
Conditions:
  Type            Status  Reason               Message
  ----            ------  ------               -------
  AbleToScale     True    SucceededGetScale    the HPA controller was able to get the target's current scale
  ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from external metric
  ScaledToZero    True    ScaledToZero         the HPA has scaled the target resource to 0 replicas due to zero metric demand

ScaledToZero 조건 이해하기

ScaledToZero 조건은 수평형 포드 자동 확장 처리에서 워크로드를 0개의 복제본으로 확장했는지 여부를 나타냅니다.

  • ScaledToZero: True (Reason: ScaledToZero): 외부 측정항목 수요가 0으로 떨어졌기 때문에 HPA 컨트롤러가 워크로드를 0 복제본으로 성공적으로 확장했음을 나타냅니다. HPA는 활성 상태(ScalingActive: True)를 유지하고 워크로드 수요가 증가하는 시점을 감지하기 위해 GKE를 지속적으로 폴링합니다.
  • ScaledToZero: False: 워크로드가 하나 이상의 복제본으로 확장되었음을 나타냅니다.

예를 들어 kubectl scale --replicas=0 명령어를 사용하여 배포를 복제본 0개로 수동으로 확장하면 HPA는 충돌하는 변경사항을 방지하기 위해 자동 확장 (ScalingActive: False)을 일시중지합니다. 자동 확장을 재개하려면 배포를 하나 이상의 복제본 (kubectl scale deployment async-worker --replicas=1)으로 다시 확장합니다.

워크로드가 0으로 확장되지 않거나 0에서 확장되지 않는 문제 해결 시나리오는 HPA를 사용하여 GKE 워크로드를 0으로 확장 및 0에서 확장 문제 해결을 참고하세요. 수평형 포드 자동 확장 처리에서 누락되거나 유효하지 않은 외부 측정항목을 보고하는 경우 자동 확장을 위해 가져온 측정항목 문제 해결을 참고하세요.

삭제

이 튜토리얼에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 단계를 따르세요.

  1. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    
  2. Pub/Sub 구독 및 주제를 삭제합니다.

    gcloud pubsub subscriptions delete my-worker-subscription \
        --project=${PROJECT_ID}
    gcloud pubsub topics delete my-worker-topic \
        --project=${PROJECT_ID}
    

다음 단계