용량 버퍼 구성

용량 버퍼는 Kubernetes CapacityBuffer CustomResourceDefinition (CRD)을 사용하여 사전 프로비저닝되고 사전 구성된 용량의 정지 상태와 예비 클러스터 용량을 사전에 관리함으로써 중요한 워크로드의 응답성과 안정성을 향상시킵니다. 용량 버퍼를 사용하면 클러스터 내에서 사용되지 않은 특정 노드 용량을 명시적으로 정의할 수 있습니다. 이 예약된 용량은 포드 예약 시간을 줄이는 데 도움이 됩니다.

우선순위가 높은 워크로드를 빠르게 확장해야 하는 경우 새 워크로드는 노드 프로비저닝을 기다리지 않고 빈 용량을 즉시 사용할 수 있습니다. 이 접근 방식은 지연 시간을 최소화하고 수요가 급증하는 동안 리소스 경합을 방지합니다.

이 페이지에서는 고정 복제본, 리소스 한도, 비율 기반 용량 버퍼를 구성하고, 특정 워크로드에 버퍼를 전용하고, 대기 버퍼 동작을 맞춤설정하고, 컨테이너 이미지를 미리 로드하는 방법을 보여줍니다.

시작하기 전에

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

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치했으면 gcloud components update 명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.
  • 버전 1.37.1-gke.3020000 이상을 실행하는 GKE 클러스터를 만들거나 액세스합니다. Autopilot 클러스터의 대기 버퍼에는 커스텀 ComputeClass가 필요합니다.
  • Standard 클러스터에서 노드 풀 자동 생성을 사용 설정합니다. Autopilot 클러스터에서는 노드 풀 자동 생성이 이미 사용 설정되어 있습니다. 노드 풀 자동 생성은 선택사항이지만 활성 버퍼에 권장되며 대기 버퍼에 필요합니다.

기본 요건 Kubernetes 객체 만들기

CapacityBuffer를 구성하려면 필요한 모든 객체 (CapacityBuffer 자체 및 PodTemplate 또는 워크로드와 같은 추가 리소스)를 보유하는 네임스페이스가 필요합니다. PodTemplate 및 CapacityBuffer는 동일한 네임스페이스에 있어야 합니다. 네임스페이스를 만들거나 default 네임스페이스를 비롯한 기존 네임스페이스를 사용할 수 있습니다.

구성하는 CapacityBuffer 유형에 따라 다음 중 하나도 필요합니다.

  • PodTemplate: 버퍼 용량의 단일 단위에 대한 리소스 요구사항을 정의합니다. CapacityBuffer 객체에 지정된 구성은 포드 템플릿을 참조합니다.
  • 워크로드: CapacityBuffer 객체에서 참조하는 기존 워크로드입니다. 이 가이드에서는 배포 객체를 워크로드 예시로 사용하지만 용량 버퍼는 다음 리소스 유형을 지원합니다.

    • 배포
    • ReplicaSet
    • StatefulSet
    • ReplicationController
    • 작업
    • scale 하위 리소스를 구현하는 CustomResourceDefinition (CRD)

이 섹션에서는 이러한 객체의 예시를 제공합니다. 용량 버퍼로 구성하려는 워크로드가 이미 있는 경우 용량 버퍼 적용으로 진행합니다.

