Pod 스냅샷에서 복원

Google Kubernetes Engine (GKE) 포드 스냅샷은 실행 중인 포드의 스냅샷을 복원하여 워크로드 시작 지연 시간을 개선하는 데 도움이 됩니다. 포드 스냅샷은 메모리 및 루트 파일 시스템의 변경사항을 포함한 전체 포드 상태를 저장합니다. 새 복제본이 생성되면 초기 상태에서 포드를 초기화하는 대신 스냅샷이 복원됩니다. 그런 다음 포드가 스냅샷이 생성된 시점부터 실행을 재개합니다.

이 문서에서는 워크로드에 대해 GKE 포드 스냅샷을 사용 설정하고 구성하는 방법을 설명합니다.

포드 스냅샷 작동 방식에 대한 자세한 내용은 포드 스냅샷 정보를 참고하세요.

시작하기 전에

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

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치했으면 gcloud components update 명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.

Pod 스냅샷 사용 설정

포드 스냅샷을 사용 설정하려면 포드 스냅샷 기능이 사용 설정된 클러스터를 만들거나 업데이트하세요. Standard 클러스터의 경우 GKE Sandbox에서 실행할 노드 풀도 만들거나 업데이트해야 합니다. GKE Sandbox는 Autopilot 클러스터에서 기본적으로 지원됩니다.

클러스터에서 포드 스냅샷을 사용 설정하려면 사용할 GKE 작업 모드에 따라 다음 절차 중 하나를 완료하세요.

Autopilot

  • 새 클러스터에서 Pod 스냅샷을 사용 설정하려면 다음 명령어를 실행합니다.

      gcloud container clusters create-auto CLUSTER_NAME \
          --enable-pod-snapshots \
          --location=CONTROL_PLANE_LOCATION \
          --cluster-version=CLUSTER_VERSION
    

    다음을 바꿉니다.

    • CLUSTER_NAME: 클러스터 이름입니다.
    • CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 위치입니다.
    • CLUSTER_VERSION: 새 클러스터의 버전으로, 1.35.3-gke.1234000 이상이어야 합니다.
  • 기존 클러스터에서 포드 스냅샷을 사용 설정하려면 다음 단계를 완료하세요.

    1. 클러스터를 버전 1.35.3-gke.1234000 이상으로 업그레이드합니다.

        gcloud container clusters upgrade CLUSTER_NAME \
            --cluster-version=CLUSTER_VERSION \
            --location=CONTROL_PLANE_LOCATION
      

      다음을 바꿉니다.

      • CLUSTER_NAME: 클러스터 이름입니다.
      • CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 위치입니다.
      • CLUSTER_VERSION: 새 클러스터의 버전으로, 1.35.3-gke.1234000 이상이어야 합니다.
    2. 클러스터에서 포드 스냅샷을 사용 설정합니다.

        gcloud container clusters update CLUSTER_NAME \
            --enable-pod-snapshots \
            --location=CONTROL_PLANE_LOCATION
      

포드 스냅샷은 E2 머신 유형을 지원하지 않습니다. Autopilot에서 GKE는 기본적으로 E2 노드를 사용할 수 있습니다. 워크로드가 호환되는 하드웨어에서 실행되도록 하려면 커스텀 ComputeClass를 사용하여 호환되는 머신 계열에 우선순위를 지정해야 합니다.

커스텀 ComputeClass를 만들고 사용하려면 다음 단계를 완료하세요.

  1. 다음 매니페스트를 non-e2-class.yaml로 저장합니다.

      apiVersion: cloud.google.com/v1
      kind: ComputeClass
      metadata:
        name: non-e2-class
      spec:
        priorities:
        - machineFamily: n2
        - machineFamily: c3
        activeMigration:
          optimizeRulePriority: false
        whenUnsatisfiable: DoNotScaleUp
    
  2. 매니페스트를 적용합니다.

      kubectl apply -f non-e2-class.yaml
    
  3. 포드 사양에서 cloud.google.com/compute-class 노드 선택기를 사용하여 ComputeClass를 참조합니다.

      spec:
        nodeSelector:
          cloud.google.com/compute-class: non-e2-class
        ...
    

