Restaurar a partir de um instantâneo do Pod

Os instantâneos de pods do Google Kubernetes Engine (GKE) ajudam a melhorar a latência de arranque da carga de trabalho restaurando instantâneos de pods em execução. Uma captura instantânea do Pod guarda todo o estado do Pod, incluindo a memória e as alterações ao sistema de ficheiros raiz. Quando são criadas novas réplicas, em vez de inicializar o pod a partir de um estado novo, a cópia instantânea é restaurada. Em seguida, o Pod retoma a execução a partir do ponto em que a captura de ecrã foi feita.

Este documento explica como ativar e configurar as capturas de ecrã de pods do GKE para as suas cargas de trabalho.

Para mais informações sobre como funcionam as capturas de ecrã de podcasts, consulte o artigo Acerca das capturas de ecrã de podcasts.

Antes de começar

Antes de começar, certifique-se de que realizou as seguintes tarefas:

  • Ative a API Google Kubernetes Engine.
  • Ative a API Google Kubernetes Engine
  • Se quiser usar a CLI gcloud para esta tarefa, instale-a e, em seguida, inicialize-a. Se instalou anteriormente a CLI gcloud, execute o comando gcloud components update para obter a versão mais recente. As versões anteriores da CLI gcloud podem não suportar a execução dos comandos neste documento.

Ative os instantâneos de pods

Para ativar os instantâneos de pods, primeiro crie ou atualize um cluster com a funcionalidade de instantâneo de pods ativada. Em seguida, crie ou atualize um conjunto de nós para ser executado no GKE Sandbox.

  1. Para ativar a funcionalidade num cluster, conclua um dos seguintes passos:

    • Para ativar as capturas instantâneas de pods num 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 o seguinte:

      • CLUSTER_NAME: o nome do cluster.
      • CLUSTER_VERSION: a versão do novo cluster, que tem de ser 1.34.1-gke.3084001 ou posterior.
      • PROJECT_ID: o ID do projeto.
    • Para ativar as capturas instantâneas de pods num cluster existente, conclua os seguintes passos:

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

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

        Substitua o seguinte:

        • CLUSTER_NAME: o nome do cluster.
        • NODEPOOL_VERSION: o nome do seu nodepool.
        • CLUSTER_VERSION: a versão para atualizar o novo cluster, que tem de ser 1.34.1-gke.3084001 ou posterior.
      2. Ative os instantâneos de pods no cluster:

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

        Substitua PROJECT_ID pelo 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 node pool.
    • NODE_VERSION: a versão a usar para o node pool.
    • MACHINE_TYPE: o tipo de máquina a usar para os nós.

    Para mais informações sobre a utilização do gVisor, consulte o artigo Isole as suas cargas de trabalho com o GKE Sandbox.

Resumos de lojas

As capturas instantâneas de pods são armazenadas num contentor do Cloud Storage, que contém a memória e (opcionalmente) o estado da GPU. As imagens instantâneas de pods requerem a federação de identidade da carga de trabalho para o GKE para ativar e usar a conta de serviço do pod para autenticar no Cloud Storage.

As capturas de ecrã de pods requerem a seguinte configuração para o contentor:

  • Espaços de nomes hierárquicos: têm de estar ativados para permitir um maior número de consultas de leitura e escrita por segundo. Os espaços de nomes hierárquicos também requerem que o acesso uniforme ao nível do contentor esteja ativado.
  • Eliminação recuperável: uma vez que as imagens instantâneas de contentores usam carregamentos compostos paralelos, deve desativar as funcionalidades de proteção de dados, como a eliminação recuperável. Se esta opção for deixada ativada, as eliminações dos objetos temporários podem aumentar significativamente a sua fatura de armazenamento.
  • Localização: a localização do contentor do Cloud Storage tem de ser a mesma que a do cluster do GKE, uma vez que o desempenho pode ser afetado se as capturas de ecrã forem transferidas entre diferentes regiões.

Crie um contentor do Cloud Storage

Para criar o contentor e as autorizações necessárias, conclua os passos seguintes:

  1. Crie um contentor do Cloud Storage. O seguinte comando cria um contentor 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 o seguinte:

    • BUCKET_NAME: o nome do seu contentor.
    • LOCATION: a localização do seu contentor.

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

Conceda autorização às cargas de trabalho para acederem ao contentor do Cloud Storage

Por predefinição, o GKE não tem autorizações para aceder ao Cloud Storage. Para ler e escrever ficheiros de instantâneos, tem de conceder autorizações da IAM à conta de serviço do Kubernetes (KSA) usada pelos seus pods de carga de trabalho.

  1. Obtenha credenciais para poder comunicar com o seu cluster através de comandos kubectl:

    gcloud container clusters get-credentials "CLUSTER_NAME"
    
  2. Para cada Pod, conclua os seguintes passos:

    1. Crie um KSA para cada agrupamento:

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

      Substitua o seguinte:

      • KSA_NAME: o nome da sua KSA.
      • NAMESPACE: o espaço de nomes dos seus agrupamentos.
    2. Conceda autorização à KSA para aceder ao contentor:

      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 o seguinte:

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

