Transferir datos

Las transferencias de datos pueden ocurrir entre los siguientes elementos:

  1. PersistentVolumeClaim (PVC) y almacenamiento de objetos
  2. Almacenamiento de objetos y almacenamiento de objetos (dentro de GDC)

El almacenamiento de objetos en GDC es compatible con S3 y se conoce como tipo s3 en los archivos YAML de Kubernetes.

Tipos de fuentes y destinos de datos

  1. Almacenamiento de objetos (conocido como "s3"): Almacenamiento de objetos presente en GDC
  2. Almacenamiento local (conocido como "local"): Almacenamiento en PVC adjuntos

Copia de almacenamiento de objetos a almacenamiento de objetos

Asegúrate de cumplir con los siguientes requisitos:

  • Un extremo de S3 con permisos de lectura para la fuente y un extremo de S3 con permisos de escritura para el destino
  • Si no tienes permiso para crear buckets con las credenciales, la transferencia fallará si el bucket de destino no existe. Asegúrate de que el bucket de destino exista si ese es el caso.
  • Privilegios para crear trabajos y crear o leer Secrets dentro de tu clúster o espacio de nombres Consulta el siguiente ejemplo para obtener permisos.

Configura la transferencia de datos

Para configurar la transferencia de datos, completa los siguientes pasos:

Crea el espacio de nombres de transferencia

Crea el espacio de nombres en el que se ejecutará el trabajo de transferencia:

apiVersion: v1
kind: Namespace
metadata:
  name: NAMESPACE

Configura las credenciales

Prepara tus credenciales para la transferencia. Sigue la opción que mejor se adapte a tu situación de transferencia.

Transferencia de GDC a GDC

Para una transferencia que se realiza por completo dentro del mismo universo de GDC, los secretos ya existen. Ten en cuenta que este método es estrictamente para transferencias dentro de un solo universo, no para transferencias entre diferentes universos.

  1. Para obtener los Secrets de credenciales de S3, sigue las instrucciones para otorgar acceso al bucket.

  2. Crea una cuenta de servicio (SA) en el espacio de nombres de destino para tu trabajo de transferencia. Luego, agrega permisos para permitir que esta cuenta lea Secrets en los espacios de nombres de origen y destino con RoleBindings entre espacios de nombres.

    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: transfer-service-account
      namespace: DESTINATION_NAMESPACE
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: read-secrets-role
      namespace: SOURCE_NAMESPACE
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-source-secrets-rolebinding
      namespace: SOURCE_NAMESPACE
    subjects:
    - kind: ServiceAccount
      name: transfer-service-account
      namespace: DESTINATION_NAMESPACE
    roleRef:
      kind: Role
      name: read-secrets-role
      apiGroup: rbac.authorization.k8s.io
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: read-secrets-role
      namespace: DESTINATION_NAMESPACE
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-dest-secrets-rolebinding
      namespace: DESTINATION_NAMESPACE
    subjects:
    - kind: ServiceAccount
      name: transfer-service-account
      namespace: DESTINATION_NAMESPACE
    roleRef:
      kind: Role
      name: read-secrets-role
      apiGroup: rbac.authorization.k8s.io
    ---
    

Transferencia de GDC a no GDC

Para una transferencia que involucra un sistema externo, debes especificar las credenciales de acceso de forma explícita.

  1. Crea credenciales en el espacio de nombres de destino:

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: src-secret
      namespace: NAMESPACE
    data:
      access-key-id: NkFDTUg3WDBCVDlQMVpZMU5MWjU= # base 64 encoded version of key
      access-key: VkRkeWJsbFgzb2FZanMvOVpnSi83SU5YUjk3Y0Q2TUdxZ2d4Q3dpdw== # base 64 encoded version of secret key
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: dst-secret
      namespace: NAMESPACE
    data:
      access-key-id: NkFDTUg3WDBCVDlQMVpZMU5MWjU= # base 64 encoded version of key
      access-key: VkRkeWJsbFgzb2FZanMvOVpnSi83SU5YUjk3Y0Q2TUdxZ2d4Q3dpdw== # base 64 encoded version of secret key
    ---
    
  2. Crea una cuenta de servicio (SA) que use tu transferencia y, luego, agrega permisos a la cuenta para leer y escribir secretos con roles y vinculaciones de roles. No necesitas agregar permisos si tu SA de espacio de nombres predeterminado o SA personalizado ya tiene estos permisos.

    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: transfer-service-account
      namespace: NAMESPACE
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: read-secrets-role
      namespace: NAMESPACE
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: read-secrets-rolebinding
      namespace: NAMESPACE
    subjects:
    - kind: ServiceAccount
      name: transfer-service-account
      namespace: NAMESPACE
    roleRef:
      kind: Role
      name: read-secrets-role
      apiGroup: rbac.authorization.k8s.io
    ---
    