표준

  • 새 클러스터에서 Pod 스냅샷을 사용 설정하려면 다음 명령어를 실행합니다.

      gcloud container clusters create CLUSTER_NAME \
          --enable-pod-snapshots \
          --cluster-version=CLUSTER_VERSION \
          --workload-pool=PROJECT_ID.svc.id.goog \
          --workload-metadata=GKE_METADATA \
          --location=CONTROL_PLANE_LOCATION
    

    다음을 바꿉니다.

    • CLUSTER_NAME: 클러스터 이름입니다.
    • CLUSTER_VERSION: 새 클러스터의 버전으로, 1.35.3-gke.1234000 이상이어야 합니다.
    • PROJECT_ID: 프로젝트 ID입니다.
    • CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 위치입니다.
  • 기존 클러스터에서 포드 스냅샷을 사용 설정하려면 다음 단계를 완료하세요.

    1. 클러스터를 버전 1.35.3-gke.1234000 이상으로 업그레이드합니다.

        gcloud container clusters upgrade CLUSTER_NAME \
            --node-pool=NODEPOOL_NAME \
            --cluster-version=CLUSTER_VERSION \
            --location=CONTROL_PLANE_LOCATION
      

      다음을 바꿉니다.

      • CLUSTER_NAME: 클러스터 이름입니다.
      • NODEPOOL_VERSION: 노드 풀의 이름입니다.
      • CLUSTER_VERSION: 새 클러스터를 업데이트할 버전으로, 1.35.3-gke.1234000 이상이어야 합니다.
      • CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 위치입니다.
    2. 클러스터에서 포드 스냅샷을 사용 설정합니다.

      gcloud beta container clusters update CLUSTER_NAME \
         --enable-pod-snapshots \
         --location=CONTROL_PLANE_LOCATION
      

      다음을 바꿉니다.

      • PROJECT_ID를 프로젝트 ID로 바꿉니다.
      • CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 위치입니다.

Standard 클러스터의 GKE Sandbox에서 포드를 실행하려면 gVisor가 사용 설정된 노드 풀을 만들거나 업데이트하세요. 노드 풀을 업데이트하려면 --sandbox type=gvisor 플래그를 사용합니다. gVisor가 사용 설정된 노드 풀을 만들려면 다음 명령어를 실행하세요.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --location=CONTROL_PLANE_LOCATION \
  --image-type=cos_containerd \
  --sandbox type=gvisor

다음 변수를 바꿉니다.

  • NODE_POOL_NAME: 새 노드 풀의 이름입니다.
  • NODE_VERSION: 노드 풀에 사용할 버전입니다.
  • MACHINE_TYPE: 노드에 사용할 머신 유형입니다.
  • CONTROL_PLANE_LOCATION: 클러스터 컨트롤 플레인의 위치입니다.

gVisor 사용에 대한 자세한 내용은 GKE Sandbox를 사용하여 워크로드 격리를 참고하세요.

스냅샷 저장

포드 스냅샷은 메모리와 GPU 상태 (선택사항)를 포함하는 Cloud Storage 버킷에 저장됩니다. 포드 스냅샷을 사용하려면 GKE용 워크로드 아이덴티티 제휴를 사용하여 포드의 서비스 계정을 사용 설정하고 Cloud Storage에 인증해야 합니다.

Pod 스냅샷에는 버킷에 다음 구성이 필요합니다.

  • 계층적 네임스페이스: 초당 쿼리 수를 높이려면 사용 설정해야 합니다. 계층적 네임스페이스를 사용하려면 균일한 버킷 수준 액세스도 사용 설정해야 합니다.
  • 소프트 삭제: 포드 스냅샷은 병렬 복합 업로드를 사용하므로 소프트 삭제와 같은 데이터 보호 기능을 사용 중지해야 합니다. 사용 설정된 상태로 두면 임시 객체 삭제로 인해 스토리지 요금이 크게 증가할 수 있습니다.
  • 위치: 스냅샷이 서로 다른 리전 간에 전송되면 성능에 영향을 미칠 수 있으므로 Cloud Storage 버킷 위치는 GKE 클러스터와 동일한 위치여야 합니다.

Cloud Storage 버킷 만들기

