Restablece a partir de una instantánea de Pod

Las instantáneas de Pods de Google Kubernetes Engine (GKE) ayudan a mejorar la latencia de inicio de la carga de trabajo, ya que restablecen instantáneas de los Pods en ejecución. Una instantánea de Pod guarda todo el estado del Pod, incluida la memoria y los cambios en el sistema de archivos raíz. Cuando se crean réplicas nuevas, en lugar de inicializar el Pod desde un estado nuevo, se restablece la instantánea. Luego, el Pod reanuda la ejecución desde el punto en el que se tomó la instantánea.

En este documento, se explica cómo habilitar y configurar las instantáneas de Pods de GKE para tus cargas de trabajo.

Para obtener más información sobre cómo funcionan las instantáneas de Pod, consulta Acerca de las instantáneas de Pod.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste la gcloud CLI, ejecuta el comando gcloud components update para obtener la versión más reciente. Es posible que las versiones anteriores de la gcloud CLI no admitan la ejecución de los comandos que se describen en este documento.

Habilita las instantáneas de Pods

Para habilitar las instantáneas de Pods, crea o actualiza un clúster con la función de instantáneas de Pods habilitada. En el caso de los clústeres de Standard, también debes crear o actualizar un grupo de nodos para que se ejecute en GKE Sandbox. GKE Sandbox es compatible de forma predeterminada con los clústeres de Autopilot.

Para habilitar las instantáneas de Pod en un clúster, completa uno de los siguientes procedimientos, según el modo de operación de GKE que quieras usar:

Autopilot

  • Para habilitar las instantáneas de Pods en un clúster nuevo, ejecuta el siguiente comando:

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

    Reemplaza lo siguiente:

    • CLUSTER_NAME: El nombre de tu clúster.
    • CONTROL_PLANE_LOCATION: Es la ubicación del plano de control de tu clúster.
    • CLUSTER_VERSION: La versión del clúster nuevo, que debe ser 1.35.3-gke.1234000 o posterior.
  • Para habilitar las instantáneas de Pods en un clúster existente, completa los siguientes pasos:

    1. Actualiza el clúster a la versión 1.35.3-gke.1234000 o posterior:

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

      Reemplaza lo siguiente:

      • CLUSTER_NAME: El nombre de tu clúster.
      • CONTROL_PLANE_LOCATION: Es la ubicación del plano de control de tu clúster.
      • CLUSTER_VERSION: La versión del clúster nuevo, que debe ser 1.35.3-gke.1234000 o posterior.
    2. Habilita las instantáneas de Pods en tu clúster:

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

Las instantáneas de Pod no admiten tipos de máquinas E2. En Autopilot, es posible que GKE use nodos E2 de forma predeterminada. Para asegurarte de que tus cargas de trabajo se ejecuten en hardware compatible, debes usar una ComputeClass personalizada para priorizar las familias de máquinas compatibles.

Para crear y usar una ComputeClass personalizada, completa los siguientes pasos:

  1. Guarda el siguiente manifiesto 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. Aplica el manifiesto

      kubectl apply -f non-e2-class.yaml
    
  3. En la especificación del Pod, haz referencia a ComputeClass con el selector de nodos cloud.google.com/compute-class:

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

Estándar

  • Para habilitar las instantáneas de Pods en un clúster nuevo, ejecuta el siguiente 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
    

    Reemplaza lo siguiente:

    • CLUSTER_NAME: El nombre de tu clúster.
    • CLUSTER_VERSION: La versión del clúster nuevo, que debe ser 1.35.3-gke.1234000 o posterior.
    • PROJECT_ID: el ID de tu proyecto
    • CONTROL_PLANE_LOCATION: Es la ubicación del plano de control de tu clúster.
  • Para habilitar las instantáneas de Pods en un clúster existente, completa los siguientes pasos:

    1. Actualiza el clúster a la versión 1.35.3-gke.1234000 o posterior:

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

      Reemplaza lo siguiente:

      • CLUSTER_NAME: El nombre de tu clúster.
      • NODEPOOL_VERSION: es el nombre de tu grupo de nodos.
      • CLUSTER_VERSION: Es la versión a la que se actualizará tu clúster nuevo, que debe ser 1.35.3-gke.1234000 o posterior.
      • CONTROL_PLANE_LOCATION: Es la ubicación del plano de control de tu clúster.
    2. Habilita las instantáneas de Pods en tu clúster:

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

      Reemplaza lo siguiente:

      • PROJECT_ID por el ID del proyecto
      • CONTROL_PLANE_LOCATION: Es la ubicación del plano de control de tu clúster.