예시 Kubernetes 워크로드를 만들려면 다음 단계를 완료하세요.

  1. 다음 매니페스트를 namespace.yaml로 저장합니다.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: capacity-buffer-example
      labels:
        name: capacity-buffer-example
    

    이 매니페스트는 capacity-buffer-example라는 네임스페이스를 만듭니다.

  2. 선택사항: 커스텀 ComputeClass에서 용량 버퍼를 사용하려면 다음 매니페스트를 custom-compute-class.yaml로 저장합니다.

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: ccc-example
    spec:
      # Buffers are also created according to these priorities
      priorities:
      - machineFamily: n4
      - machineFamily: n4d
      - machineFamily: c4
      - machineFamily: c4d
      nodePoolAutoCreation:
        enabled: true
    

    이 매니페스트는 GKE가 프로비저닝하는 노드의 컴퓨팅 우선순위를 정의하고 제어하는 커스텀 ComputeClass를 만듭니다. 자세한 내용은 커스텀 ComputeClass를 참조하세요.

  3. 다음 매니페스트를 buffer-pod-template.yaml로 저장합니다.

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: buffer-unit-template
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    template:
      spec:
        terminationGracePeriodSeconds: 0
        containers:
        - name: buffer-container
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              cpu: "1"
              memory: "1Gi"
            limits:
              cpu: "1"
              memory: "1Gi"
        # Optional: Using buffers with a custom ComputeClass /
        # controls the properties of the provisioned nodes.
        nodeSelector:
          cloud.google.com/compute-class: ccc-example
    

    이 매니페스트는 버퍼 용량의 단일 단위 (1 CPU 및 1Gi 메모리)에 대한 리소스 요구사항을 정의하는 PodTemplate를 만듭니다. 이 구성은 GKE가 버퍼에 프로비저닝하는 용량 단위의 크기를 지정합니다. 예를 들어 이 PodTemplate을 사용하면 클러스터가 확장될 때 GKE는 사용 가능한 리소스가 1 CPU 및 1Gi 미만인 노드를 버퍼의 일부로 간주하지 않습니다.

  4. 다음 매니페스트를 sample-workload-deployment.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: critical-workload-ref
      namespace: capacity-buffer-example # the namespace must be the same namespace as the CapacityBuffer
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: critical-workload
      template:
        metadata:
          labels:
            app: critical-workload
        spec:
          containers:
          - name: busybox
            image: busybox
            command: ["sleep", "3600"]
            resources:
              requests:
                cpu: 100m
          # Optional: Using buffers with a custom ComputeClass /
          # controls the properties of the provisioned nodes.
          nodeSelector:
            cloud.google.com/compute-class: ccc-example
    

    이 매니페스트는 다음 섹션의 백분율 기반 버퍼 예시의 참조 객체인 10개의 복제본이 있는 샘플 배포를 만듭니다.

  5. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f namespace.yaml -f custom-compute-class.yaml -f buffer-pod-template.yaml -f sample-workload-deployment.yaml
    
  6. GKE에서 객체를 만들었는지 확인합니다.

    kubectl get podtemplate -n capacity-buffer-example
    kubectl get deployment critical-workload-ref -n capacity-buffer-example
    

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

    NAME                   AGE
    buffer-unit-template   1m
    
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    critical-workload-ref   10/10   10           10          1m
    

용량 버퍼 적용

이 섹션에서는 워크로드에 적용할 수 있는 다양한 유형의 용량 버퍼 예시를 제공합니다.

고정 복제본 버퍼 구성

고정 복제본으로 CapacityBuffer를 구성하면 PodTemplate을 기반으로 원하는 정확한 버퍼 단위 수를 지정합니다.

고정 복제본으로 버퍼를 만들려면 다음 단계를 완료하세요.

  1. 다음 매니페스트를 cb-fixed-replicas.yaml로 저장합니다.

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: fixed-replica-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      replicas: 3
      provisioningStrategy: "STRATEGY"
    

    다음을 바꿉니다.

    • NAMESPACE: 네임스페이스의 이름(예: capacity-buffer-example)
    • POD_TEMPLATE: 리소스 요구사항을 정의하는 PodTemplate입니다(예: buffer-unit-template).
    • STRATEGY: 프로비저닝 전략("buffer.x-k8s.io/active-capacity"(기본값) 또는 "buffer.gke.io/standby-capacity")

    이 매니페스트는 PodTemplate을 참조하여 특정 수의 버퍼 단위를 요청하는 CapacityBuffer 리소스를 만듭니다.

  2. 매니페스트를 적용합니다.

    kubectl apply -f cb-fixed-replicas.yaml
    
  3. GKE가 용량 버퍼를 적용했는지 확인합니다.

    kubectl get capacitybuffer fixed-replica-buffer -n NAMESPACE
    

    상태의 replicas 필드에는 매니페스트에 정의한 복제본 수를 반영하는 3가 표시되어야 합니다. STATUS 필드에 ReadyForProvisioning가 표시됩니다.

리소스 한도 버퍼 구성

limits 필드를 사용하여 버퍼가 사용해야 하는 최대 리소스 양을 정의할 수 있으며, 이는 PodTemplate 크기를 기준으로 계산됩니다.