버킷과 필요한 권한을 만들려면 다음 단계를 완료하세요.

  1. Cloud Storage 버킷을 만듭니다. 다음 명령어는 필요한 구성으로 버킷을 만듭니다.

    gcloud storage buckets create "gs://BUCKET_NAME" \
       --uniform-bucket-level-access \
       --enable-hierarchical-namespace \
       --soft-delete-duration=0d \
       --location="LOCATION"
    

    다음을 바꿉니다.

    • BUCKET_NAME: 버킷의 이름입니다.
    • LOCATION: 버킷의 위치입니다.

    버킷 만들기에 대한 전체 옵션 목록은 buckets create 옵션을 참고하세요.

워크로드에 Cloud Storage 버킷 액세스 권한 부여

기본적으로 GKE에는 Cloud Storage에 액세스할 수 있는 권한이 없습니다. 스냅샷 파일을 읽고 쓰려면 워크로드 포드에서 사용하는 Kubernetes ServiceAccount (KSA)에 IAM 권한을 부여해야 합니다. 개별 권한을 부여하는 대신 단기 토큰을 부여할 수도 있습니다.

  1. kubectl 명령어로 클러스터와 통신할 수 있도록 사용자 인증 정보를 가져옵니다.

    gcloud container clusters get-credentials "CLUSTER_NAME"
    
  2. 각 Pod에 대해 다음 단계를 완료합니다.

    1. 각 포드의 KSA를 만듭니다.

      kubectl create serviceaccount "KSA_NAME" \
          --namespace "NAMESPACE"
      

      다음을 바꿉니다.

      • KSA_NAME: KSA의 이름입니다.
      • NAMESPACE: 포드의 네임스페이스입니다.
    2. KSA에 버킷 액세스 권한을 부여합니다.

      gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="roles/storage.bucketViewer"
      
      gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="roles/storage.objectUser"
      

      다음을 바꿉니다.

      • PROJECT_NUMBER: 프로젝트 번호
      • PROJECT_ID: 프로젝트 ID입니다.

단기 토큰을 사용하여 멀티테넌시 사용 설정

개별 KSA에 권한을 부여하는 대신 수명이 짧고 범위가 제한된 토큰을 사용하여 멀티 테넌시를 사용 설정할 수 있습니다. 이 접근 방식은 수동 IAM 바인딩과 관련된 전파 지연을 방지하는 데 도움이 됩니다. 각 KSA에 권한을 부여하는 대신 스냅샷 스토리지 버킷에 대한 roles/storage.admin 역할을 GKE 노드 서비스 계정에 일회성으로 부여합니다. 그러면 노드 서비스 계정에서 특정 경로에 대해 필요에 따라 단기 토큰을 만듭니다.

포드 스냅샷으로 토큰을 사용 설정하려면 GKE 버전 1.35.3-gke.1234000 이상이 필요합니다.

멀티 테넌시를 사용 설정하려면 다음 단계를 완료하세요.

  1. 노드 서비스 계정에 버킷 액세스 권한을 부여하려면 다음 명령어를 실행합니다.

    gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
        --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-gkenode.iam.gserviceaccount.com" \
        --role="roles/storage.admin"
    
  2. 스냅샷 스토리지를 구성할 때 tokenSource 필드 값을 federatedP4SA로 설정합니다.

Cloud Storage 버킷에 액세스할 수 있는 컨트롤러 권한 부여

포드 스냅샷 컨트롤러가 Cloud Storage 버킷 내에서 스냅샷을 삭제할 수 있도록 하려면 GKE 서비스 에이전트에게 스토리지 객체 사용자 권한이 부여되어야 합니다.

  1. roles/storage.objectUser 역할을 부여합니다.

    gcloud projects add-iam-policy-binding "PROJECT_ID" \
      --member="serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com" \
      --role="roles/storage.objectUser" \
      --condition="expression=resource.name.startsWith(\"projects/_/buckets/BUCKET_NAME\"),title=restrict_to_bucket,description=Restricts access to one bucket only"
    

    다음을 바꿉니다.

    • PROJECT_NUMBER: 프로젝트 번호
    • PROJECT_ID: 프로젝트 ID입니다.
    • BUCKET_NAME: 버킷의 이름입니다.

(선택사항) Cloud Storage 버킷의 관리 폴더 만들기