Para ejecutar Pods en GKE Sandbox en un clúster de Standard, crea o actualiza un grupo de nodos con gVisor habilitado. Para actualizar un grupo de nodos, usa la marca --sandbox type=gvisor. Para crear un grupo de nodos con gVisor habilitado, ejecuta el siguiente 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

Reemplaza las siguientes variables:

  • NODE_POOL_NAME: es el nombre de tu grupo de nodos nuevo.
  • NODE_VERSION: Es la versión que se usará para el grupo de nodos.
  • MACHINE_TYPE: Es el tipo de máquina que se usará para los nodos.
  • CONTROL_PLANE_LOCATION: Es la ubicación del plano de control de tu clúster.

Para obtener más información sobre el uso de gVisor, consulta Aísla tus cargas de trabajo con GKE Sandbox.

Almacena instantáneas

Las instantáneas de Pod se almacenan en un bucket de Cloud Storage, que contiene la memoria y el estado de la GPU (opcional). Las instantáneas de Pod requieren la federación de identidades para cargas de trabajo de GKE para habilitar y usar la cuenta de servicio del Pod para autenticarse en Cloud Storage.

Las instantáneas de Pod requieren la siguiente configuración para el bucket:

  • Espacios de nombres jerárquicos: deben estar habilitados para permitir una mayor cantidad de consultas por segundo de lectura y escritura. Los espacios de nombres jerárquicos también requieren que se habilite el acceso uniforme a nivel de bucket.
  • Borrar de forma no definitiva: Debido a que las instantáneas de Pod usan cargas compuestas paralelas, debes inhabilitar las funciones de protección de datos, como borrar de forma no definitiva. Si se deja habilitada, la eliminación de los objetos temporales puede aumentar significativamente tu factura de almacenamiento.
  • Ubicación: La ubicación del bucket de Cloud Storage debe ser la misma que la del clúster de GKE, ya que el rendimiento podría verse afectado si las instantáneas se transfieren entre diferentes regiones.

Crea un bucket de Cloud Storage

Para crear el bucket y los permisos necesarios, completa los siguientes pasos:

  1. Crear un bucket de Cloud Storage El siguiente comando crea un bucket con la configuración requerida:

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

    Reemplaza lo siguiente:

    • BUCKET_NAME: Es el nombre de tu bucket.
    • LOCATION: Es la ubicación de tu bucket.

    Para obtener una lista completa de las opciones de creación de bucket, consulta Opciones de buckets create.

Otorga permiso a las cargas de trabajo para acceder al bucket de Cloud Storage

De forma predeterminada, GKE no tiene permisos para acceder a Cloud Storage. Para leer y escribir archivos de instantáneas, debes otorgar permisos de IAM a la cuenta de servicio de Kubernetes (KSA) que usan tus Pods de cargas de trabajo. Como alternativa a otorgar permisos individuales, puedes otorgar tokens de corta duración.

  1. Obtén credenciales para que puedas comunicarte con tu clúster con los comandos de kubectl:

    gcloud container clusters get-credentials "CLUSTER_NAME"
    
  2. Para cada Pod, completa los siguientes pasos:

    1. Crea una KSA para cada Pod:

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

      Reemplaza lo siguiente:

      • KSA_NAME: Es el nombre de tu KSA.
      • NAMESPACE: Es el espacio de nombres de tus Pods.
    2. Otorga permiso a la KSA para acceder al 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"
      

      Reemplaza lo siguiente:

      • PROJECT_NUMBER: Es el número de tu proyecto.
      • PROJECT_ID: el ID de tu proyecto

Habilita la función multiusuario con tokens de corta duración

