Restaurar de um snapshot de pod

Os snapshots de pods do Google Kubernetes Engine (GKE) ajudam a melhorar a latência de inicialização da carga de trabalho restaurando snapshots de pods em execução. Um snapshot de pod salva todo o estado do pod, incluindo memória e mudanças no sistema de arquivos raiz. Quando novas réplicas são criadas, em vez de inicializar o pod de um estado novo, o snapshot é restaurado. Em seguida, o pod retoma a execução do ponto em que o snapshot foi tirado.

Neste documento, explicamos como ativar e configurar snapshots de pods do GKE para suas cargas de trabalho.

Para mais informações sobre como os snapshots de pod funcionam, consulte Sobre snapshots de pod.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a CLI do Google Cloud para essa tarefa, instale e inicialize a gcloud CLI. Se você instalou a gcloud CLI anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da gcloud CLI não sejam compatíveis com a execução dos comandos neste documento.

Ativar snapshots de pods

Para ativar snapshots de pods, primeiro crie ou atualize um cluster com o recurso de snapshot de pod ativado. Em seguida, crie ou atualize um pool de nós para executar no GKE Sandbox.

  1. Para ativar o recurso em um cluster, siga uma destas etapas:

    • Para ativar os snapshots de pod em um novo cluster, execute o seguinte comando:

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

      Substitua:

      • CLUSTER_NAME: o nome do cluster.
      • CLUSTER_VERSION: a versão do novo cluster, que precisa ser 1.34.1-gke.3084001 ou mais recente.
      • PROJECT_ID: o ID do projeto.
    • Para ativar os snapshots de pod em um cluster, siga estas etapas:

      1. Atualize o cluster para a versão 1.34.1-gke.3084001 ou mais recente:

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

        Substitua:

        • CLUSTER_NAME: o nome do cluster.
        • NODEPOOL_VERSION: o nome do pool de nós.
        • CLUSTER_VERSION: a versão para atualizar o novo cluster, que precisa ser 1.34.1-gke.3084001 ou posterior.
      2. Ative snapshots de pods no cluster:

        gcloud container clusters update CLUSTER_NAME \
           --workload-pool=PROJECT_ID .svc.id.goog" \
           --enable-pod-snapshots
        

        Substitua PROJECT_ID pela ID do seu projeto.

  2. Ative o GKE Sandbox no seu cluster Standard:

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

    Substitua as seguintes variáveis:

    • NODE_POOL_NAME: o nome do novo pool de nós.
    • NODE_VERSION: a versão a ser usada no pool de nós.
    • MACHINE_TYPE: o tipo de máquina a ser usado para os nós.

    Para mais informações sobre como usar o gVisor, consulte Isolar as cargas de trabalho usando o GKE Sandbox.

Armazenar snapshots

Os snapshots de pods são armazenados em um bucket do Cloud Storage, que contém a memória e (opcionalmente) o estado da GPU. Os snapshots de pod exigem a Federação de Identidade da Carga de Trabalho para GKE para ativar e usar a conta de serviço do pod e fazer a autenticação no Cloud Storage.

Os snapshots de pod exigem a seguinte configuração para o bucket:

  • Namespaces hierárquicos: precisam estar ativados para permitir consultas de leitura e gravação por segundo mais altas. Os namespaces hierárquicos também exigem que o acesso uniforme no nível do bucket esteja ativado.
  • Exclusão reversível: como os snapshots de pod usam uploads compostos paralelos, é recomendável desativar recursos de proteção de dados, como a exclusão reversível. Se essa opção permanecer ativada, as exclusões de objetos temporários poderão aumentar significativamente sua fatura de armazenamento.
  • Local: o local do bucket do Cloud Storage precisa ser o mesmo do cluster do GKE, porque o desempenho pode ser afetado se os snapshots forem transferidos entre regiões diferentes.

criar o bucket do Cloud Storage

Para criar o bucket e as permissões necessárias, siga estas etapas:

  1. Criar um bucket do Cloud Storage. O comando a seguir cria um bucket com a configuração necessária:

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

    Substitua:

    • BUCKET_NAME: o nome do bucket.
    • LOCATION: o local do bucket.

    Para uma lista completa de opções de criação de buckets, consulte opções de buckets create.

Conceder permissão às cargas de trabalho para acessar o bucket do Cloud Storage

Por padrão, o GKE não tem permissões para acessar o Cloud Storage. Para ler e gravar arquivos de snapshot, conceda permissões do IAM à conta de serviço do Kubernetes (KSA) usada pelos pods de carga de trabalho.

  1. Receba as credenciais para se comunicar com o cluster usando comandos kubectl:

    gcloud container clusters get-credentials "CLUSTER_NAME"
    
  2. Para cada pod, siga estas etapas:

    1. Crie uma KSA para cada pod:

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

      Substitua:

      • KSA_NAME: o nome da KSA.
      • NAMESPACE: o namespace dos pods.
    2. Conceda à KSA permissão para acessar o bucket:

      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"
      

      Substitua:

      • PROJECT_NUMBER: o número do projeto.
      • PROJECT_ID: o ID do projeto.

