Transférer les données

Les transferts de données peuvent avoir lieu entre les éléments suivants :

  1. Revendication de volume persistant (PVC) et stockage d'objets
  2. Stockage d'objets et stockage d'objets (dans GDC)

Le stockage d'objets sur GDC est compatible avec S3 et est appelé type s3 dans les fichiers YAML Kubernetes.

Types de sources et de destinations de données

  1. Stockage d'objets (appelé "s3") : stockage d'objets présent sur GDC
  2. Stockage local (appelé "local") : stockage sur les PVC associés

Copier des données d'un stockage d'objets vers un autre

Assurez-vous de disposer des prérequis suivants :

  • Un point de terminaison S3 avec des autorisations de lecture pour la source et un point de terminaison S3 avec des autorisations d'écriture pour la destination.
  • Si vous ne disposez pas de l'autorisation de créer un bucket avec les identifiants, le transfert échoue si le bucket de destination n'existe pas. Dans ce cas, assurez-vous que le bucket de destination existe.
  • Privilèges permettant de créer des tâches et de créer ou de lire des secrets dans votre cluster ou espace de noms. Consultez l'exemple suivant pour connaître les autorisations.

Configurer le transfert de données

Pour configurer le transfert de données, procédez comme suit :

Créer l'espace de noms de transfert

Créez l'espace de noms dans lequel la tâche de transfert s'exécutera :

apiVersion: v1
kind: Namespace
metadata:
  name: NAMESPACE

Configurer les identifiants

Préparez vos identifiants pour le transfert. Choisissez l'option qui correspond le mieux à votre scénario de transfert.

Transfert de GDC à GDC

Pour un transfert qui s'effectue entièrement dans le même univers GDC, les secrets existent déjà. Notez que cette méthode est strictement réservée aux transferts au sein d'un même univers, et non aux transferts entre différents univers.

  1. Pour obtenir les secrets d'identifiants S3, suivez les instructions pour accorder l'accès au bucket.

  2. Créez un compte de service dans l'espace de noms de destination pour votre tâche de transfert. Ensuite, ajoutez des autorisations pour permettre à ce compte de lire les secrets dans les espaces de noms source et de destination à l'aide de RoleBindings inter-espaces de noms.

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

Transfert de GDC vers un système non-GDC

Pour un transfert impliquant un système externe, vous devez spécifier explicitement les identifiants d'accès.

  1. Créez des identifiants dans l'espace de noms de destination :

    ---
    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. Créez un compte de service utilisé par votre transfert, puis ajoutez des autorisations au compte pour lire et écrire des secrets à l'aide de rôles et de liaisons de rôles. Vous n'avez pas besoin d'ajouter d'autorisations si votre compte de service d'espace de noms par défaut ou votre compte de service personnalisé dispose déjà de ces autorisations.

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

Obtenir des certificats CA

Obtenez les certificats CA pour vos systèmes de stockage d'objets. Vous pouvez obtenir les mêmes certificats auprès de votre AO ou PA en suivant les instructions pour récupérer les groupes de confiance.

---

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.

---

(Facultatif) Créer un LoggingTarget

Créez un LoggingTarget pour afficher les journaux du service de transfert dans 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

Créer la charge de travail de transfert

Vous pouvez exécuter le transfert en tant qu'opération ponctuelle à l'aide d'un Job, ou le planifier pour qu'il s'exécute de manière répétée à l'aide d'un CronJob.

Choisissez la méthode qui correspond le mieux à votre cas d'utilisation :

Créer une tâche ponctuelle

Utilisez cette configuration pour un transfert de données manuel unique.

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

Créer une tâche cron planifiée

Utilisez cette configuration pour synchroniser en permanence votre bucket de destination avec votre bucket source selon une planification fixe.

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

Surveiller votre transfert de données

Une fois que vous avez instancié la tâche, vous pouvez surveiller son état à l'aide de kubectl commandes, telles que kubectl describe. Pour vérifier le transfert, listez les objets dans votre bucket de destination afin de valider le transfert de vos données. L'outil de transfert de données est indépendant de l'emplacement des points de terminaison impliqués dans le transfert.

Exécutez la commande suivante pour vérifier l'état de votre charge de travail :

# 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

La commande précédente vous indique l'état de la tâche.

La tâche invite un pod à transférer les données. Vous pouvez obtenir le nom du pod et consulter les journaux pour voir si des erreurs se sont produites lors du transfert.

Pour afficher les journaux des pods, exécutez la commande suivante :

# 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

Journaux de tâches réussies :

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"

L'affichage des journaux vous permet de voir la vitesse de transfert des données, qui n'est pas la même que la bande passante utilisée, les octets déplacés, le nombre de fichiers en erreur et les fichiers déplacés.

Copier le stockage par blocs vers le stockage d'objets