Como alternativa a otorgar permisos a KSA individuales, puedes habilitar la arquitectura multiusuario con tokens de corta duración y alcance restringido. Este enfoque ayuda a evitar la demora en la propagación asociada con las vinculaciones manuales de IAM. En lugar de otorgar permisos a cada KSA, otorgas el rol roles/storage.admin en el bucket de almacenamiento de instantáneas a la cuenta de servicio del nodo de GKE una sola vez. Luego, la cuenta de servicio del nodo crea tokens de corta duración a pedido para rutas específicas.

Para habilitar tokens con instantáneas de Pod, se requiere la versión 1.35.3-gke.1234000 o posterior de GKE.

Para habilitar la arquitectura multiusuario, completa los siguientes pasos:

  1. Para otorgarle permiso a la cuenta de servicio del nodo para acceder al bucket, ejecuta el siguiente 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. Cuando configures el almacenamiento para las instantáneas, establece el valor del campo tokenSource en federatedP4SA.

Otorga permiso de controlador para acceder al bucket de Cloud Storage

Para permitir que el Pod Snapshot Controller borre instantáneas dentro del bucket de Cloud Storage, se le debe otorgar al agente de servicio de GKE permiso de usuario de objeto de almacenamiento.

  1. Otorga la función 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"
    

    Reemplaza lo siguiente:

    • PROJECT_NUMBER: Es el número de tu proyecto.
    • PROJECT_ID: el ID de tu proyecto
    • BUCKET_NAME: Es el nombre de tu bucket.

(Opcional) Crea carpetas administradas para el bucket de Cloud Storage

La creación de carpetas te permite aislar los permisos para las instantáneas de los Pods que no son de confianza mutua, lo que resulta útil en casos de uso de múltiples inquilinos. Para configurar carpetas administradas, completa los siguientes pasos:

  1. Crea un rol personalizado de IAM que solo contenga los permisos necesarios para las instantáneas de Pod:

    gcloud iam roles create podSnapshotGcsReadWriter \
        --project="PROJECT_ID" \
        --permissions="storage.objects.get,storage.objects.create,storage.objects.delete,storage.folders.create"
    
  2. Otorga el rol de roles/storage.bucketViewer a todos los KSA en el espacio de nombres de destino. Este rol permite que los KSA lean los metadatos del bucket, pero no otorga permisos de lectura ni escritura para los objetos del 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"
    

    Reemplaza lo siguiente:

    • PROJECT_NUMBER: Es el número de tu proyecto.
    • PROJECT_ID: el ID de tu proyecto
  3. Para cada KSA que necesite almacenar instantáneas de Pods, completa los siguientes pasos:

    1. Crea una carpeta administrada para la KSA:

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

      Reemplaza FOLDER_PATH por la ruta de acceso a la carpeta administrada, por ejemplo, my-app-snapshots.

    2. Otorga a la KSA el rol personalizado podSnapshotGcsReadWriter en la carpeta administrada:

      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"
      

      Reemplaza KSA_NAME por el nombre de la KSA.

Configura el almacenamiento para las instantáneas

Para especificar dónde almacenar los archivos de instantáneas, crea un recurso PodSnapshotStorageConfig.

  1. En el siguiente ejemplo, se configura GKE para almacenar instantáneas de Pods en la ruta de acceso FOLDER_PATH/ dentro del bucket de Cloud Storage BUCKET_NAME. Guarda el siguiente manifiesto 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"
    

    Reemplaza lo siguiente:

    • BUCKET_NAME: Es el nombre de tu bucket de Cloud Storage.
    • FOLDER_PATH: Es la ruta de acceso a la carpeta administrada de Cloud Storage.
    • TOKEN_SOURCE: Es el proveedor de identidad para el acceso. Usa podKSA (predeterminado) o federatedP4SA para la arquitectura multiusuario.
  2. Aplica el manifiesto

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

Crea una política de instantáneas

Para habilitar las instantáneas de un Pod, crea un recurso PodSnapshotPolicy con un selector que coincida con las etiquetas del Pod.

  1. En el siguiente ejemplo, se crea una política que se aplica a los Pods con la etiqueta app: my-app y usa la configuración de almacenamiento example-pod-snapshot-storage-config. Guarda el siguiente manifiesto 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
    

    Reemplaza TRIGGER_TYPE por el tipo de activador. Los valores admitidos son workload para los activadores basados en la carga de trabajo o manual para las instantáneas a pedido.

    Para obtener una lista completa de todos los campos que puedes configurar, consulta la documentación de la definición de recurso personalizado (CRD) de PodSnapshotPolicy.

  2. Aplica el manifiesto

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