(Opcional) Crie pastas geridas para o contentor do Cloud Storage

A criação de pastas permite-lhe isolar as autorizações para instantâneos de pods mutuamente não fidedignos, o que é útil em exemplos de utilização multiinquilinos. Para configurar pastas geridas, conclua os seguintes passos:

  1. Crie uma função de IAM personalizada que contenha apenas as autorizações necessárias para instantâneos de pods:

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project="PROJECT_ID" \
        --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"
    
  2. Conceda a função roles/storage.bucketViewer a todos os KSAs no espaço de nomes de destino. Esta função permite que as KSAs leiam os metadados do contentor, mas não concede autorizações de leitura nem de escrita a objetos no contentor.

    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 o seguinte:

    • PROJECT_NUMBER: o número do seu projeto.
    • PROJECT_ID: o ID do projeto.
  3. Para cada KSA que precise de armazenar capturas de ecrã de pods, conclua os seguintes passos:

    1. Crie uma pasta gerida para a KSA:

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

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

    2. Conceda à KSA a função personalizada podSnapshotGcsReadWriter na pasta gerida:

      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.

Configure o armazenamento de instantâneos

Para especificar onde armazenar os ficheiros de imagens instantâneas, crie um PodSnapshotStorageConfigrecurso.

  1. O exemplo seguinte configura o GKE para armazenar instantâneos de pods no caminho FOLDER_PATH/ dentro do contentor do Cloud Storage BUCKET_NAME. Guarde 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 o seguinte:

    • NAMESPACE: o espaço de nomes dos seus agrupamentos. Por predefinição, esta opção é default.
    • BUCKET_NAME: o nome do seu contentor do Cloud Storage.
    • FOLDER_PATH: o caminho para a pasta gerida do Cloud Storage.
  2. Aplique o manifesto:

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

Crie uma política de instantâneos

Para ativar as capturas instantâneas para um Pod, crie um recurso PodSnapshotPolicy com um seletor que corresponda às etiquetas do Pod.

  1. O exemplo seguinte cria uma política que se aplica a Pods com a etiqueta app: my-app e usa a configuração de armazenamento example-pod-snapshot-storage-config. Guarde o seguinte manifesto 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
    

Otimize o tamanho do instantâneo

Quando é acionada uma captura instantânea do pod, o gVisor captura o estado completo de todos os contentores, incluindo:

  • Estado da aplicação, como memória e registos
  • Alterações ao sistema de ficheiros raiz e tmpfs (incluindo volumes emptyDir)
  • Estado do kernel, como descritores de ficheiros abertos, threads e sockets

O tamanho da captura de ecrã é determinado por estes fatores. As fotos rápidas maiores demoram mais tempo a guardar e restaurar. Para otimizar o desempenho, antes de acionar uma captura instantânea, deve limpar todos os ficheiros ou estados da aplicação que não sejam necessários depois de o pod ser restaurado a partir da captura instantânea.

A otimização do tamanho das imagens instantâneas é particularmente importante para cargas de trabalho como modelos de linguagem (conteúdo extenso). Os servidores de MDIs transferem frequentemente os pesos dos modelos para o armazenamento local (rootfs ou tmpfs) antes de os carregar para a GPU. Quando é tirado um instantâneo, o estado da GPU e os ficheiros de ponderação do modelo são guardados. Neste cenário, se o modelo tiver 100 GB, a imagem instantânea resultante tem aproximadamente 200 GB (100 GB de ficheiros de modelo, mais 100 GB que representam o estado da GPU). Depois de os pesos do modelo serem carregados na GPU, muitas vezes, os ficheiros no sistema de ficheiros não são necessários para a execução da aplicação. Se eliminar estes ficheiros de modelo antes de acionar a captura instantânea, pode reduzir o tamanho da captura instantânea em metade e restaurar a aplicação com uma latência significativamente inferior.

Acione um instantâneo

Pode acionar um instantâneo a partir de uma carga de trabalho quando a aplicação estiver pronta ou acionar manualmente um instantâneo a pedido para um Pod específico.

Acione um instantâneo a partir de uma carga de trabalho

Para acionar uma captura instantânea a partir do código da aplicação, configure a aplicação para enviar um sinal quando estiver pronta para uma captura instantânea. Para sinalizar que está pronto, escreva 1 no ficheiro /proc/gvisor/checkpoint, por exemplo, echo 1 > /proc/gvisor/checkpoint.. A operação de escrita inicia o processo de captura de ecrã de forma assíncrona e é concluída imediatamente. A leitura do mesmo descritor de ficheiro bloqueia o processo de leitura até que a captura instantânea e o restauro estejam concluídos e a carga de trabalho esteja pronta para ser retomada.