(Opcional) Criar pastas gerenciadas para o bucket do Cloud Storage

A criação de pastas permite isolar permissões para snapshots de pods mutuamente não confiáveis, o que é útil em casos de uso multitenant. Para configurar pastas gerenciadas, siga estas etapas:

  1. Crie um papel personalizado do IAM que contenha apenas as permissões necessárias para snapshots de pod:

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project="PROJECT_ID" \
        --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"
    
  2. Conceda o papel roles/storage.bucketViewer a todos os KSAs no namespace de destino. Com essa função, o KSA pode ler metadados do bucket, mas não tem permissões de leitura ou gravação para objetos no bucket.

    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"
    

    Substitua:

    • PROJECT_NUMBER: o número do projeto.
    • PROJECT_ID: o ID do projeto.
  3. Para cada KSA que precisa armazenar snapshots de pod, siga estas etapas:

    1. Crie uma pasta gerenciada para a KSA:

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

      Substitua FOLDER_PATH pelo caminho da pasta gerenciada, por exemplo, my-app-snapshots.

    2. Conceda ao KSA a função personalizada podSnapshotGcsReadWriter na pasta gerenciada:

      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"
      

      Substitua KSA_NAME pelo nome da KSA.

Configurar o armazenamento para snapshots

Para especificar onde armazenar os arquivos de snapshot, crie um recurso PodSnapshotStorageConfig.

  1. O exemplo a seguir configura o GKE para armazenar snapshots de pods no caminho FOLDER_PATH/ dentro do bucket do Cloud Storage BUCKET_NAME. Salve o seguinte manifesto como example-pod-snapshot-storage-config:

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

    Substitua:

    • NAMESPACE: o namespace dos pods. Por padrão, ele é default.
    • BUCKET_NAME: o nome do bucket do Cloud Storage.
    • FOLDER_PATH: o caminho para a pasta gerenciada do Cloud Storage.
  2. Aplique o manifesto:

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

Criar uma política de snapshot

Para ativar snapshots em um pod, crie um recurso PodSnapshotPolicy com um seletor que corresponda aos rótulos do pod.

  1. O exemplo a seguir cria uma política que se aplica a pods com o rótulo app: my-app e usa a configuração de armazenamento example-pod-snapshot-storage-config. Salve o manifesto a seguir como example-pod-snapshot-policy.yaml:

    apiVersion: podsnapshot.gke.io/v1alpha1
    kind: PodSnapshotPolicy
    metadata:
      name: example-pod-snapshot-policy
      namespace: NAMESPACE
    spec:
      storageConfigName: example-pod-snapshot-storage-config
      selector:
        matchLabels:
          app: my-app
      triggerConfig:
        type: workload
        postCheckpoint: resume
    
  2. Aplique o manifesto:

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

Otimizar o tamanho do snapshot

Quando um snapshot de pod é acionado, o gVisor captura todo o estado de todos os contêineres, incluindo:

  • Estado do aplicativo, como memória e registros
  • Mudanças no sistema de arquivos raiz e no tmpfs (incluindo volumes emptyDir)
  • Estado do kernel, como descritores de arquivos abertos, linhas de execução e sockets

O tamanho do snapshot é determinado por estes fatores. Snapshots maiores levam mais tempo para serem salvos e restaurados. Para otimizar o desempenho, antes de acionar um snapshot, limpe qualquer estado ou arquivo do aplicativo que não seja necessário depois que o pod for restaurado do snapshot.

A otimização do tamanho do snapshot é particularmente importante para cargas de trabalho como modelos de linguagem grandes (LLMs). Os servidores de LLM geralmente fazem o download dos pesos do modelo para o armazenamento local (rootfs ou tmpfs) antes de carregá-los na GPU. Quando um snapshot é criado, o estado da GPU e os arquivos de peso do modelo são salvos. Nesse cenário, se o modelo for de 100 GB, o snapshot resultante será de aproximadamente 200 GB (100 GB de arquivos de modelo mais 100 GB representando o estado da GPU). Depois que os pesos do modelo são carregados na GPU, os arquivos no sistema de arquivos geralmente não são necessários para a execução do aplicativo. Ao excluir esses arquivos de modelo antes de acionar o snapshot, é possível reduzir o tamanho dele pela metade e restaurar o aplicativo com uma latência significativamente menor.

Acionar um snapshot

É possível acionar um snapshot de dentro de uma carga de trabalho quando o aplicativo estiver pronto ou acionar manualmente um snapshot sob demanda para um pod específico.

Acionar um snapshot de uma carga de trabalho

Para acionar um snapshot no código do aplicativo, configure o aplicativo para enviar um sinal quando ele estiver pronto para um snapshot. Para sinalizar prontidão, grave 1 no arquivo /proc/gvisor/checkpoint, por exemplo, echo 1 > /proc/gvisor/checkpoint. A operação de gravação inicia o processo de snapshot de forma assíncrona e retorna imediatamente. A leitura do mesmo descritor de arquivo bloqueia o processo de leitura até que o snapshot e a restauração sejam concluídos e a carga de trabalho esteja pronta para ser retomada.

