Restaurar de um snapshot do 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 capturado.

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:

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

Ativar snapshots de pods

Para ativar snapshots de pods, crie ou atualize um cluster com o recurso de snapshot de pod ativado. Para clusters Standard, também é necessário criar ou atualizar um pool de nós para execução no GKE Sandbox. O GKE Sandbox é compatível por padrão com clusters do Autopilot.

Para ativar snapshots de pod em um cluster, conclua um dos procedimentos a seguir, dependendo do modo de operação do GKE que você quer usar:

Piloto automático

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

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

    Substitua:

    • CLUSTER_NAME: o nome do cluster.
    • CONTROL_PLANE_LOCATION: o local do plano de controle do cluster.
    • CLUSTER_VERSION: a versão do novo cluster, que precisa ser 1.35.3-gke.1234000 ou mais recente.
  • Para ativar os snapshots de pod em um cluster, siga estas etapas:

    1. Faça upgrade do cluster para a versão 1.35.3-gke.1234000 ou mais recente:

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

      Substitua:

      • CLUSTER_NAME: o nome do cluster.
      • CONTROL_PLANE_LOCATION: o local do plano de controle do cluster.
      • CLUSTER_VERSION: a versão do novo cluster, que precisa ser 1.35.3-gke.1234000 ou mais recente.
    2. Ative snapshots de pods no cluster:

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

Os snapshots de pod não são compatíveis com tipos de máquina E2. No Autopilot, o GKE pode usar nós E2 por padrão. Para garantir que suas cargas de trabalho sejam executadas em hardware compatível, use uma ComputeClass personalizada para priorizar famílias de máquinas compatíveis.

Para criar e usar uma ComputeClass personalizada, siga estas etapas:

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

      kubectl apply -f non-e2-class.yaml
    
  3. Na especificação do pod, faça referência à ComputeClass usando o seletor de nós cloud.google.com/compute-class:

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

Padrão

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

      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
    

    Substitua:

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

    1. Faça upgrade do cluster para a versão 1.35.3-gke.1234000 ou mais recente:

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

      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.35.3-gke.1234000 ou mais recente.
      • CONTROL_PLANE_LOCATION: o local do plano de controle do cluster.
    2. Ative snapshots de pods no cluster:

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

      Substitua:

      • PROJECT_ID pelo código do projeto;
      • CONTROL_PLANE_LOCATION: o local do plano de controle do cluster.

Para executar pods no GKE Sandbox em um cluster Standard, crie ou atualize um pool de nós com o gVisor ativado. Para atualizar um pool de nós, use a flag --sandbox type=gvisor. Para criar um pool de nós com o gVisor ativado, execute o seguinte comando:

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

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.
  • CONTROL_PLANE_LOCATION: o local do plano de controle do cluster.

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 mais consultas por segundo de leitura e gravação. 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, você precisa 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. Como alternativa à concessão de permissões individuais, é possível conceder tokens de curta duração em vez disso.

  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.

Ativar a multilocação usando tokens de curta duração

Como alternativa a conceder permissões a KSAs individuais, é possível ativar a multitenância usando tokens de curta duração e com escopo restrito. Essa abordagem ajuda a evitar o atraso de propagação associado às vinculações manuais do IAM. Em vez de conceder permissões a cada KSA, faça uma concessão única da função roles/storage.admin no bucket de armazenamento de snapshots para a conta de serviço do nó do GKE. Em seguida, a conta de serviço do nó cria tokens de curta duração sob demanda para caminhos específicos.

Para ativar tokens com snapshots de pod, é necessário ter a versão 1.35.3-gke.1234000 ou mais recente do GKE.

Para ativar a multitenância, siga estas etapas:

  1. Para conceder à conta de serviço do nó permissão para acessar o bucket, execute o seguinte comando:

    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. Ao configurar o armazenamento para snapshots, defina o valor do campo tokenSource como federatedP4SA.

Conceder permissão de controlador para acessar o bucket do Cloud Storage

Para permitir que o controlador de snapshots de pods exclua snapshots no bucket do Cloud Storage, o agente de serviço do GKE precisa receber a permissão de usuário de objetos do Storage.

  1. Conceda o papel 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"
    

    Substitua:

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