Configura políticas de instantáneas de Pod adicionales

Puedes configurar políticas adicionales en tu PodSnapshotPolicy, como las siguientes:

  • Limpieza automática: Para limpiar automáticamente los recursos de instantáneas de Pods antiguos, configura una política de retención con el campo spec.retentionConfig. Puedes especificar una duración con el campo lastAccessTimeout (por ejemplo, 7d), después de la cual se borrará la instantánea.

  • Organiza instantáneas: Puedes agrupar las instantáneas de forma lógica para diferenciar entre las que se tomaron en entornos similares, pero en contextos diferentes. Por ejemplo, en una situación de múltiples arrendatarios en la que el Pod base podría ser el mismo para todos los usuarios, podrías aislar las instantáneas por usuario o grupo. Para aislar instantáneas, especifica etiquetas de agrupación en la política con el campo snapshotGroupingRules.

En el siguiente ejemplo, se muestra cómo configurar los parámetros de configuración de retención y agrupación en tu PodSnapshotPolicy. Estos parámetros de configuración se pueden establecer de forma independiente:

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

Para obtener una lista completa de todos los campos que puedes configurar, consulta la documentación del CRD de PodSnapshotPolicy.

Optimiza el tamaño de la instantánea

Cuando se activa una instantánea de Pod, gVisor captura todo el estado de todos los contenedores, lo que incluye lo siguiente:

  • Estado de la aplicación, como la memoria y los registros
  • Cambios en el sistema de archivos raíz y tmpfs (incluidos los volúmenes emptyDir)
  • Estado del kernel, como descriptores de archivos, subprocesos y sockets abiertos

El tamaño de la instantánea se determina en función de estos factores. Las instantáneas más grandes tardan más en guardarse y restablecerse. Para optimizar el rendimiento, antes de activar una instantánea, debes limpiar cualquier estado o archivo de la aplicación que no se requiera después de que se restablezca el Pod a partir de la instantánea.

Optimizar el tamaño de la instantánea es especialmente importante para cargas de trabajo como los modelos de lenguaje grandes (LLM). Los servidores de LLM suelen descargar los pesos del modelo en el almacenamiento local (rootfs o tmpfs) antes de cargarlos en la GPU. Cuando se toma una instantánea, se guardan tanto el estado de la GPU como los archivos de peso del modelo. En este caso, si el modelo es de 100 GB, la instantánea resultante será de aproximadamente 200 GB (100 GB de archivos del modelo y 100 GB que representan el estado de la GPU). Después de que los pesos del modelo se cargan en la GPU, a menudo no se necesitan los archivos del sistema de archivos para que se ejecute la aplicación. Si borras estos archivos del modelo antes de activar la instantánea, puedes reducir el tamaño de la instantánea a la mitad y restablecer la aplicación con una latencia significativamente menor.

Cómo activar una instantánea

Puedes activar una instantánea desde una carga de trabajo cuando la aplicación esté lista o puedes activar manualmente una instantánea a pedido para un Pod específico.

Cómo activar una instantánea desde una carga de trabajo

Para activar una instantánea desde el código de la aplicación, configúrala para que envíe un indicador cuando esté lista para una instantánea. Para indicar que está listo, escribe 1 en el archivo /proc/gvisor/checkpoint, por ejemplo, echo 1 > /proc/gvisor/checkpoint.. La operación de escritura inicia el proceso de instantánea de forma asíncrona y muestra los resultados de inmediato. La lectura del mismo descriptor de archivo bloqueará el proceso de lectura hasta que se completen la instantánea y el restablecimiento, y la carga de trabajo esté lista para reanudarse.

El uso exacto variará según tu aplicación, pero el siguiente ejemplo muestra un activador de instantáneas para una aplicación de Python. Para activar una instantánea desde esta carga de trabajo de ejemplo, completa los siguientes pasos:

  1. Guarda el siguiente manifiesto 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. Implementa la aplicación:

    kubectl apply -f my-app.yaml
    