Obtén certificados de CA

Obtén los certificados de CA para tus sistemas de almacenamiento de objetos. Puedes obtener los mismos certificados de tu AO o PA si sigues las instrucciones para recuperar paquetes de confianza.

---

apiVersion: v1
kind: Secret
metadata:
  name: src-cert
  namespace: NAMESPACE
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBekNDQWV1Z0F3SUJBZ0lSQUpHM2psOFZhTU85a1FteGdXUFl3N3d3RFFZSktvWklodmNOQVFFTEJRQXcKR3pFWk1CY0dBMVVFQXhNUVltOXZkSE4wY21Gd0xYZGxZaTFqWVRBZUZ3MHlNekF5TVRVd01USXlNakZhRncweQpNekExTVRZd01USXlNakZhTUJzeEdUQVhCZ05WQkFNVEVHSnZiM1J6ZEhKaGNDMTNaV0l0WTJFd2dnRWlNQTBHCkNTcUdTSWI== # base 64 encoded version of certificate

---

apiVersion: v1
kind: Secret
metadata:
  name: dst-cert
  namespace: NAMESPACE
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBekNDQWV1Z0F3SUJBZ0lSQUtoaEJXWWo3VGZlUUZWUWo0U0RpckV3RFFZSktvWklodmNOQVFFTEJRQXcKR3pFWk1CY0dBMVVFQXhNUVltOXZkSE4wY21Gd0xYZGxZaTFqWVRBZUZ3MHlNekF6TURZeU16TTROVEJhRncweQpNekEyTURReU16TTROVEJhTUJzeEdUQVhCZ05WQkFNVEVHSnZiM1J6ZEhKaGNDMTNaV0l0WTJFd2dnRWlNQTBHCkNTcUdTSWIzRFFF== # base 64 encoded version of certificate. Can be same OR different than source certificate.

---

Crea un LoggingTarget (opcional)

Crea un LoggingTarget para ver los registros del servicio de transferencia en Loki.

apiVersion: logging.gdc.goog/v1
kind: LoggingTarget
metadata:
  namespace: NAMESPACE # Same namespace as your transfer job
  name: logtarg1
spec:
  # Choose matching pattern that identifies pods for this job
  # Optional
  # Relationship between different selectors: AND
  selector:

    # Choose pod name prefix(es) to consider for this job
    # Observability platform will scrape all pods
    # where names start with specified prefix(es)
    # Should contain [a-z0-9-] characters only
    # Relationship between different list elements: OR
    matchPodNames:
      - transfer-job # Choose the prefix here that matches your transfer job name
  serviceName: transfer-service

Crea la carga de trabajo de transferencia

Puedes ejecutar la transferencia como una operación única con un Job o programarla para que se ejecute de forma repetida con un CronJob.

Elige el método que mejor se adapte a tu caso de uso:

Crea un trabajo único

Usa esta configuración para una sola transferencia de datos manual.

---
apiVersion: batch/v1
kind: Job
metadata:
  name: transfer-job
  namespace: NAMESPACE
spec:
  template:
    spec:
      serviceAccountName: transfer-service-account # The service account created in the previous step
      containers:
        - name: storage-transfer-pod
          image: gcr.io/private-cloud-staging/storage-transfer:latest
          imagePullPolicy: Always
          command:
            - /storage-transfer
          args:
            # The S3 endpoints for your source and destination
            - '--src_endpoint=SRC_ENDPOINT'
            - '--dst_endpoint=DST_ENDPOINT'
            # The Fully Qualified Names (FQN) of the buckets
            - '--src_path=SRC_BUCKET_FQN/'
            - '--dst_path=DST_BUCKET_FQN/'
            # Cross-namespace mapping: point directly to the live credentials using NAMESPACE/SECRET_NAME
            - '--src_credentials=NAMESPACE/SRC_SECRET_NAME'
            - '--dst_credentials=NAMESPACE/DST_SECRET_NAME'
            # Point to the CA certificate Secret created in the destination namespace
            - '--src_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
            - '--dst_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
            - '--src_type=s3'
            - '--dst_type=s3'
            - '--bandwidth_limit=BANDWIDTH_LIMIT' # Optional. Examples: '10K', '100M', '1G'
      restartPolicy: OnFailure