Assurez-vous de disposer des prérequis suivants :

  • Un point de terminaison S3 avec un ID de clé S3 et une clé d'accès secrète avec au moins des autorisations d'ÉCRITURE sur le bucket dédié vers lequel vous souhaitez transférer des données.
  • Un cluster fonctionnel avec une connectivité au point de terminaison S3.
  • Privilèges permettant de créer des tâches et des secrets dans votre cluster.
  • Pour la réplication du stockage de blocs, un pod avec un PersistentVolumeClaim (PVC) associé que vous souhaitez sauvegarder dans le stockage d'objets, ainsi que des privilèges permettant d'inspecter les tâches et les PVC en cours d'exécution.
  • Pour la réplication du stockage de blocs, une fenêtre pendant laquelle aucune écriture n'a lieu dans le PersistentVolume (PV).
  • Pour la restauration du stockage de blocs à partir d'un point de terminaison de stockage d'objets, des privilèges permettant d'allouer un PV avec une capacité suffisante.

Pour répliquer un PV dans le stockage d'objets, vous devez associer un volume à un pod existant. Pendant la fenêtre de transfert, le pod ne doit effectuer aucune écriture. Pour éviter de dissocier le PV monté de la tâche, le processus de transfert de données fonctionne en exécutant la tâche de transfert sur la même machine que le pod et en utilisant un montage hostPath pour exposer le volume sur le disque. En préparation du transfert, vous devez d'abord trouver le nœud sur lequel le pod s'exécute, ainsi que des métadonnées supplémentaires telles que l'UID du pod et le type de PVC pour référencer le chemin approprié sur le nœud. Vous devez remplacer ces métadonnées dans l'exemple de fichier YAML décrit dans la section suivante.

Collecter des métadonnées

Pour collecter les métadonnées requises pour créer la tâche de transfert de données, procédez comme suit :

  1. Recherchez le nœud qui contient le pod planifié :

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

    Enregistrez le résultat de cette commande en tant que NODE_NAME à utiliser dans le fichier YAML de la tâche de transfert de données.

  2. Recherchez l'UID du pod :

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

    Enregistrez le résultat de cette commande en tant que POD_UID à utiliser dans le fichier YAML de la tâche de transfert de données.

  3. Recherchez le nom du PVC :

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

    Enregistrez le résultat de cette commande en tant que PVC_NAME à utiliser dans le fichier YAML de la tâche de transfert de données.

  4. Recherchez le provisionneur de stockage du PVC :

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

    Enregistrez le résultat de cette commande en tant que PROVISIONER_TYPE à utiliser dans le fichier YAML de la tâche de transfert de données.

Créer des secrets

Pour répliquer un fichier dans le stockage d'objets sur plusieurs clusters, vous devez d'abord instancier les secrets dans votre cluster Kubernetes. Vous devez utiliser des clés correspondantes pour les données secrètes afin que l'outil puisse extraire les identifiants.

Pour effectuer le transfert dans un espace de noms existant, consultez l'exemple suivant de création de secrets dans un espace de noms 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

Créer la tâche

Avec les données que vous avez collectées dans la section précédente, créez une tâche avec l'outil de transfert de données. La tâche de transfert de données comporte un montage hostPath qui référence le chemin d'accès au PV d'intérêt et un nodeSelector pour le nœud concerné.

Voici un exemple de tâche de transfert de données :

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

Comme pour le transfert de données S3, vous devez créer un secret contenant les clés d'accès pour le point de terminaison de destination dans le cluster Kubernetes, et la tâche de transfert de données doit s'exécuter avec un compte de service disposant des privilèges suffisants pour lire le secret à partir du serveur d'API. Surveillez l'état du transfert à l'aide des commandes kubectl standards fonctionnant sur la tâche.

Tenez compte des points suivants lorsque vous transférez un stockage de blocs vers un stockage d'objets :

  • Par défaut, les liens symboliques suivent et se répliquent dans le stockage d'objets, mais une copie profonde plutôt qu'une copie superficielle est effectuée. Lors de la restauration, les liens symboliques sont détruits.
  • Comme pour la réplication du stockage d'objets, le clonage dans un sous-répertoire du bucket est destructif. Assurez-vous que le bucket est disponible exclusivement pour votre volume.

Restaurer des données du stockage d'objets vers le stockage de blocs

Allouer un PV

Pour restaurer un stockage par blocs à partir d'un point de terminaison de stockage d'objets, procédez comme suit :

  1. Allouez un volume persistant à cibler lors de la restauration. Utilisez un PVC pour allouer le volume, comme illustré dans l'exemple suivant :

    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. Vérifiez l'état du PVC :

    kubectl get pvc restore-pvc -n restore-ns
    

    Une fois que le PVC est à l'état Bound, il est prêt à être utilisé dans le pod qui le réhydrate.

  3. Si un ensemble avec état finit par utiliser le PV, vous devez faire correspondre les PVC StatefulSet rendus. Les pods produits par StatefulSet utilisent les volumes hydratés. L'exemple suivant montre des modèles de revendication de volume dans un StatefulSet nommé ss.

      volumeClaimTemplates:
      - metadata:
          name: pvc-name
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: "default"
          resources:
            requests:
              storage: 1Gi
    
  4. Préallouez des PVC avec des noms tels que ss-pvc-name-0 et ss-pvc-name-1 pour vous assurer que les pods résultants utilisent les volumes préalloués.

Hydrater le PV

Une fois le PVC lié à un PV, démarrez la tâche pour remplir le 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

Une fois la tâche terminée, les données du bucket de stockage d'objets remplissent le volume. Un pod distinct peut utiliser les données en utilisant les mêmes mécanismes standards pour monter un volume.