Cómo activar una instantánea de forma manual

Para activar manualmente una instantánea a pedido de un Pod específico, crea un recurso PodSnapshotManualTrigger.

  1. En el siguiente ejemplo, se activa una instantánea para un Pod llamado my-pod. Guarda el siguiente manifiesto como example-manual-trigger.yaml:

    apiVersion: podsnapshot.gke.io/v1
    kind: PodSnapshotManualTrigger
    metadata:
      name: example-manual-trigger
      namespace: NAMESPACE
    spec:
      targetPod: my-pod
    
  2. Aplica el manifiesto

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

Para confirmar si la instantánea se activó correctamente, verifica el campo status del recurso PodSnapshotManualTrigger:

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

El campo status indica si se activó la instantánea correctamente o si falló.

Verifica las instantáneas

Para confirmar que se tomó una instantánea, revisa el historial de eventos de los 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

Reemplaza POD_NAME por el nombre del Pod, por ejemplo, my-app o my-pod.

El resultado se ve de la manera siguiente:

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

Administra instantáneas

Cuando creas una instantánea de Pod, se crea un recurso CRD de PodSnapshot para almacenar el estado del Pod en ese momento. El campo status de este recurso indica si la operación de instantánea se realizó correctamente y si la instantánea está disponible para restablecimientos.

Para ver todos los recursos de PodSnapshot en un espacio de nombres, ejecuta el siguiente comando:

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

El resultado se ve de la manera siguiente:

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

Restablece una carga de trabajo a partir de una instantánea

Para restablecer tu carga de trabajo a partir de la instantánea más reciente, puedes borrar el Pod existente después de que se tome una instantánea y, luego, volver a implementar el Pod. Como alternativa, puedes implementar un Pod nuevo con una especificación idéntica. GKE restablece automáticamente el Pod a partir de la instantánea coincidente.

En los siguientes pasos, se muestra cómo se restablece un Pod a partir de una instantánea coincidente borrando y volviendo a implementar el Pod:

  1. Borra el Pod:

    kubectl delete -f POD_NAME.yaml
    

    Reemplaza POD_NAME por el nombre de tu Pod, por ejemplo, my-app.

  2. Vuelve a aplicar el Pod:

    kubectl apply -f POD_NAME.yaml
    
  3. Consulta los registros para confirmar el restablecimiento de la instantánea:

    kubectl logs my-app --namespace NAMESPACE
    

    El resultado depende de cómo hayas configurado tu aplicación. En la aplicación de ejemplo, los registros muestran GKE Pod Snapshot: restore cuando se produce una operación de restablecimiento.

Restablece a partir de una instantánea específica

De forma predeterminada, GKE restablece las cargas de trabajo desde el recurso PodSnapshot más reciente que coincide con el Pod. Cuando se toma una instantánea, GKE genera automáticamente un nombre único (UUID) para el recurso PodSnapshot, que puedes ver ejecutando kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Para restablecer una carga de trabajo desde un recurso PodSnapshot anterior o específico, agrega la anotación podsnapshot.gke.io/ps-name a la especificación del Pod de la carga de trabajo y especifica el nombre del recurso PodSnapshot que se usará para restablecer la carga de trabajo:

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

Reemplaza POD_SNAPSHOT_NAME por el nombre de la instantánea desde la que deseas restablecer. Puedes obtener los nombres de las instantáneas ejecutando el comando kubectl get podsnapshots.gke.io --namespace NAMESPACE.

Para que GKE use la instantánea especificada para la restauración, la condición de estado del recurso PodSnapshot debe ser Ready y existir en el mismo espacio de nombres que el Pod. Si el PodSnapshot no es Ready o no existe en el mismo espacio de nombres que el Pod, la carga de trabajo realiza un inicio en frío en lugar de restablecerse desde una instantánea.

Cómo inhabilitar las instantáneas

Si quitas el CRD de PodSnapshotPolicy, se impide que se creen y restablezcan instantáneas de los Pods. La eliminación del recurso no afecta a los Pods en ejecución. Sin embargo, si borras la política mientras se guarda o restablece un Pod, es posible que este entre en un estado de error.