리소스 한도 버퍼를 만들려면 다음 단계를 완료하세요.

  1. 다음 매니페스트를 cb-resource-limits.yaml로 저장합니다.

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: resource-limit-buffer
      namespace: NAMESPACE
    spec:
      podTemplateRef:
        name: POD_TEMPLATE
      limits:
        cpu: "5"
        memory: "5Gi"
      provisioningStrategy: "STRATEGY"
    

    다음을 바꿉니다.

    • NAMESPACE: 네임스페이스의 이름(예: capacity-buffer-example)
    • POD_TEMPLATE: 리소스 요구사항을 정의하는 PodTemplate입니다(예: buffer-unit-template).
    • STRATEGY: 프로비저닝 전략("buffer.x-k8s.io/active-capacity"(기본값) 또는 "buffer.gke.io/standby-capacity")

    이 매니페스트는 총 한도가 CPU 5개, 메모리 5GiB인 CapacityBuffer 리소스를 만듭니다. 이전 단계의 PodTemplate 예시를 사용하는 경우 각 단위를 1 CPU 및 1Gi 메모리로 정의합니다. 그러면 버퍼 단위가 5개 생성됩니다.

  2. 매니페스트를 적용합니다.

    kubectl apply -f cb-resource-limits.yaml
    
  3. GKE가 용량 버퍼를 적용했는지 확인합니다.

    kubectl get capacitybuffer resource-limit-buffer -n NAMESPACE
    

    CapacityBuffer 상태를 확인합니다. replicas 필드에는 정의한 한도에서 파생된 값이 표시되어야 합니다. 이전 섹션의 PodTemplate 예시를 사용하는 경우 정의된 한도 내에 맞는 최대 단위 수이므로 5 버퍼 단위가 표시됩니다.

비율 기반 버퍼 구성

비율 기반 버퍼를 구성하면 기존 확장 가능한 워크로드의 비율에 따라 버퍼 크기가 동적으로 조정됩니다. 비율 기반 용량 버퍼는 배포, StatefulSet, ReplicaSet, 작업과 같은 확장 하위 리소스를 구현하는 Kubernetes 확장 가능 객체에만 지원됩니다. 포드 템플릿에는 replicas 필드가 없으므로 포드 템플릿에 비율 기반 버퍼를 정의할 수 없습니다.

대부분의 경우 백분율 기반 버퍼보다는 고정 복제본 또는 리소스 한도 전략으로 시작합니다. 결정할 때 다음 사항을 고려하세요.

  • 워크로드가 낮은 수 또는 0으로 확장되는 경우 안전 여유가 활성 포드에 비례하여 감소하므로 백분율 기반 버퍼는 갑작스러운 확장 시 응답성이 떨어집니다.
  • 대기 노드는 정지되기 전 초기화 기간 동안 컴퓨팅 요금이 발생합니다. 워크로드 변동에 따라 대기 버퍼를 동적으로 확장하면 컴퓨팅 리소스가 낭비되므로 대신 대기 버퍼에 고정 복제본이나 리소스 한도를 사용하세요.
  • 백분율 기반 버퍼는 복제본 수가 적은 규모로 축소되지 않는 대규모 배포의 활성 버퍼에 주로 유용합니다.

참조된 워크로드가 축소될 때 최소 버퍼 크기를 유지하려면 replicas 필드를 percentage 필드와 함께 설정합니다. GKE는 더 많은 버퍼 단위를 생성하는 필드를 사용합니다. 버퍼 사이즈를 제한하려면 limits 필드도 설정합니다.

예를 들어 복제본이 10개인 배포를 참조하는 percentage: 20 및 replicas: 3가 있는 버퍼를 생각해 보세요. 10개 복제본의 20% 는 2이며, 이는 replicas 값인 3보다 작으므로 GKE는 버퍼 단위를 3개 프로비저닝합니다. 배포가 복제본 20개로 확장되면 버퍼는 4개 단위로 증가합니다. 자세한 내용은 CapacityBuffer 참고 문서를 확인하세요.