(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. Esse papel permite que o KSA leia metadados do bucket, mas não concede 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 pods, 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/v1
    kind: PodSnapshotStorageConfig
    metadata:
      name: example-pod-snapshot-storage-config
    spec:
      snapshotStorageConfig:
        gcs:
          bucket: "BUCKET_NAME"
          path: "FOLDER_PATH"
          tokenSource: "TOKEN_SOURCE"
    

    Substitua:

    • BUCKET_NAME: o nome do bucket do Cloud Storage.
    • FOLDER_PATH: o caminho para a pasta gerenciada do Cloud Storage.
    • TOKEN_SOURCE: o provedor de identidade para acesso. Use podKSA (padrão) ou federatedP4SA para multilocação.
  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 seguinte manifesto como 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
    

    Substitua TRIGGER_TYPE pelo tipo de gatilho. Os valores aceitos são workload para gatilhos baseados em carga de trabalho ou manual para snapshots on demand.

    Para uma lista completa de todos os campos que podem ser configurados, consulte a documentação da definição de recurso personalizado (CRD) PodSnapshotPolicy.

  2. Aplique o manifesto:

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

Configurar outras políticas de snapshot de pod

Você pode configurar outras políticas no PodSnapshotPolicy, como:

  • Limpeza automática: para limpar automaticamente recursos de instantâneo de pod antigos, configure uma política de retenção usando o campo spec.retentionConfig. É possível especificar uma duração usando o campo lastAccessTimeout (por exemplo, 7d). Depois desse período, o snapshot é excluído.

  • Organizar snapshots: é possível agrupar snapshots de forma lógica para diferenciar aqueles que foram tirados em ambientes semelhantes, mas em contextos diferentes. Por exemplo, em um cenário multitenant em que o pod base pode ser o mesmo para todos os usuários, é possível isolar os snapshots por usuário ou grupo. Para isolar snapshots, especifique rótulos de agrupamento na política usando o campo snapshotGroupingRules.

O exemplo a seguir mostra como configurar as configurações de retenção e agrupamento na PodSnapshotPolicy. Essas configurações podem ser definidas de forma independente:

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

Para uma lista completa de todos os campos que podem ser configurados, consulte a documentação do CRD PodSnapshotPolicy.

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 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, você pode 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 do 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 dessa carga de trabalho de exemplo, 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.

  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/v1
    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 snapshot 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.podsnapshot.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 as 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. 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.

Solução de problemas

A seção a seguir contém informações para ajudar a resolver problemas comuns com snapshots de pod.

Riscos de mutação pós-ponto de verificação com PVCs

Um risco significativo ocorre durante o fluxo de trabalho "checkpoint and resume" se o seu pod usar uma reivindicação de volume persistente (PVC). Se você configurar uma carga de trabalho para ser retomada imediatamente após um checkpoint (usando o campo postCheckpoint: resume), o aplicativo vai permanecer ativo e poderá modificar o PVC após o checkpoint.

  • Problema de encerramento completo: após o ciclo de checkpoint e retomada, quando você exclui um pod, o Kubernetes inicia uma sequência de encerramento completo enviando um sinal SIGTERM para o processo principal no contêiner. Muitos aplicativos implementam uma lógica de encerramento completo, em que podem acionar rotinas de limpeza, excluindo ou atualizando arquivos temporários no PVC.
  • Falha na restauração: se essas mudanças ocorrerem no PVC depois que o snapshot do pod for criado, o procedimento de restauração vai esperar o estado do PVC como ele existia no momento exato do checkpoint, o que pode levar a falhas na restauração ou inconsistência de dados.
  • Mitigação recomendada: se for necessário usar um PVC para a carga de trabalho, não retome a carga após um checkpoint. Use a configuração postCheckpoint: stop no seu PodSnapshotPolicy. Essa configuração ajuda a garantir que o processo não tenha a oportunidade de realizar gravações auxiliares ou mudanças de estado após a conclusão da fase de checkpoint.

Montagens de ConfigMap e mascaramento de diretório

Ao integrar dados de configuração a um contêiner, o método de montagem pode afetar a integridade de um snapshot.

Se um ConfigMap for montado usando uma montagem de volume padrão, o Kubernetes vai tratar todo o diretório de destino como uma montagem externa. Como as montagens externas são ignoradas durante os snapshots, todo o diretório é excluído do snapshot.

No exemplo a seguir, as mudanças no diretório /etc/my-app/ não são capturadas no snapshot porque todo o diretório é uma montagem externa:

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

Para resolver esse problema, use um subPath. Um subPath ajuda a garantir que apenas o arquivo de configuração específico seja tratado como uma montagem externa. Essa configuração tem como destino o arquivo exato, o que permite que os arquivos e a estrutura restantes no diretório principal continuem fazendo parte do sistema de arquivos local do contêiner, que é capturado corretamente durante o processo de checkpoint.

O exemplo a seguir mostra a configuração volumeMounts usando um subPath:

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

Volumes anônimos implícitos

Algumas imagens de contêiner definem volumes nos metadados (usando a instrução VOLUME no Dockerfile). Mesmo que a especificação do pod não defina um volume, o Kubernetes cria automaticamente um volume anônimo para qualquer caminho definido como um volume na imagem de base. Por exemplo, a imagem alpine/git define /git como um volume implícito.

Esses volumes anônimos são tratados como montagens externas e, assim como os PVCs, não são pontos de verificação. Recomendamos que você verifique suas imagens de base e garanta que dados críticos não sejam armazenados nesses volumes implícitos.

A seguir