폴더를 만들면 서로 신뢰할 수 없는 포드에서 스냅샷의 권한을 격리할 수 있으며 이는 멀티 테넌트 사용 사례에서 유용합니다. 관리 폴더를 설정하려면 다음 단계를 완료하세요.

  1. Pod 스냅샷에 필요한 권한만 포함된 커스텀 IAM 역할을 만듭니다.

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project="PROJECT_ID" \
        --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"
    
  2. 타겟 네임스페이스의 모든 KSA에 roles/storage.bucketViewer 역할을 부여합니다. 이 역할을 사용하면 KSA가 버킷 메타데이터를 읽을 수 있지만 버킷의 객체에 대한 읽기 또는 쓰기 권한은 부여되지 않습니다.

    gcloud storage buckets add-iam-policy-binding "gs://BUCKET_NAME" \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/namespace/NAMESPACE" \
        --role="roles/storage.bucketViewer"
    

    다음을 바꿉니다.

    • PROJECT_NUMBER: 프로젝트 번호
    • PROJECT_ID: 프로젝트 ID입니다.
  3. 포드 스냅샷을 저장해야 하는 각 KSA에 대해 다음 단계를 완료합니다.

    1. KSA의 관리형 폴더를 만듭니다.

      gcloud storage managed-folders create "gs://BUCKET_NAME/FOLDER_PATH/"
      

      FOLDER_PATH을 관리 폴더의 경로로 바꿉니다(예: my-app-snapshots).

    2. 관리 폴더에서 KSA에 맞춤 podSnapshotGcsReadWriter 역할을 부여합니다.

      gcloud storage managed-folders add-iam-policy-binding "gs://BUCKET_NAME/FOLDER_PATH/" \
          --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \
          --role="projects/PROJECT_ID/roles/podSnapshotGcsReadWriter"
      

      KSA_NAME을 KSA 이름으로 바꿉니다.

스냅샷 스토리지 구성

스냅샷 파일을 저장할 위치를 지정하려면 PodSnapshotStorageConfig 리소스를 만듭니다.

  1. 다음 예에서는 Cloud Storage 버킷 BUCKET_NAME 내의 FOLDER_PATH/ 경로에 포드 스냅샷을 저장하도록 GKE를 구성합니다. 다음 매니페스트를 example-pod-snapshot-storage-config로 저장합니다.

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotStorageConfig
    metadata:
      name: example-pod-snapshot-storage-config
    spec:
      snapshotStorageConfig:
        gcs:
          bucket: "BUCKET_NAME"
          path: "FOLDER_PATH"
          tokenSource: "TOKEN_SOURCE"
    

    다음을 바꿉니다.

    • BUCKET_NAME: Cloud Storage 버킷 이름.
    • FOLDER_PATH: Cloud Storage 관리 폴더의 경로입니다.
    • TOKEN_SOURCE: 액세스 권한을 부여하는 ID 공급자입니다. 멀티테넌시에는 podKSA (기본값) 또는 federatedP4SA을 사용합니다.
  2. 매니페스트를 적용합니다.

    kubectl apply -f example-pod-snapshot-storage-config.yaml
    

스냅샷 정책 만들기

포드의 스냅샷을 사용 설정하려면 포드의 라벨과 일치하는 선택기가 있는 PodSnapshotPolicy 리소스를 만듭니다.

  1. 다음 예시에서는 app: my-app 라벨이 있는 포드에 적용되고 example-pod-snapshot-storage-config 스토리지 구성을 사용하는 정책을 만듭니다. 다음 매니페스트를 example-pod-snapshot-policy.yaml로 저장합니다.

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotPolicy
    metadata:
      name: example-pod-snapshot-policy
      namespace: NAMESPACE
    spec:
      storageConfigName: example-pod-snapshot-storage-config
      selector:
        matchLabels:
          app: my-app
      triggerConfig:
        type: TRIGGER_TYPE
        postCheckpoint: resume
    

    TRIGGER_TYPE을 트리거 유형으로 바꿉니다. 지원되는 값은 워크로드 기반 트리거의 경우 workload이고 주문형 스냅샷의 경우 manual입니다.

    구성할 수 있는 모든 필드의 전체 목록은 PodSnapshotPolicy CustomResourceDefinition (CRD) 문서를 참고하세요.

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

    kubectl apply -f example-pod-snapshot-policy.yaml --namespace NAMESPACE
    