O uso exato varia de acordo com o aplicativo, mas o exemplo a seguir mostra um gatilho de snapshot para um aplicativo Python. Para acionar um Snapshot deste exemplo de carga de trabalho, conclua as etapas a seguir:

  1. Salve o seguinte manifesto como 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. Implante o aplicativo:

    kubectl apply -f my-app.yaml
    

Acionar um snapshot manualmente

Para acionar manualmente um snapshot sob demanda de um pod específico, crie um recurso PodSnapshotManualTrigger. O acionamento manual de um snapshot está disponível nas versões 1.34.1-gke.3556000 e mais recentes do GKE.

  1. O exemplo a seguir aciona um snapshot para um pod chamado my-pod. Salve o seguinte manifesto como example-manual-trigger.yaml:

    apiVersion: podsnapshot.gke.io/v1alpha1
    kind: PodSnapshotManualTrigger
    metadata:
      name: example-manual-trigger
      namespace: NAMESPACE
    spec:
      targetPod: my-pod
    
  2. Aplique o manifesto:

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

Para confirmar se o snapshot foi acionado, verifique o campo status do recurso PodSnapshotManualTrigger:

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

O campo status indica se o acionamento do snapshot foi concluído ou falhou.

Verificar snapshots

Para confirmar se um snapshot foi criado, verifique o histórico de eventos de eventos 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

Substitua POD_NAME pelo nome do pod, por exemplo, my-app ou my-pod.

A saída será assim:

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

Gerenciar snapshots

Quando você cria um instantâneo de pod, um recurso CRD PodSnapshot é criado para armazenar o estado do pod naquele momento. O campo status desse recurso indica se a operação de snapshot foi bem-sucedida e se o snapshot está disponível para restaurações.

Para conferir todos os recursos PodSnapshot em um namespace, execute o seguinte comando:

kubectl get podsnapshots.gke.io --namespace NAMESPACE

A saída será assim:

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

Restaurar uma carga de trabalho de um snapshot

Para restaurar sua carga de trabalho do snapshot mais recente, exclua o pod atual depois que um snapshot for criado e, em seguida, implante o pod novamente. Como alternativa, implante um novo pod com uma especificação idêntica. O GKE restaura automaticamente o pod do snapshot correspondente.

As etapas a seguir mostram como um pod é restaurado de um snapshot correspondente excluindo e reimplantando o pod:

  1. Exclua o pod:

    kubectl delete -f POD_NAME.yaml
    

    Substitua POD_NAME pelo nome do pod, por exemplo, my-app.

  2. Aplique o pod novamente:

    kubectl apply -f POD_NAME.yaml
    
  3. Confira os registros para confirmar a restauração do snapshot:

    kubectl logs my-app --namespace NAMESPACE
    

    A saída depende de como você configurou o aplicativo. No aplicativo de exemplo, os registros mostram GKE Pod Snapshot: restore quando uma operação de restauração ocorre.

Restaurar de um snapshot específico

Por padrão, o GKE restaura cargas de trabalho do recurso PodSnapshot mais recente que corresponde ao pod. Quando um snapshot é criado, o GKE gera automaticamente um nome exclusivo (UUID) para o recurso PodSnapshot, que você pode conferir executando kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Para restaurar uma carga de trabalho de um recurso PodSnapshot mais antigo ou específico, adicione a anotação podsnapshot.gke.io/ps-name à especificação do pod da carga de trabalho, especificando o nome do recurso PodSnapshot a ser usado para restaurar a carga de trabalho:

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:
  ...

Substitua POD_SNAPSHOT_NAME pelo nome do snapshot que você quer restaurar. Para saber os nomes dos snapshots, execute o comando kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Para que o GKE use o snapshot especificado para restauração, a condição de status do recurso PodSnapshot precisa ser Ready e estar no mesmo namespace do pod. Se o PodSnapshot não for Ready ou não existir no mesmo namespace do pod, a carga de trabalho vai realizar uma inicialização a frio em vez de restaurar de um snapshot.

Desativar snapshots

Remover o CRD PodSnapshotPolicy impede que os pods sejam capturados e restaurados. Os pods em execução não são afetados pela exclusão de recursos. No entanto, se você excluir a política enquanto um pod estiver sendo salvo ou restaurado, ele poderá entrar em um estado de falha.

Para desativar a criação de snapshots e a restauração de novos pods regidos por uma política, exclua o PodSnapshotPolicy executando o seguinte comando:

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

Substitua SNAPSHOT_POLICY pelo nome do PodSnapshotPolicy que você quer excluir, por exemplo example-pod-snapshot-policy.

Também é possível excluir um recurso PodSnapshot específico para que os pods não sejam mais restaurados desse snapshot específico. A exclusão do recurso PodSnapshot também remove os arquivos armazenados no Cloud Storage.

Para impedir que um snapshot específico seja usado em restaurações futuras, exclua o objeto PodSnapshot executando o seguinte comando:

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

Substitua POD_SNAPSHOT_NAME pelo nome do snapshot que você quer excluir, por exemplo, example-podsnapshot.

A seguir