비율 기반 버퍼를 만들려면 다음 단계를 완료하세요.

  1. 다음 매니페스트를 cb-percentage-based.yaml로 저장합니다.

    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: CapacityBuffer
    metadata:
      name: percentage-buffer
      namespace: NAMESPACE
    spec:
      scalableRef:
        apiGroup: apps
        kind: Deployment
        name: SCALABLE_RESOURCE_NAME
      percentage: 20
      provisioningStrategy: "STRATEGY"
    

    다음을 바꿉니다.

    • NAMESPACE: 네임스페이스의 이름입니다.
    • SCALABLE_RESOURCE_NAME: 확장 가능한 리소스의 이름(예: critical-workload-ref)
    • STRATEGY: 프로비저닝 전략("buffer.x-k8s.io/active-capacity"(기본값) 또는 "buffer.gke.io/standby-capacity")

    이 매니페스트는 참조된 리소스 복제본의 20% 에 해당하는 버퍼 사이즈를 요청하는 CapacityBuffer 리소스를 만듭니다. 이전 섹션의 배포 예시를 사용하는 경우 복제본 값은 10으로 설정됩니다.

  2. 매니페스트를 적용합니다.

    kubectl apply -f cb-percentage-based.yaml
    
  3. GKE가 용량 버퍼를 적용했는지 확인합니다.

    kubectl get capacitybuffer percentage-buffer -n NAMESPACE
    

    CapacityBuffer 상태를 확인합니다. replicas 필드에는 백분율 계산 값이 표시되어야 합니다. 이전 섹션의 배포 예시를 사용하는 경우 배포에 정의된 복제본 10개의 20% 인 2 버퍼 단위가 표시됩니다.

  4. 배포를 최대 20개의 복제본으로 수동 확장하여 동적 확장을 테스트합니다.

    kubectl scale deployment critical-workload-ref -n NAMESPACE --replicas=20
    

    CapacityBuffer 컨트롤러가 반응하여 버퍼를 복제본 4개로 자동 확장합니다.

특정 워크로드에 용량 버퍼 전용

기본적으로 버퍼 노드의 예약 제약조건과 일치하는 대기 중인 포드는 버퍼 용량을 요청할 수 있습니다. 여러 워크로드가 커스텀 ComputeClass 또는 노드 풀을 공유하는 경우 워크로드 분리를 사용하여 특정 워크로드의 용량 버퍼를 예약합니다. 이 접근 방식에는 노드 풀 자동 생성 또는 Standard 클러스터의 활성 버퍼를 위한 전용 노드 풀이 필요합니다.

여러 개별 워크로드에 별도의 용량 버퍼를 할당하지 마세요. 각 전용 버퍼에는 자체 노드 풀이 필요하므로 버퍼를 프로비저닝하고 다시 채우는 데 시간이 더 오래 걸립니다. 권장 버퍼 수는 확장성을 참조하세요.

용량 버퍼를 특정 워크로드에 전용하려면 다음 단계를 완료하세요.

  1. 기본 요건 Kubernetes 객체 만들기의 sample-workload-deployment.yaml와 같은 워크로드 매니페스트에서 포드 사양에 커스텀 톨러레이션(toleration) 및 노드 선택기를 추가합니다.

    spec:
      tolerations:
      - key: KEY
        operator: Equal
        value: "VALUE"
        effect: NoSchedule
      nodeSelector:
        KEY: "VALUE"
        cloud.google.com/compute-class: ccc-example
    

    다음을 바꿉니다.

    • KEY: taint 및 노드 라벨의 커스텀 키(예: group) 제한된 키 프리픽스는 워크로드 분리 제한사항을 참조하세요.
    • VALUE: 워크로드를 식별하는 커스텀 값입니다(예: critical-workload).

    Autopilot 클러스터에서 버퍼가 지원되지 않는 포드 기반 결제 모델 대신 노드 기반 결제를 사용하도록 nodeSelector 필드에 커스텀 ComputeClass 또는 하드웨어 선택기를 유지합니다.

  2. 동일한 예약 제약 조건을 사용하도록 CapacityBuffer를 구성합니다.

    • CapacityBuffer에서 scalableRef 필드를 사용하는 경우 spec.scalableRef 필드에서 워크로드를 참조합니다. 버퍼는 워크로드의 tolerations 및 nodeSelector 필드를 자동으로 상속합니다.
    • CapacityBuffer에서 podTemplateRef 필드를 사용하는 경우 동일한 tolerations 및 nodeSelector 필드를 PodTemplate 매니페스트에 추가합니다(예: buffer-pod-template.yaml).
  3. 매니페스트를 적용하고 CapacityBuffer를 만듭니다. 자세한 내용은 용량 버퍼 적용을 참조하세요. 대기 버퍼에 이미지를 미리 로드하는 경우 전용 버퍼 노드에서 예약할 수 있도록 미리 로드 DaemonSet에 커스텀 톨러레이션을 추가합니다. 버퍼가 커스텀 ComputeClass를 사용하는 경우 DaemonSet에는 ComputeClass taint에 대한 톨러레이션(toleration)도 필요합니다.

    tolerations:
    - key: "buffer.gke.io/standby-capacity-node-suspended"
      operator: "Exists"
    - key: KEY
      operator: Equal
      value: "VALUE"
      effect: NoSchedule
    - key: cloud.google.com/compute-class
      operator: Equal
      value: ccc-example
      effect: NoSchedule
    
  4. 클러스터 자동 확장 처리가 버퍼 노드를 프로비저닝한 후 노드에 전용 노드 라벨과 노드 taint가 있는지 확인합니다.

    kubectl get nodes -l KEY=VALUE \
        -o custom-columns='NAME:.metadata.name,TAINTS:.spec.taints[*].key'
    

    출력의 각 노드에는 KEY taint 키가 나열됩니다. 버퍼가 커스텀 ComputeClass를 사용하는 경우 노드에는 cloud.google.com/compute-class taint 키도 나열됩니다. 대기 버퍼 노드에는 일시중지된 노드의 buffer.gke.io/standby-capacity-node-suspended와 같이 GKE에서 관리하는 taint도 있습니다. 워크로드가 확장되면 kubectl get pods -n NAMESPACE -o wide를 실행하고 NODE 열에 이 출력의 전용 노드 이름이 나열되는지 확인합니다.