추가 Pod 스냅샷 정책 구성

PodSnapshotPolicy에서 다음과 같은 추가 정책을 구성할 수 있습니다.

  • 자동 정리: 오래된 포드 스냅샷 리소스를 자동으로 정리하려면 spec.retentionConfig 필드를 사용하여 보관 정책을 구성합니다. lastAccessTimeout 필드 (예: 7d)를 사용하여 스냅샷이 삭제되는 기간을 지정할 수 있습니다.

  • 스냅샷 정리: 비슷한 환경에서 촬영했지만 컨텍스트가 다른 스냅샷을 구분하기 위해 스냅샷을 논리적으로 그룹화할 수 있습니다. 예를 들어 모든 사용자의 기본 포드가 동일할 수 있는 멀티 테넌트 시나리오에서 사용자 또는 그룹별로 스냅샷을 격리할 수 있습니다. 스냅샷을 격리하려면 snapshotGroupingRules 필드를 사용하여 정책에 그룹화 라벨을 지정합니다.

다음 예시에서는 PodSnapshotPolicy에서 보관 및 그룹화 설정을 모두 구성하는 방법을 보여줍니다. 다음 설정은 독립적으로 설정할 수 있습니다.

# ... other fields omitted
spec:
  retentionConfig:
    lastAccessTimeout: 7d
  snapshotGroupingRules:
    groupByLabelValue:
      labels: ["tenant", "environment"]
      groupRetentionPolicy:
        maxSnapshotCountPerGroup: 5

구성할 수 있는 모든 필드의 전체 목록은 PodSnapshotPolicy CRD 문서를 참고하세요.

스냅샷 크기 최적화

포드 스냅샷이 트리거되면 gVisor는 다음을 포함한 모든 컨테이너의 전체 상태를 캡처합니다.

  • 메모리, 레지스터와 같은 애플리케이션 상태
  • 루트 파일 시스템 및 tmpfs (emptyDir 볼륨 포함) 변경사항
  • 열린 파일 설명자, 스레드, 소켓과 같은 커널 상태

스냅샷 크기는 이러한 요소에 따라 결정됩니다. 스냅샷이 클수록 저장하고 복원하는 데 시간이 오래 걸립니다. 성능을 최적화하려면 스냅샷을 트리거하기 전에 스냅샷에서 포드가 복원된 후 필요하지 않은 애플리케이션 상태나 파일을 정리해야 합니다.

스냅샷 크기 최적화는 대규모 언어 모델 (LLM)과 같은 워크로드에 특히 중요합니다. LLM 서버는 GPU에 로드하기 전에 모델 가중치를 로컬 스토리지 (rootfs 또는 tmpfs)에 다운로드하는 경우가 많습니다. 스냅샷을 찍으면 GPU 상태와 모델 가중치 파일이 모두 저장됩니다. 이 시나리오에서 모델이 100GB인 경우 결과 스냅샷은 약 200GB입니다 (100GB의 모델 파일과 GPU 상태를 나타내는 100GB). 모델 가중치가 GPU에 로드된 후에는 애플리케이션을 실행하는 데 파일 시스템의 파일이 필요하지 않은 경우가 많습니다. 스냅샷을 트리거하기 전에 이러한 모델 파일을 삭제하면 스냅샷 크기를 절반으로 줄이고 지연 시간이 훨씬 짧은 애플리케이션을 복원할 수 있습니다.

스냅샷 트리거

애플리케이션이 준비되면 워크로드 내에서 스냅샷을 트리거하거나 특정 포드에 대해 주문형 스냅샷을 수동으로 트리거할 수 있습니다.

워크로드에서 스냅샷 트리거

애플리케이션 코드 내에서 스냅샷을 트리거하려면 스냅샷을 준비할 때 신호를 전송하도록 애플리케이션을 구성합니다. 준비 상태를 알리려면 /proc/gvisor/checkpoint 파일에 1를 작성합니다(예: echo 1 > /proc/gvisor/checkpoint.). 쓰기 작업은 스냅샷 프로세스를 비동기적으로 시작하고 즉시 반환합니다. 동일한 파일 설명자에서 읽으면 스냅샷과 복원이 모두 완료되고 워크로드가 다시 시작될 준비가 될 때까지 읽기 프로세스가 차단됩니다.

