빠른 포드 확장을 위한 추가 컴퓨팅 용량 프로비저닝


이 페이지에서는 트래픽이 많은 이벤트 중에 새 노드가 시작될 때까지 기다리지 않고 워크로드가 빠르게 확장할 수 있도록 Google Kubernetes Engine(GKE) 클러스터에서 추가 컴퓨팅 용량을 예약하는 방법을 설명합니다. 이 안내를 따라 일관된 사용 기준에 따라서나 특정 이벤트에 앞서 컴퓨팅 오버헤드를 예약할 수 있습니다.

예비 용량 프로비저닝이 유용한 이유

GKE Autopilot 클러스터와 노드 자동 프로비저닝이 포함된 표준 클러스터는 기존 노드에 새 포드를 실행할 용량이 없으면 새 노드를 만듭니다. 각 새 노드를 부팅하는 데 약 80~120초가 걸립니다. GKE는 노드가 시작될 때까지 기다린 후 새 노드에 대기 중인 포드를 배치하며, 포드는 그 다음에 부팅될 수 있습니다. 또는 표준 클러스터에서 새 포드를 실행하는 데 필요한 추가 용량이 있는 새 노드 풀을 수동으로 만들 수 있습니다. 이 페이지는 Autopilot 또는 노드 자동 프로비저닝과 같은 노드 자동 확장 메커니즘을 사용하는 클러스터에 적용됩니다.

경우에 따라 확장 이벤트 중에 포드가 더 빠르게 부팅되도록 할 수 있습니다. 예를 들어 인기 있는 라이브 서비스 멀티플레이어 게임의 새로운 확장을 출시하는 경우, 게임 서버 포드의 부팅 시간이 빨라지면 출시일에 로그인하는 플레이어의 큐 타임이 단축될 수 있습니다. 또 다른 예로 전자상거래 플랫폼을 운영하는데 한시적으로 반짝 세일을 계획하는 경우 판매 기간 동안 트래픽 버스트가 발생할 수 있습니다.

예비 용량 프로비저닝은 포드 버스팅과 호환되므로 다른 포드에서 해당 용량을 사용할 수 있고 아직 사용되지 않는 경우 포드에서 해당 노드의 다른 포드에서 요청한 리소스를 일시적으로 사용할 수 있습니다. 버스팅을 사용하려면 리소스 한도를 리소스 요청보다 높게 설정하거나 리소스 한도를 설정하지 않습니다. 자세한 내용은 GKE에서 포드 버스팅 구성을 참조하세요.

GKE에서 예비 용량 프로비저닝 작동 방식

예비 용량을 프로비저닝하려면 Kubernetes PriorityClasses 및 자리표시자 포드를 사용하면 됩니다. PriorityClass를 사용하면 일부 워크로드가 다른 워크로드보다 우선순위가 낮다는 것을 GKE에 알릴 수 있습니다. 낮은 PriorityClass를 사용하는 자리표시자 포드를 배포하고 예약해야 하는 컴퓨팅 용량을 요청할 수 있습니다. GKE는 자리표시자 포드를 수용하기 위해 새 노드를 만들어 클러스터에 용량을 추가합니다.

프로덕션 워크로드가 확장되면 GKE는 우선순위가 낮은 자리표시자 포드를 삭제하고 그 자리에 프로덕션 포드(더 높은 우선순위 PriorityClass 사용)의 새 복제본을 예약합니다. 우선순위 수준이 다른 낮은 우선순위의 포드가 여러 개 있는 경우 GKE는 우선순위가 가장 낮은 포드를 먼저 제거합니다.

용량 프로비저닝 방법

사용 사례에 따라 다음 방법 중 하나로 GKE 클러스터에 추가 용량을 프로비저닝할 수 있습니다.

  • 일관된 용량 프로비저닝: 배포를 사용하여 클러스터에서 지속적으로 실행되는 우선순위가 낮은 특정 수의 자리표시자 포드를 만듭니다. GKE가 프로덕션 워크로드를 실행하기 위해 이러한 포드를 제거할 때, 배포 컨트롤러는 GKE가 우선 순위가 낮은 제거된 포드를 다시 생성할 수 있도록 더 많은 용량을 프로비저닝하도록 보장합니다. 이 방법은 배포를 삭제할 때까지 여러 확장 및 축소 이벤트 간에 일관된 용량 오버헤드를 제공합니다.
  • 단일 사용 용량 프로비저닝: 작업을 사용하여 특정 기간 동안 우선순위가 낮은 특정 개수의 병렬 자리표시자 포드를 실행합니다. 이 시간이 경과하거나 GKE가 모든 작업 복제본을 제거하면 예약된 용량을 사용할 수 없게 됩니다. 이 메서드는 특정 기간 동안 사용 가능한 특정 용량을 제공합니다.