대기 버퍼 동작 맞춤설정

주석을 사용하여 대기 버퍼가 시작되고 새로고침되는 방식을 맞춤설정할 수 있습니다. CapacityBuffer 리소스의 metadata.annotations 필드에 다음 주석을 추가합니다.

  • buffer.gke.io/standby-capacity-init-time: GKE에서 노드를 정지하기 전에 노드가 생성 후 활성 상태로 유지되는 시간입니다. 5m 또는 1h와 같은 기간 문자열을 지정합니다. 기본값은 5m입니다.
  • buffer.gke.io/standby-capacity-refresh-frequency: GKE에서 정지된 노드를 새로고침하는 빈도입니다. 12h 또는 24h과 같은 기간 문자열을 최대 120h (5일)까지 지정합니다. 기본값은 24h입니다.

다음 예시에서는 대기 버퍼의 동작을 맞춤설정하는 이러한 선택적 필드가 있는 매니페스트를 보여줍니다.

apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: customized-standby-buffer
  namespace: my-namespace
  annotations:
    buffer.gke.io/standby-capacity-init-time: "15m"
    buffer.gke.io/standby-capacity-refresh-frequency: "12h"
spec:
  podTemplateRef:
    name: buffer-unit-template
  replicas: 3
  provisioningStrategy: "buffer.gke.io/standby-capacity"

대기 버퍼에 이미지 미리 로드

대기 노드가 재개될 때 워크로드 시작 시간을 단축하려면 DaemonSet를 사용하여 컨테이너 이미지를 미리 로드하면 됩니다. DaemonSet는 노드가 정지되기 전 시작 기간에 실행됩니다.

DaemonSet를 사용하여 이미지를 미리 로드하려면 다음 단계를 완료합니다.

  1. 다음 매니페스트를 image-puller-daemonset.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: image-prefetch-daemonset
      namespace: NAMESPACE
    spec:
      selector:
        matchLabels:
          name: image-prefetch
      template:
        metadata:
          labels:
            name: image-prefetch
        spec:
          tolerations:
          - key: "buffer.gke.io/standby-capacity-node-suspended"
            operator: "Exists"
          initContainers:
          - name: image-puller
            image: IMAGE_NAME
            command: ["sh", "-c", "true"]
          containers:
          - name: pause
            image: registry.k8s.io/pause:3.9
    

    다음을 바꿉니다.

    • NAMESPACE: DaemonSet의 네임스페이스입니다(예: capacity-buffer-example).
    • IMAGE_NAME: 미리 로드할 이미지의 이름입니다(예: your-app-image:latest).

    이 매니페스트에는 GKE가 대기 노드를 정지한 후에도 DaemonSet가 대기 노드에 예약된 상태로 유지되도록 buffer.gke.io/standby-capacity-node-suspended 톨러레이션(toleration)이 포함되어 있습니다.

  2. DaemonSet 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f image-puller-daemonset.yaml
    
  3. DaemonSet가 생성되었는지 확인합니다.

    kubectl get daemonset image-prefetch-daemonset -n NAMESPACE
    
  4. 용량 버퍼가 생성되고 프로비저닝할 준비가 되었는지 확인합니다.

    kubectl get capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

    상태를 확인합니다. STATUS 필드에 ReadyForProvisioning가 표시됩니다.