정확한 사용량은 애플리케이션에 따라 다르지만 다음 예에서는 Python 애플리케이션의 스냅샷 트리거를 보여줍니다. 이 예시 워크로드에서 스냅샷을 트리거하려면 다음 단계를 완료하세요.

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

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-app
      namespace: NAMESPACE
      labels:
        app: my-app
    spec:
      serviceAccountName: KSA_NAME
      runtimeClassName: gvisor
      containers:
      - name: my-container
        image: python:3.10-slim
        command: ["python3", "-c"]
        args:
          - |
            import time
            def trigger_snapshot():
              try:
                with open("/proc/gvisor/checkpoint", "r+") as f:
                  f.write("1")
                  res = f.read().rstrip()
                  print(f"GKE Pod Snapshot: {res}")
              except FileNotFoundError:
                print("GKE Pod Snapshot file does not exist -- Pod Snapshots is disabled")
                return
              except OSError as e:
                return e
            i = 0
            while True:
              print(f"Count: {i}", flush=True)
              if (i == 20): #simulate the application being ready to snapshot at 20th count
                trigger_snapshot()
              i += 1
              time.sleep(1)
        resources:
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "250m"
            memory: "256Mi"
    
  2. 애플리케이션을 배포합니다.

    kubectl apply -f my-app.yaml
    

수동으로 스냅샷 트리거

특정 포드의 주문형 스냅샷을 수동으로 트리거하려면 PodSnapshotManualTrigger 리소스를 만드세요.

  1. 다음 예시에서는 my-pod라는 포드의 스냅샷을 트리거합니다. 다음 매니페스트를 example-manual-trigger.yaml로 저장합니다.

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotManualTrigger
    metadata:
      name: example-manual-trigger
      namespace: NAMESPACE
    spec:
      targetPod: my-pod
    
  2. 매니페스트를 적용합니다.

    kubectl apply -f example-manual-trigger.yaml --namespace NAMESPACE
    

스냅샷이 성공적으로 트리거되었는지 확인하려면 PodSnapshotManualTrigger 리소스의 status 필드를 확인합니다.

kubectl get podsnapshotmanualtriggers.podsnapshot.gke.io example-manual-trigger -n NAMESPACE -o yaml

status 필드는 스냅샷 트리거가 성공했는지 실패했는지 나타냅니다.

스냅샷 확인

GKEPodSnapshotting 이벤트의 활동 내역을 확인하여 스냅샷이 촬영되었는지 확인할 수 있습니다.

kubectl get events -o \
custom-columns=NAME:involvedObject.name,CREATIONTIME:.metadata.creationTimestamp,REASON:.reason,MESSAGE:.message \
--namespace NAMESPACE \
--field-selector involvedObject.name=POD_NAME,reason=GKEPodSnapshotting

POD_NAME을 포드 이름(예: my-app 또는 my-pod)으로 바꿉니다.

다음과 유사한 결과가 출력됩니다.

NAME                                    CREATIONTIME           REASON               MESSAGE
default/5b449f9c7c-bd7pc                2025-11-05T16:25:11Z   GKEPodSnapshotting   Successfully checkpointed the pod to PodSnapshot

스냅샷 관리

포드 스냅샷을 만들면 해당 시점의 포드 상태를 저장하는 PodSnapshot CRD 리소스가 생성됩니다. 이 리소스의 status 필드는 스냅샷 작업이 성공했는지, 스냅샷을 복원할 수 있는지 여부를 나타냅니다.

네임스페이스의 모든 PodSnapshot 리소스를 보려면 다음 명령어를 실행합니다.

kubectl get podsnapshots.podsnapshot.gke.io --namespace NAMESPACE

다음과 유사한 결과가 출력됩니다.

NAME                                   STATUS                  POLICY           AGE
de334898-1e7a-4cdb-9f2e-7cc2181c29e4   AllSnapshotsAvailable   example-policy   47h

스냅샷에서 워크로드 복원