가격 책정

GKE Autopilot에서는 배포하는 우선순위가 낮은 워크로드를 포함하여 실행 중인 포드의 리소스 요청에 대한 요금이 부과됩니다. 자세한 내용은 Autopilot 가격 책정을 참조하세요.

GKE Standard에서는 포드가 해당 용량을 사용하는지 여부에 관계없이 GKE가 프로비저닝하는 기본 Compute Engine VM에 대한 요금이 부과됩니다. 자세한 내용은 Standard 가격 책정을 참조하세요.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update를 실행하여 최신 버전을 가져옵니다.
  • GKE Autopilot 클러스터 또는 노드 자동 프로비저닝이 사용 설정된 GKE Standard 클러스터가 있는지 확인합니다.
  • 용량 프로비저닝에 적합한 값을 선택할 수 있도록 용량 프로비저닝의 고려사항을 읽어보세요.

PriorityClass 만들기

용량 프로비저닝 메서드에 설명된 방법 중 하나를 사용하려면 먼저 다음 PriorityClass를 만들어야 합니다.

  • 기본 PriorityClass: 포드 사양에서 다른 PriorityClass를 명시적으로 설정하지 않는 모든 포드에 할당된 전역 기본 PriorityClass입니다. 이 기본 PriorityClass가 있는 포드는 더 낮은 PriorityClass를 사용하는 포드를 제거할 수 있습니다.
  • Low PriorityClass: GKE에서 가능한 가장 낮은 우선순위로 설정된 기본이 아닌 PriorityClass입니다. 이 PriorityClass가 있는 포드는 PriorityClass가 더 높은 포드를 실행하도록 제거될 수 있습니다.
  1. 다음 매니페스트를 priorityclasses.yaml로 저장합니다.

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: low-priority
    value: -10
    preemptionPolicy: Never
    globalDefault: false
    description: "Low priority workloads"
    ---
    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: default-priority
    value: 0
    preemptionPolicy: PreemptLowerPriority
    globalDefault: true
    description: "The global default priority."
    

    이 매니페스트에는 다음 필드가 포함됩니다.

    • preemptionPolicy: PriorityClass를 사용하는 포드가 우선순위가 낮은 포드를 제거할 수 있는지 여부를 지정합니다. low-priority PriorityClass는 Never를 사용하고 default PriorityClass는 PreemptLowerPriority를 사용합니다.
    • value: PriorityClass를 사용하는 포드의 우선순위입니다. defaultPriorityClass는 0를 사용합니다. low-priority PriorityClass는 -1를 사용합니다. Autopilot에서 default PriorityClass 우선순위보다 작은 값으로 설정할 수 있습니다.

      Standard에서 이 값을 -10 미만으로 설정하면 PriorityClass를 사용하는 포드가 새 노드 생성을 트리거하지 않고 대기 상태로 유지됩니다.

      우선순위에 적합한 값을 결정하는 데 도움이 필요하면 우선순위 선택을 참조하세요.

    • globalDefault: GKE 사양에서 포드가 PriorityClass를 명시적으로 설정하지 않는 포드에 PriorityClass를 할당할지 여부를 지정합니다. low-priority PriorityClass는 false를 사용하고 default PriorityClass는 true를 사용합니다.

  2. 매니페스트 적용

    kubectl apply -f priorityclasses.yaml
    

추가 컴퓨팅 용량 프로비저닝

다음 섹션에서는 단일 이벤트에 대한 용량 또는 시간 경과에 따라 일관적으로 용량을 프로비저닝하는 예시를 보여줍니다.

일관된 용량 프로비저닝에 배포 사용

  1. 다음 매니페스트를 capacity-res-deployment.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: capacity-res-deploy
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: reservation
      template:
        metadata:
          labels:
            app: reservation
        spec:
          priorityClassName: low-priority
          terminationGracePeriodSeconds: 0
          containers:
          - name: ubuntu
            image: ubuntu
            command: ["sleep"]
            args: ["infinity"]
            resources:
              requests:
                cpu: 500m
                memory: 500Mi
    

    이 매니페스트에는 다음 필드가 포함됩니다.

    • spec.replicas: 요구사항에 맞게 이 값을 변경합니다.
    • spec.resources.requests: 요구사항을 충족하도록 CPU 및 메모리 요청을 변경합니다. 용량 크기 선택의 안내에 따라 적절한 요청 값을 결정합니다.
    • spec.containers.commandspec.containers.args: GKE에서 제거할 때까지 활성 상태로 유지하도록 포드에 지시합니다.
  2. 매니페스트 적용

    kubectl apply -f capacity-res-deployment.yaml
    
  3. 포드 상태를 가져옵니다.

    kubectl get pods -l app=reservation
    

    모든 복제본의 상태가 Running가 될 때까지 기다립니다.