Para inhabilitar la creación y el restablecimiento de instantáneas para los Pods nuevos regidos por una política, borra el PodSnapshotPolicy ejecutando el siguiente comando:

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

Reemplaza SNAPSHOT_POLICY por el nombre del PodSnapshotPolicy que deseas borrar, por ejemplo, example-pod-snapshot-policy.

También puedes borrar un recurso PodSnapshot específico para que los Pods ya no se restablezcan desde esa instantánea específica. Borrar el recurso PodSnapshot también quita los archivos almacenados en Cloud Storage.

Para evitar que se use una instantánea específica para restablecimientos futuros, borra el objeto PodSnapshot ejecutando el siguiente comando:

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

Reemplaza POD_SNAPSHOT_NAME por el nombre de la instantánea que deseas borrar, por ejemplo, example-podsnapshot.

Soluciona problemas

En la siguiente sección, se incluye información para ayudarte a solucionar problemas comunes con las instantáneas de Pod.

Riesgos de mutación posteriores al punto de control con PVC

Se produce un riesgo significativo durante el flujo de trabajo de "checkpoint and resume" si tu Pod usa una Persistent Volume Claim (PVC). Si configuras una carga de trabajo para que se reanude inmediatamente después de un punto de control (con el campo postCheckpoint: resume), la aplicación permanecerá activa y podrá modificar el PVC después del punto de control.

  • Problema de cierre ordenado: Después del ciclo de punto de control y reanudación, cuando borras un Pod, Kubernetes inicia una secuencia de cierre ordenado enviando un indicador SIGTERM al proceso principal del contenedor. Muchas aplicaciones implementan una lógica de cierre ordenado durante la cual pueden activar rutinas de limpieza, borrar o actualizar archivos temporales en el PVC.
  • Falla de restablecimiento: Si estos cambios ocurren en el PVC después de que se toma la instantánea del Pod, el procedimiento de restablecimiento esperará el estado del PVC tal como existía en el momento exacto del punto de control, lo que podría provocar fallas de restablecimiento o inconsistencia de datos.
  • Mitigación recomendada: Si es necesario usar un PVC para la carga de trabajo, no la reanudes después de un punto de control. Usa la configuración postCheckpoint: stop en tu PodSnapshotPolicy. Esta configuración ayuda a garantizar que el proceso no tenga la oportunidad de realizar escrituras auxiliares ni cambios de estado después de que se complete la fase de creación de puntos de control.

Montaje de ConfigMap y enmascaramiento de directorios

Cuando se integran datos de configuración en un contenedor, el método de activación puede afectar la integridad de una instantánea.

Si se une un ConfigMap con un montaje de volumen estándar, Kubernetes trata todo el directorio de destino como un montaje externo. Como las unidades externas se omiten durante las instantáneas, todo el directorio se excluye de la instantánea.

En el siguiente ejemplo, no se capturan los cambios en el directorio /etc/my-app/ en la instantánea porque todo el directorio es un montaje externo:

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 este problema, usa un subPath. Un subPath ayuda a garantizar que solo el archivo de configuración específico se trate como un montaje externo. Esta configuración apunta al archivo exacto, lo que permite que los archivos y la estructura restantes dentro del directorio principal sigan siendo parte del sistema de archivos local del contenedor, que se captura correctamente durante el proceso de creación de puntos de control.

En el siguiente ejemplo, se muestra la configuración de volumeMounts con un subPath:

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

Volúmenes anónimos implícitos

Ciertas imágenes de contenedor definen volúmenes dentro de sus metadatos (a través de la instrucción VOLUME en el Dockerfile). Incluso si la especificación del Pod no define un volumen, Kubernetes crea automáticamente un volumen anónimo para cualquier ruta de acceso definida como un volumen en la imagen base. Por ejemplo, la imagen alpine/git define /git como un volumen implícito.

Estos volúmenes anónimos se tratan como activaciones externas y, al igual que los PVC, no se guardan como puntos de control. Te recomendamos que revises tus imágenes base y te asegures de que los datos críticos no se almacenen en esos volúmenes implícitos.

¿Qué sigue?