최신 스냅샷에서 워크로드를 복원하려면 스냅샷을 생성한 후 기존 포드를 삭제한 다음 포드를 다시 배포하면 됩니다. 또는 동일한 사양으로 새 포드를 배포할 수 있습니다. GKE는 일치하는 스냅샷에서 포드를 자동으로 복원합니다.

다음 단계에서는 포드를 삭제하고 다시 배포하여 일치하는 스냅샷에서 포드를 복원하는 방법을 보여줍니다.

  1. 포드를 삭제합니다.

    kubectl delete -f POD_NAME.yaml
    

    POD_NAME을 포드 이름(예: my-app)으로 바꿉니다.

  2. 포드를 다시 적용합니다.

    kubectl apply -f POD_NAME.yaml
    
  3. 로그를 확인하여 스냅샷 복원을 확인합니다.

    kubectl logs my-app --namespace NAMESPACE
    

    출력은 애플리케이션을 구성한 방식에 따라 다릅니다. 예시 애플리케이션에서 복원 작업이 발생하면 로그에 GKE Pod Snapshot: restore가 표시됩니다.

특정 스냅샷에서 복원

기본적으로 GKE는 포드와 일치하는 가장 최근의 PodSnapshot 리소스에서 워크로드를 복원합니다. 스냅샷이 생성되면 GKE는 PodSnapshot 리소스의 고유한 이름 (UUID)을 자동 생성하며, kubectl get podsnapshots.gke.io --namespace NAMESPACE를 실행하여 이를 확인할 수 있습니다.

이전 또는 특정 PodSnapshot 리소스에서 워크로드를 복원하려면 워크로드 포드 사양에 podsnapshot.gke.io/ps-name 주석을 추가하여 워크로드 복원에 사용할 PodSnapshot 리소스의 이름을 지정합니다.

apiVersion: v1
kind: Pod
metadata:
  name: my-app
  namespace: NAMESPACE
  labels:
    app: my-app
  annotations:
    podsnapshot.gke.io/ps-name: "POD_SNAPSHOT_NAME"
spec:
  serviceAccountName: KSA_NAME
  runtimeClassName: gvisor
  containers:
  ...

POD_SNAPSHOT_NAME을 복원할 스냅샷의 이름으로 바꿉니다. kubectl get podsnapshots.gke.io --namespace NAMESPACE 명령어를 실행하여 스냅샷 이름을 가져올 수 있습니다.

GKE가 복원에 지정된 스냅샷을 사용하려면 PodSnapshot 리소스 상태 조건이 Ready이어야 하고 Pod와 동일한 네임스페이스에 있어야 합니다. PodSnapshot이 Ready이거나 포드와 동일한 네임스페이스에 없는 경우 워크로드는 스냅샷에서 복원하는 대신 콜드 스타트를 실행합니다.

스냅샷 사용 중지

PodSnapshotPolicy CRD를 삭제하면 포드가 스냅샷으로 생성되고 복원되지 않습니다. 실행 중인 포드는 리소스 삭제의 영향을 받지 않습니다. 하지만 포드가 저장되거나 복원되는 동안 정책을 삭제하면 포드가 실패 상태가 될 수 있습니다.

정책에 의거하여 관리되는 새 포드의 스냅샷 생성 및 복원을 사용 중지하려면 다음 명령어를 실행하여 PodSnapshotPolicy를 삭제합니다.

kubectl delete podsnapshotpolicies.podsnapshot.gke.io SNAPSHOT_POLICY --namespace=NAMESPACE

SNAPSHOT_POLICY을 삭제할 PodSnapshotPolicy의 이름으로 바꿉니다(예: example-pod-snapshot-policy).

포드가 더 이상 특정 스냅샷에서 복원되지 않도록 특정 PodSnapshot 리소스를 삭제할 수도 있습니다. PodSnapshot 리소스를 삭제하면 Cloud Storage에 저장된 파일도 삭제됩니다.

특정 스냅샷이 향후 복원에 사용되지 않도록 하려면 다음 명령어를 실행하여 PodSnapshot 객체를 삭제합니다.

kubectl delete podsnapshots.podsnapshot.gke.io POD_SNAPSHOT_NAME --namespace=NAMESPACE

POD_SNAPSHOT_NAME을 삭제할 스냅샷의 이름으로 바꿉니다(예: example-podsnapshot).