단일 이벤트 용량 프로비저닝에 작업 사용

  1. 다음 매니페스트를 capacity-res-job.yaml로 저장합니다.

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: capacity-res-job
    spec:
      parallelism: 4
      backoffLimit: 0
      template:
        spec:
          priorityClassName: low-priority
          terminationGracePeriodSeconds: 0
          containers:
          - name: ubuntu-container
            image: ubuntu
            command: ["sleep"]
            args: ["36000"]
            resources:
              requests:
                cpu: "16"
          restartPolicy: Never
    

    이 매니페스트에는 다음 필드가 포함됩니다.

    • spec.parallelism: 용량을 예약하기 위해 동시에 실행할 작업 수로 변경합니다.
    • spec.backoffLimit: 0: 작업 컨트롤러가 삭제된 작업을 다시 만들지 못하게 합니다.
    • template.spec.resources.requests: 요구사항을 충족하도록 CPU 및 메모리 요청을 변경합니다. 고려사항의 안내에 따라 적절한 값을 결정합니다.
    • template.spec.containers.commandtemplate.spec.containers.args: 작업에 추가 용량이 필요한 기간(초) 동안 활성 상태를 유지하도록 지시합니다.
  2. 매니페스트 적용

    kubectl apply -f capacity-res-job.yaml
    
  3. 작업 상태를 가져옵니다.

    kubectl get jobs
    

    모든 작업이 Running 상태가 될 때까지 기다립니다.

용량 프로비저닝 및 제거 테스트

용량 프로비저닝이 예상대로 작동하는지 확인하려면 다음을 수행합니다.

  1. 터미널에서 용량 프로비저닝 워크로드의 상태를 확인합니다.

    1. 배포의 경우 다음 명령어를 실행합니다.

      kubectl get pods --label=app=reservation -w
      
    2. 작업의 경우 다음 명령어를 실행합니다.

      kubectl get Jobs -w
      
  2. 터미널 창을 열고 다음을 수행합니다.

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

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: helloweb
        labels:
          app: hello
      spec:
        replicas: 5
        selector:
          matchLabels:
            app: hello
            tier: web
        template:
          metadata:
            labels:
              app: hello
              tier: web
          spec:
            containers:
            - name: hello-app
              image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
              ports:
              - containerPort: 8080
              resources:
                requests:
                  cpu: 400m
                  memory: 400Mi
      
    2. 매니페스트 적용

      kubectl apply -f test-deployment.yaml
      
  3. 원래 터미널 창에서 GKE는 다음 예시와 비슷하게 일부 용량 프로비저닝 워크로드를 종료하여 새 복제본을 예약합니다.

    NAME                                         READY   STATUS    RESTARTS   AGE
    capacity-res-deploy-6bd9b54ffc-5p6wc         1/1     Running   0          7m25s
    capacity-res-deploy-6bd9b54ffc-9tjbt         1/1     Running   0          7m26s
    capacity-res-deploy-6bd9b54ffc-kvqr8         1/1     Running   0          2m32s
    capacity-res-deploy-6bd9b54ffc-n7zn4         1/1     Running   0          2m33s
    capacity-res-deploy-6bd9b54ffc-pgw2n         1/1     Running   0          2m32s
    capacity-res-deploy-6bd9b54ffc-t5t57         1/1     Running   0          2m32s
    capacity-res-deploy-6bd9b54ffc-v4f5f         1/1     Running   0          7m24s
    helloweb-85df88c986-zmk4f                    0/1     Pending   0          0s
    helloweb-85df88c986-lllbd                    0/1     Pending   0          0s
    helloweb-85df88c986-bw7x4                    0/1     Pending   0          0s
    helloweb-85df88c986-gh8q8                    0/1     Pending   0          0s
    helloweb-85df88c986-74jrl                    0/1     Pending   0          0s
    capacity-res-deploy-6bd9b54ffc-v6dtk   1/1     Terminating   0          2m47s
    capacity-res-deploy-6bd9b54ffc-kvqr8   1/1     Terminating   0          2m47s
    capacity-res-deploy-6bd9b54ffc-pgw2n   1/1     Terminating   0          2m47s
    capacity-res-deploy-6bd9b54ffc-n7zn4   1/1     Terminating   0          2m48s
    capacity-res-deploy-6bd9b54ffc-2f8kx   1/1     Terminating   0          2m48s
    ...
    helloweb-85df88c986-lllbd              0/1     Pending       0          1s
    helloweb-85df88c986-gh8q8              0/1     Pending       0          1s
    helloweb-85df88c986-74jrl              0/1     Pending       0          1s
    helloweb-85df88c986-zmk4f              0/1     Pending       0          1s
    helloweb-85df88c986-bw7x4              0/1     Pending       0          1s
    helloweb-85df88c986-gh8q8              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-zmk4f              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-bw7x4              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-lllbd              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-74jrl              0/1     ContainerCreating   0          1s
    helloweb-85df88c986-zmk4f              1/1     Running             0          4s
    helloweb-85df88c986-lllbd              1/1     Running             0          4s
    helloweb-85df88c986-74jrl              1/1     Running             0          5s
    helloweb-85df88c986-gh8q8              1/1     Running             0          5s
    helloweb-85df88c986-bw7x4              1/1     Running             0          5s
    

    이 출력은 새 배포가 대기중에서 실행 중으로 변경되는 데 5초가 소요되었음을 나타냅니다.