용량 버퍼 상태 및 성능 모니터링

kubectl 명령어와 Cloud Monitoring 측정항목을 사용하여 용량 버퍼의 상태를 모니터링할 수 있습니다.

CapacityBuffer 리소스 상태 확인

용량 버퍼의 상태를 확인하고 워크로드를 수신할 준비가 되었는지 확인하려면 다음 단계를 완료하세요.

  1. 클러스터 전체의 모든 용량 버퍼 상태를 가져옵니다.

    kubectl get capacitybuffer -A
    
  2. 특정 버퍼의 세부 상태, 조건, 이벤트 로그를 검사합니다.

    kubectl describe capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE
    

정지된 대기 버퍼 노드 식별

대기 버퍼 VM은 사전 프로비저닝되지만 비용을 줄이기 위해 정지 상태로 유지됩니다. 이러한 정지된 노드는 커스텀 조건이 있으므로 인식할 수 있습니다. 정지된 노드 인스턴스를 감사하려면 다음 명령어를 실행합니다.

kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'

True 상태는 대기 VM이 정지되었음을 나타냅니다. False 또는 <none> 상태는 활성 상태의 실행 중인 노드를 나타냅니다.

Cloud Monitoring으로 성능 모니터링

용량 버퍼가 확장 시간에 미치는 엔드 투 엔드 영향을 모니터링하려면 Google Cloud 콘솔에서 시작 지연 시간 대시보드를 사용합니다. 포드 시작 지연 시간 분포 및 포드 첫 번째 준비 지연 시간 차트를 사용하여 포드 생성부터 준비까지의 kubernetes.io/pod/latencies/pod_first_ready 측정항목을 추적합니다. Cloud Logging에서 Scheduled 이벤트를 쿼리하여 포드 예약 지연 시간을 측정할 수도 있습니다. 자세한 내용은 시작 지연 시간 측정항목 모니터링을 참조하세요.

용량 버퍼 삭제

워크로드에 더 이상 용량 버퍼가 필요하지 않으면 CapacityBuffer 객체를 삭제합니다. 이렇게 하면 자리표시자 포드가 삭제되고 클러스터 자동 확장 처리가 노드를 축소할 수 있습니다.

kubectl delete capacitybuffer CAPACITY_BUFFER_NAME -n NAMESPACE

CAPACITY_BUFFER_NAME을 삭제하려는 CapacityBuffer의 이름으로 바꿉니다.

문제 해결

다음 섹션에는 용량 버퍼의 일반적인 문제를 해결하는 방법에 대한 정보가 포함되어 있습니다.

결제 모델로 인해 용량 버퍼가 준비되지 않음

포드 기반 청구 모델(포드당 지불)을 사용하는 워크로드에 CapacityBuffer를 만드는 경우 용량 버퍼를 프로비저닝할 수 없습니다.

이 문제를 확인하려면 CapacityBuffer 상태를 확인합니다.

kubectl describe capacitybuffer BUFFER_NAME -n NAMESPACE

상태가 False인 ReadyForProvisioning 유형의 조건을 찾습니다.

이 문제를 해결하려면 CapacityBuffer가 노드 기반 결제와 호환되는 워크로드 또는 PodTemplate을 참조하는지 확인하세요.

커스텀 ComputeClass에서 프로비저닝한 노드에 버퍼 포드가 예약되지 않음

CapacityBuffer 구성 종속 항목 (예: PodTemplate)이 커스텀 ComputeClass를 선택하는 경우 새로 프로비저닝된 노드에 버퍼 포드가 예약되지 않는 문제가 발생할 수 있습니다. 이 문제로 인해 클러스터 자동 확장 처리가 유휴 노드가 삭제되는 동안 중복 노드 풀과 노드를 반복적으로 만듭니다.

이 문제는 커스텀 ComputeClass가 taint 또는 특정 런타임 요구사항이 있는 노드를 프로비저닝하고 버퍼 포드(또는 버퍼 포드가 사용하는 PodTemplate)에 일치하는 톨러레이션(toleration) 또는 설정이 없는 경우에 발생합니다.