---

Crea un CronJob programado

Usa esta configuración para mantener tu bucket de destino sincronizado de forma continua con tu bucket de origen en un programa fijo.

---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: transfer-cronjob
  namespace: NAMESPACE
spec:
  schedule: "0 * * * *"  # Runs at the top of every hour. Adjust the cron schedule as needed.
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 5
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: transfer-service-account # The service account created in the previous step
          containers:
            - name: storage-transfer-pod
              image: gcr.io/private-cloud-staging/storage-transfer:latest
              imagePullPolicy: Always
              command:
                - /storage-transfer
              args:
                # The S3 endpoints for your source and destination
                - '--src_endpoint=SRC_ENDPOINT'
                - '--dst_endpoint=DST_ENDPOINT'
                # The Fully Qualified Names (FQN) of the buckets
                - '--src_path=SRC_BUCKET_FQN/'
                - '--dst_path=DST_BUCKET_FQN/'
                # Cross-namespace mapping: point directly to the live credentials using NAMESPACE/SECRET_NAME
                - '--src_credentials=NAMESPACE/SRC_SECRET_NAME'
                - '--dst_credentials=NAMESPACE/DST_SECRET_NAME'
                # Point to the CA certificate Secret created in the destination namespace
                - '--src_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
                - '--dst_ca_certificate_reference=NAMESPACE/CA_CERT_SECRET'
                - '--src_type=s3'
                - '--dst_type=s3'
                - '--bandwidth_limit=BANDWIDTH_LIMIT' # Optional. Examples: '10K', '100M', '1G'
          restartPolicy: OnFailure
---

Supervisa tu transferencia de datos

Después de crear una instancia del trabajo, puedes supervisar su estado con kubectl comandos, como kubectl describe. Para verificar la transferencia, haz una lista de los objetos dentro de tu bucket de destino para validar que se transfirieron tus datos. La herramienta de transferencia de datos es independiente de la ubicación de los extremos involucrados en la transferencia.

Ejecuta el siguiente comando para verificar el estado de tu carga de trabajo:

# If you created a one-time Job:
kubectl describe job transfer-job -n NAMESPACE

# If you created a scheduled CronJob:
kubectl describe cronjob transfer-cronjob -n NAMESPACE

El comando anterior te indica el estado del trabajo.

El trabajo solicita a un pod que transfiera los datos. Puedes obtener el nombre del pod y consultar los registros para ver si hay errores durante la transferencia.

Para ver los registros del pod, ejecuta lo siguiente:

# 1. First, find the exact pod name generated by your Job
kubectl get pods -n NAMESPACE | grep transfer

# 2. Then, view the logs for that specific pod
kubectl logs POD_NAME -n NAMESPACE

Registros de trabajos realizados correctamente:

DEBUG : Starting main for transfer
I0607 21:34:39.183106       1 transfer.go:103]  "msg"="Starting transfer "  "destination"="sample-bucket" "source"="/data"
2023/06/07 21:34:39 NOTICE: Bandwidth limit set to {100Mi 100Mi}
I0607 21:34:49.238901       1 transfer.go:305]  "msg"="Job finished polling "  "Finished"=true "Number of Attempts"=2 "Success"=true
I0607 21:34:49.239675       1 transfer.go:153]  "msg"="Transfer completed."  "AvgSpeed"="10 KB/s" "Bytes Moved"="10.0 kB" "Errors"=0 "Files Moved"=10 "FilesComparedAtSourceAndDest"=3 "Time since beginning of transfer"="1.0s"

Ver los registros te permite ver la velocidad de transferencia de datos, que no es la misma que el ancho de banda usado, los bytes movidos, la cantidad de archivos con errores y los archivos movidos.