용량 프로비저닝 고려사항

일관된 용량 프로비저닝

  • 필요한 자리표시자 포드 복제본 수와 각 복제본의 요청 크기를 평가합니다. 낮은 우선순위 복제본은 해당 워크로드가 우선순위가 낮은 워크로드가 예약한 용량에 적합할 수 있도록 최소한 가장 큰 프로덕션 워크로드와 동일한 용량을 요청해야 합니다.
  • 대규모로 많은 양의 프로덕션 워크로드를 운영하는 경우 자리표시자 포드의 리소스 요청을 하나의 워크로드만이 아닌 여러 프로덕션 워크로드를 실행하는 데 충분한 용량을 프로비저닝하는 값으로 설정하는 것이 좋습니다.

단일 사용 용량 프로비저닝

  • 자리표시자 작업의 지속 시간을 추가 용량이 필요한 기간으로 설정합니다. 예를 들어 24시간 게임 출시일 동안 추가 용량을 원하는 경우 시간을 86,400초로 설정합니다. 이렇게 하면 프로비저닝된 용량이 필요 이상으로 오래 지속되지 않습니다.
  • 유지보수 기간을 용량 예약과 동일한 기간으로 설정합니다. 이렇게 하면 우선순위가 낮은 작업이 노드 업그레이드 중에 제거되지 않습니다. 워크로드의 높은 수요가 예상되는 경우 유지보수 기간을 설정하는 것도 좋습니다.
  • 대규모로 많은 양의 프로덕션 워크로드를 운영하는 경우 자리표시자 작업의 리소스 요청을 하나의 워크로드만이 아닌 여러 프로덕션 워크로드를 실행하는 데 충분한 용량을 프로비저닝하는 값으로 설정하는 것이 좋습니다.

용량은 단일 확장 이벤트에 대해서만 프로비저닝됩니다. 용량을 수직 확장 후 사용하면 축소되어 다른 확장 이벤트에 더 이상 사용할 수 없습니다. 여러 확장 및 축소 이벤트가 예상되는 경우 일관된 용량 예약 방법을 사용하고 필요에 따라 예약 크기를 조정하세요. 예를 들어 이벤트 전에 포드 요청을 더 크게 만들고 그 이후에 더 적게나 0으로 설정할 수 있습니다.

우선순위 선택

PriorityClass의 우선순위를 0 미만으로 설정할 수 있습니다.

요구사항이 다른 워크로드에 사용할 클러스터에서 여러 PriorityClass를 정의할 수 있습니다. 예를 들어 PriorityClass를 단일 사용 용량 프로비저닝에 대해서는 -10 우선순위로 만들고 일관적인 용량 프로비저닝에 대해서는 PriorityClass를 -9 우선순위로 만들 수 있습니다. 그런 다음 우선순위가 -9인 PriorityClass를 사용하여 일관된 용량을 프로비저닝할 수 있으며, 특별 이벤트에 더 많은 용량을 원하면 -10 우선순위인 PriorityClass를 사용하는 새 작업을 배포할 수 있습니다. GKE는 우선순위가 가장 낮은 워크로드를 먼저 제거합니다.

또한 다른 PriorityClasses를 사용하여 실제 작업을 수행하는 우선순위가 낮은 비프로덕션 워크로드를 프로덕션 워크로드보다는 낮지만 자리표시자 포드보다는 높은 우선순위로 실행할 수 있습니다. 예를 들면 -5입니다.

용량 크기 선택

수직 확장할 때 자리표시자 워크로드의 복제본 수 및 리소스 요청을 프로덕션 워크로드에 필요할 수 있는 용량 이상으로 설정할 수 있습니다.

프로비저닝된 총 용량은 배포하는 자리표시자 포드 수와 각 복제본의 리소스 요청을 기반으로 합니다. 수직 확장할 때 자리표시자 포드에 GKE에서 프로비저닝한 것보다 더 많은 용량이 필요한 경우 GKE에서 더 많은 용량을 프로비저닝할 수 있을 때까지 일부 프로덕션 워크로드가 Pending으로 유지됩니다.

다음 단계