A utilização exata varia consoante a sua aplicação, mas o exemplo seguinte mostra um acionador de instantâneo para uma aplicação Python. Para acionar uma Snapshot a partir desta carga de trabalho de exemplo, conclua os seguintes passos:

  1. Guarde 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. Implemente a aplicação:

    kubectl apply -f my-app.yaml
    

Acione um instantâneo manualmente

Para acionar manualmente uma captura instantânea a pedido para um Pod específico, crie um recurso PodSnapshotManualTrigger. O acionamento manual de uma captura instantânea está disponível nas versões 1.34.1-gke.3556000 e posteriores do GKE.

  1. O exemplo seguinte aciona uma captura de ecrã para um pod com o nome my-pod. Guarde 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 a captura instantânea foi acionada com êxito, 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 da captura instantânea foi bem-sucedido ou falhou.

Valide instantâneos

Pode confirmar que foi tirado um instantâneo verificando o histórico de eventos para 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 seu Pod, por exemplo, my-app ou my-pod.

O resultado é semelhante ao seguinte:

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

Faça a gestão dos resumos

Quando cria uma captura instantânea do pod, é criado um recurso CRD para armazenar o estado do pod nesse momento.PodSnapshot O campo status deste recurso indica se a operação de instantâneo foi bem-sucedida e se o instantâneo está disponível para restauros.

Para ver todos os recursos PodSnapshot num espaço de nomes, execute o seguinte comando:

kubectl get podsnapshots.gke.io --namespace NAMESPACE

O resultado é semelhante ao seguinte:

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

Restaure uma carga de trabalho a partir de uma captura instantânea

Para restaurar a carga de trabalho a partir da captura instantânea mais recente, pode eliminar o pod existente depois de tirar uma captura instantânea e, em seguida, voltar a implementar o pod. Em alternativa, pode implementar um novo pod com uma especificação idêntica. O GKE restaura automaticamente o pod a partir do instantâneo correspondente.

Os passos seguintes mostram como um Pod é restaurado a partir de uma captura de ecrã correspondente através da eliminação e da nova implementação do Pod:

  1. Elimine o Pod:

    kubectl delete -f POD_NAME.yaml
    

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

  2. Volte a aplicar o Pod:

    kubectl apply -f POD_NAME.yaml
    
  3. Veja os registos para confirmar o restauro do instantâneo:

    kubectl logs my-app --namespace NAMESPACE
    

    O resultado depende da forma como configurou a sua aplicação. Na aplicação de exemplo, os registos mostram GKE Pod Snapshot: restore quando ocorre uma operação de restauro.

Restaure a partir de um instantâneo específico

Por predefinição, o GKE restaura as cargas de trabalho a partir do recurso PodSnapshot mais recente que corresponde ao pod. Quando é tirada uma captura instantânea, o GKE gera automaticamente um nome exclusivo (UUID) para o recurso PodSnapshot, que pode ver executando kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Para restaurar uma carga de trabalho a partir de um recurso 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 usar para restaurar a carga de trabalho: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:
  ...

Substitua POD_SNAPSHOT_NAME pelo nome da cópia instantânea a partir da qual quer fazer o restauro. Pode obter os nomes dos instantâneos executando o comando kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Para que o GKE use a imagem instantânea especificada para o restauro, a condição de estado do recurso PodSnapshot tem de ser Ready e existir no mesmo espaço de nomes que o pod. Se o PodSnapshot não for Ready ou não existir no mesmo espaço de nomes que o pod, a carga de trabalho executa um arranque a frio em vez de restaurar a partir de uma captura de ecrã.

Desative os instantâneos

A remoção do CRD PodSnapshotPolicy impede que sejam tiradas capturas de ecrã e restaurados os pods. Os pods em execução não são afetados pela eliminação de recursos. No entanto, se eliminar a política enquanto um Pod está a ser guardado ou restaurado, o Pod pode entrar num estado de falha.

Para desativar a criação de instantâneos e o restauro para novos pods regidos por uma política, elimine o PodSnapshotPolicy executando o seguinte comando:

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

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

Também pode eliminar um recurso PodSnapshot específico para que os pods deixem de ser restaurados a partir desse resumo específico. A eliminação do recurso PodSnapshot também remove os ficheiros armazenados no Cloud Storage.

Para impedir que uma cópia instantânea específica seja usada para restauros futuros, elimine o objeto PodSnapshot executando o seguinte comando:

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

Substitua POD_SNAPSHOT_NAME pelo nome da imagem instantânea que quer eliminar, por exemplo, example-podsnapshot.

O que se segue?