Copia el almacenamiento en bloque al almacenamiento de objetos

Asegúrate de cumplir con los siguientes requisitos:

  • Un extremo de S3 con un ID de clave de S3 y una clave de acceso secreta con al menos permisos de ESCRITURA para el bucket dedicado al que deseas transferir datos
  • Un clúster en funcionamiento con conectividad al extremo de S3
  • Privilegios para crear trabajos y Secrets dentro de tu clúster
  • Para la replicación del almacenamiento en bloque, un Pod con un PersistentVolumeClaim (PVC) adjunto del que deseas crear una copia de seguridad en el almacenamiento de objetos y privilegios para inspeccionar los trabajos y PVC en ejecución
  • Para la replicación del almacenamiento en bloque, un período durante el cual no se realizan escrituras en el PersistentVolume (PV).
  • Para la restauración del almacenamiento en bloque desde un extremo de almacenamiento de objetos, privilegios para asignar un PV con capacidad suficiente.

Para replicar un PV en el almacenamiento de objetos, debes adjuntar un volumen a un pod existente. Durante el período de la transferencia, el pod no debe realizar ninguna escritura. Para evitar separar el PV activado del trabajo, el proceso de transferencia de datos funciona ejecutando el trabajo de transferencia en la misma máquina que el pod y usando una activación de hostPath para exponer el volumen en el disco. Como preparación para la transferencia, primero debes encontrar el nodo en el que se ejecuta el pod y metadatos adicionales, como el UID del pod y el tipo de PVC, para hacer referencia a la ruta adecuada en el nodo. Debes sustituir estos metadatos en el archivo YAML de muestra que se describe en la siguiente sección.

Recopila metadatos

Para recopilar los metadatos necesarios para crear el trabajo de transferencia de datos, sigue estos pasos:

  1. Busca el nodo que tiene el pod programado:

    kubectl get pod POD_NAME -o jsonpath='{.spec.nodeName}'
    

    Registra el resultado de este comando como NODE_NAME para usarlo en el archivo YAML del trabajo de transferencia de datos.

  2. Busca el UID del pod:

    kubectl get pod POD_NAME -o 'jsonpath={.metadata.uid}'
    

    Registra el resultado de este comando como el POD_UID para usar en el archivo YAML del trabajo de transferencia de datos.

  3. Busca el nombre del PVC:

    kubectl get pvc www-web-0 -o 'jsonpath={.spec.volumeName}'
    

    Registra el resultado de este comando como PVC_NAME para usarlo en el archivo YAML del trabajo de transferencia de datos.

  4. Busca el aprovisionador de almacenamiento de PVC:

    kubectl get pvc www-web-0 -o jsonpath='{.metadata.annotations.volume\.v1\.kubernetes\.io\/storage-provisioner}'
    

    Registra el resultado de este comando como el PROVISIONER_TYPE para usarlo en el archivo YAML del trabajo de transferencia de datos.

Crea Secrets

Para replicar archivos en el almacenamiento de objetos en todos los clústeres, primero debes crear instancias de los secretos dentro de tu clúster de Kubernetes. Debes usar claves coincidentes para los datos de Secret para que la herramienta extraiga las credenciales.

Para realizar la transferencia en un espacio de nombres existente, consulta el siguiente ejemplo de creación de Secrets en un espacio de nombres transfer:

apiVersion: v1
kind: Secret
metadata:
  name: src-secret
  namespace: transfer
data:
  access-key-id: c3JjLWtleQ== # echo -n src-key| base64 -w0
  access-key: c3JjLXNlY3JldA== # echo -n src-secret| base64 -w0
---
apiVersion: v1
kind: Secret
metadata:
  name: dst-secret
  namespace: transfer
data:
  access-key-id: ZHN0LWtleQ== # echo -n dst-key| base64 -w0
  access-key: ZHN0LXNlY3JldA== # echo -n dst-secret| base64 -w0

Crea el trabajo

Con los datos que recopilaste en la sección anterior, crea un trabajo con la herramienta de transferencia de datos. El trabajo de transferencia de datos tiene una activación hostPath que hace referencia a la ruta de acceso del PV de interés y un nodeSelector para el nodo pertinente.

El siguiente es un ejemplo de un trabajo de transferencia de datos:

apiVersion: batch/v1
kind: Job
metadata:
  name: transfer-job
  namespace: transfer
spec:
  template:
    spec:
      nodeSelector: NODE_NAME
      serviceAccountName: data-transfer-sa
      containers:
      - name: storage-transfer-pod
        image: storage-transfer
        command:
        - /storage-transfer
        args:
        - --dst_endpoint=https://your-dst-endpoint.com
        - --src_path=/pvc-data
        - --dst_path=transfer-dst-bucket
        - --dst_credentials=transfer/dst-secret
        - --src_type=local
        - --dst_type=s3
      volumeMounts:
      - mountPath: /pvc-data
        name: pvc-volume
      volumes:
      - name: pvc-volume
      hostPath:
        path: /var/lib/kubelet/pods/POD_UID/volumes/PROVISIONER_TYPE/PVC_NAME
      restartPolicy: Never

Al igual que con la transferencia de datos de S3, debes crear un Secret que contenga las claves de acceso para el extremo de destino en el clúster de Kubernetes, y el trabajo de transferencia de datos debe ejecutarse con una cuenta de servicio con privilegios adecuados para leer el Secret desde el servidor de la API. Supervisa el estado de la transferencia con comandos kubectl estándar que operan en el trabajo.

Ten en cuenta los siguientes detalles cuando transfieras almacenamiento en bloque al almacenamiento de objetos:

  • De forma predeterminada, los vínculos simbólicos siguen y se replican en el almacenamiento de objetos, pero se realiza una copia profunda en lugar de superficial. Cuando se restablece, destruye los vínculos simbólicos.
  • Al igual que con la replicación del almacenamiento de objetos, la clonación en un subdirectorio del bucket es destructiva. Asegúrate de que el bucket esté disponible exclusivamente para tu volumen.

Restablece del almacenamiento de objetos al almacenamiento en bloque

Asigna un PV

Para restablecer el almacenamiento en bloque desde un extremo de almacenamiento de objetos, sigue estos pasos:

  1. Asigna un volumen persistente al destino en el restablecimiento. Usa un PVC para asignar el volumen, como se muestra en el siguiente ejemplo:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: restore-pvc
      namespace: restore-ns
    spec:
      storageClassName: "default"
      accessModes:
    ReadWriteOnce
      resources:
        requests:
          storage: 1Gi # Need sufficient capacity for full restoration.
    
  2. Verifica el estado del PVC:

    kubectl get pvc restore-pvc -n restore-ns
    

    Una vez que el PVC está en estado Bound, está listo para consumirse dentro del pod que lo rehidrata.

  3. Si un conjunto de estado consume el PV, debes hacer coincidir los PVC de StatefulSet renderizados. Los pods que produce StatefulSet consumen los volúmenes hidratados. En el siguiente ejemplo, se muestran las plantillas de reclamo de volumen en un StatefulSet llamado ss.

      volumeClaimTemplates:
      - metadata:
          name: pvc-name
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: "default"
          resources:
            requests:
              storage: 1Gi
    
  4. Asigna previamente PVC con nombres como ss-pvc-name-0 y ss-pvc-name-1 para asegurarte de que los pods resultantes consuman los volúmenes asignados previamente.

Hidrata el PV

Después de que el PVC esté vinculado a un PV, inicia el trabajo para propagar el PV:

apiVersion: batch/v1
kind: Job
metadata:
  name: transfer-job
  namespace: transfer
spec:
  template:
    spec:
      serviceAccountName: data-transfer-sa
      volumes:
      - name: data-transfer-restore-volume
        persistentVolumeClaim:
          claimName: restore-pvc
      containers:
      - name: storage-transfer-pod
        image: storage-transfer
        command:
        - /storage-transfer
        args:
        - --src_endpoint=https://your-src-endpoint.com
        - --src_path=/your-src-bucket
        - --src_credentials=transfer/src-secret
        - --dst_path=/restore-pv-mnt-path
        - --src_type=s3
        - --dst_type=local
      volumeMounts:
      - mountPath: /restore-pv-mnt-path
        name: data-transfer-restore-volume

Una vez que el trabajo termina de ejecutarse, los datos del bucket de almacenamiento de objetos propagan el volumen. Un pod independiente puede consumir los datos con los mismos mecanismos estándar para activar un volumen.