이 문제를 해결하려면 CapacityBuffer 구성을 업데이트하여 필요한 톨러레이션(toleration), 노드 선택기 또는 런타임 클래스를 지정하세요. 예를 들어 종속 항목이 GKE Sandbox로 구성된 커스텀 ComputeClass를 선택하는 경우 다음 중 하나를 수행하도록 종속 항목을 업데이트합니다.

  • spec.runtimeClassName: gvisor 필드를 지정합니다.
  • sandbox.gke.io/runtime=gvisor:NoSchedule taint에 대한 명시적 톨러레이션(toleration)을 포함합니다.

자세한 내용은 커스텀 ComputeClass 문서를 참조하세요.

대기 버퍼 노드를 재개할 수 없음

정지된 대기 버퍼 노드는 다음 이유 중 하나로 인해 재개되지 않을 수 있습니다.

  • 정지된 대기 노드를 재개하려면 노드의 머신 유형 및 특정 CPU 플랫폼 세대(예: E2 또는 N2 머신 시리즈 내)에 대해 영역에 사용 가능한 Compute Engine 용량이 필요합니다. 영역에 해당 구성에 대한 컴퓨팅 용량이 부족하면 노드가 재개되지 않습니다. 자세한 내용은 Compute Engine 일시중지 및 재개 제한사항을 참조하세요.
  • 커스텀 ComputeClass에서 우선순위가 더 높은 노드로의 활성 마이그레이션(activeMigration.optimizeRulePriority: true)을 사용 설정하고 스팟 VM을 주문형 VM보다 높은 우선순위로 배치하면 GKE는 시간이 지남에 따라 주문형 대기 노드를 스팟 VM으로 마이그레이션합니다. 스팟 VM은 용량 제약 조건의 영향을 더 많이 받고 정지된 스팟 VM은 재개 시 주문형 VM으로 전환할 수 없으므로 이러한 제약 조건으로 인해 대기 노드가 재개되지 않을 수 있습니다.
  • 노드를 재개하면 프로젝트의 Compute Engine 할당량을 초과합니다. 자세한 내용은 할당량 한도로 인해 용량 버퍼를 프로비저닝할 수 없음을 참조하세요.

대기 노드가 재개되지 않은 이유를 확인하려면 로그 탐색기에서 Compute Engine 감사 로그를 쿼리하여 compute.instances.resume 작업에 대한 ZONE_RESOURCE_POOL_EXHAUSTED 또는 QUOTA_EXCEEDED 오류를 확인합니다.

이 문제를 해결하거나 완화하려면 다음 중 하나 이상을 수행합니다.

  • 클러스터 자동 확장 처리가 여러 영역에서 노드를 프로비저닝하거나 재개할 수 있도록 리전 클러스터를 사용합니다.
  • 커스텀 ComputeClass의 spec.priorities 목록에서 여러 머신 계열을 구성합니다. 정지된 노드를 재개할 수 없는 경우 클러스터 자동 확장 처리는 다른 우선순위 규칙에 따라 새 노드를 만드는 방식으로 대체할 수 있습니다. 이러한 새 노드는 재개된 대기 노드보다 준비되는 데 시간이 더 오래 걸립니다. 정지된 노드는 원래 머신 유형으로만 재개할 수 있으므로 이 구성은 정지된 노드를 재개하는 데 도움이 되지 않습니다.
  • 주문형 VM과 함께 전용 커스텀 ComputeClass를 사용하거나 대기 버퍼에서 사용하는 ComputeClass의 activeMigration.optimizeRulePriority 필드를 false로 설정합니다.
  • 대기 버퍼를 작은 활성 버퍼와 페어링하여 즉각적인 트래픽 급증을 흡수합니다.

할당량 한도로 인해 용량 버퍼를 프로비저닝할 수 없음

용량 버퍼는 요청된 것보다 적은 복제본을 프로비저닝하거나 Kubernetes ResourceQuotas 또는 Compute Engine 할당량을 초과하는 경우 수직 확장에 실패할 수 있습니다.