문제 해결

다음 섹션에는 Pod 스냅샷의 일반적인 문제를 해결하는 데 도움이 되는 정보가 포함되어 있습니다.

PVC를 사용한 체크포인트 후 변형 위험

포드가 영구 볼륨 클레임 (PVC)을 사용하는 경우 '체크포인트 및 재개' 워크플로 중에 심각한 위험이 발생합니다. postCheckpoint: resume 필드를 사용하여 체크포인트 직후에 재개되도록 워크로드를 구성하면 애플리케이션이 활성 상태로 유지되고 체크포인트 후에 PVC를 수정할 수 있습니다.

  • 단계적 종료 문제: 체크포인트 및 재개 주기 후 포드를 삭제하면 Kubernetes는 컨테이너의 기본 프로세스에 SIGTERM 신호를 전송하여 단계적 종료 시퀀스를 시작합니다. 많은 애플리케이션이 단계적 종료 로직을 구현하며 이 과정에서 정리 루틴을 트리거하여 PVC의 임시 파일을 삭제하거나 업데이트할 수 있습니다.
  • 복원 실패: 포드 스냅샷이 생성된 후 PVC에서 이러한 변경사항이 발생하면 복원 절차에서는 체크포인트 시점에 존재했던 PVC 상태를 예상하므로 복원 실패 또는 데이터 불일치가 발생할 수 있습니다.
  • 권장되는 완화 조치: 워크로드에 PVC를 사용해야 하는 경우 체크포인트 후에 워크로드를 재개하지 마세요. PodSnapshotPolicy에서 postCheckpoint: stop 구성을 사용합니다. 이 구성을 사용하면 체크포인트 단계가 완료된 후 프로세스가 보조 쓰기 또는 상태 변경을 실행할 기회가 없도록 할 수 있습니다.

ConfigMap 마운트 및 디렉터리 마스킹

구성 데이터를 컨테이너에 통합할 때 마운트 방법이 스냅샷의 무결성에 영향을 줄 수 있습니다.

표준 볼륨 마운트를 사용하여 ConfigMap을 마운트하면 Kubernetes는 전체 타겟 디렉터리를 외부 마운트로 취급합니다. 스냅샷 중에 외부 마운트가 건너뛰므로 전체 디렉터리가 스냅샷에서 제외됩니다.

다음 예에서는 전체 디렉터리가 외부 마운트이므로 /etc/my-app/ 디렉터리의 변경사항이 스냅샷에 캡처되지 않습니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  config.json: |
    {
      "mode": "local"
    }
---
apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  runtimeClassName: gvisor
  containers:
    - name: my-app-container
      image: my-app-image
      volumeMounts:
        - mountPath: /etc/my-app
          name: config-volume
  volumes:
    - name: config-volume
      configMap:
        name: my-config

이 문제를 해결하려면 subPath를 사용하세요. subPath는 특정 구성 파일만 외부 마운트로 처리되도록 하는 데 도움이 됩니다. 이 구성은 정확한 파일을 타겟팅하므로 상위 디렉터리 내의 나머지 파일과 구조는 체크포인트 프로세스 중에 적절하게 캡처되는 컨테이너의 로컬 파일 시스템의 일부로 유지됩니다.

다음 예시에서는 subPath을 사용하는 volumeMounts 구성을 보여줍니다.

      volumeMounts:
        - mountPath: /etc/my-app/config.json
          name: config-volume
          subPath: config.json

암시적 익명 볼륨

특정 컨테이너 이미지는 메타데이터 내에서 볼륨을 정의합니다 (Dockerfile의 VOLUME 명령어를 통해). 포드 사양에서 볼륨을 정의하지 않더라도 Kubernetes는 기본 이미지에서 볼륨으로 정의된 모든 경로에 대해 익명 볼륨을 자동으로 만듭니다. 예를 들어 alpine/git 이미지는 /git을 암시적 볼륨으로 정의합니다.

이러한 익명 볼륨은 외부 마운트로 처리되며 PVC와 마찬가지로 체크포인트가 지정되지 않습니다. 기본 이미지를 확인하고 중요한 데이터가 이러한 암시적 볼륨에 저장되지 않도록 하는 것이 좋습니다.

다음 단계