버퍼를 제한하는 할당량을 식별하려면 다음 할당량 중 하나 이상을 확인합니다.

  • 네임스페이스의 Kubernetes ResourceQuota가 버퍼를 제한하는지 확인합니다.

    kubectl describe capacitybuffer \
        CAPACITY_BUFFER_NAME \
        -n NAMESPACE
    

    status.conditions 출력에서 상태가 True인 LimitedByQuotas 조건을 찾습니다. 정지된 대기 노드에서 지원하는 단위를 포함하여 활성 및 대기 버퍼 단위는 모두 버퍼 포드가 실행 중인 것처럼 네임스페이스 ResourceQuota 한도에 반영됩니다. 버퍼가 네임스페이스 할당량을 초과하면 GKE는 사용 가능한 할당량에 맞게 status.replicas 필드를 제한합니다.

  • Compute Engine 프로젝트 할당량이 노드 프로비저닝을 차단하는지 확인합니다. 로그 탐색기에서 container.googleapis.com/cluster-autoscaler-visibility 로그에서 no.scale.up.nap.quota.exceeded 이벤트를 검색하거나 Compute Engine 감사 로그에서 QUOTA_EXCEEDED 오류를 검색합니다.

    대기 버퍼의 Compute Engine 할당량을 확인할 때는 vCPU 및 메모리 할당량 외에 다음 할당량을 모두 확인하세요.

    • 정지된 대기 노드는 내부 및 외부 IP 주소를 유지하므로 사용 중인 IP 주소 할당량을 소비합니다.
    • 대기 VM을 정지하면 Compute Engine은 노드의 메모리를 디스크에 기록하므로 노드의 메모리 크기에 비례하여 Persistent disk standard (GB) 디스크 할당량이 사용됩니다.

할당량 한도를 해결하려면 다음 중 하나를 수행합니다.

  • 버퍼의 네임스페이스에서 Kubernetes ResourceQuota를 늘립니다.
  • Compute Engine 할당량 조정 요청
  • CapacityBuffer 매니페스트에서 replicas, limits 또는 percentage 값을 줄입니다.

대기 노드가 재개된 후 DaemonSet 포드가 데이터 수신을 중지함

정지된 대기 버퍼 노드가 재개된 후 해당 노드의 DaemonSet 포드가 노드가 정지되기 전에 열린 장기 연결을 통해 데이터 수신을 중지할 수 있습니다. 포드에서 오류를 로깅하지 않고 다시 연결하지 않습니다.

이 문제는 DaemonSet 포드가 스트리밍 HTTP 응답, WebSocket 연결, 서버 전송 이벤트 또는 gRPC 서버 스트리밍 호출과 같은 수신 전용 클라이언트 역할을 할 때 발생합니다. 대기 노드가 정지된 동안 서버 또는 중간 네트워크 기기가 타임아웃되고 연결을 닫습니다. 노드가 재개되면 포드의 네트워크 스택은 여전히 연결이 열려 있는 것으로 간주합니다. 포드가 데이터를 전송하지 않으므로 연결이 종료되었음을 감지하지 못하고 데이터를 무기한 기다립니다.

이 문제를 해결하려면 DaemonSet 포드의 클라이언트 애플리케이션을 구성하여 다음 중 하나를 수행하여 닫힌 연결을 감지하고 다시 연결합니다.

  • 포드의 애플리케이션에서 클라이언트 측 TCP 연결 유지를 구성합니다 (서버에서만 연결 유지를 사용 설정하면 포드에 알림이 전송되지 않음). TCP 연결 유지 매개변수에 대한 자세한 내용은 유휴 연결을 참조하세요.
    1. 클라이언트 라이브러리 또는 언어 런타임에서 SO_KEEPALIVE 소켓 옵션을 사용 설정합니다(예: Node.js의 socket.setKeepAlive(true, initialDelay) 또는 Go의 net.Dialer.KeepAlive). 일부 런타임은 기본적으로 TCP 연결 유지를 사용 중지합니다.
    2. 운영체제 기본값에 의존하는 대신 몇 초와 같이 짧은 연결 유지 유휴 시간 (TCP_KEEPIDLE)을 구성합니다.
    3. 애플리케이션을 업데이트하여 연결 유지 프로브가 실패할 때 연결 오류(예: 연결 재설정 또는 시간 초과)를 포착하고 새 연결을 엽니다.
  • WebSocket 핑 및 퐁 프레임 또는 gRPC 연결 유지 핑과 같은 클라이언트에서 애플리케이션 수준 하트비트 또는 읽기 제한 시간을 구성하고 제한 시간이 발생하면 다시 연결하도록 애플리케이션을 업데이트합니다.

다음 단계