# Configurer Amazon EKS avec S3

Avant de déployer Dynamic Engine et ses environnements, configurez un cluster Amazon EKS avec Amazon S3 comme back-end de stockage partagé.

## Avant de commencer

* Un compte AWS avec les autorisations IAM requises. Pour la liste complète des conditions préalables requises, consultez [Configurer Amazon EKS pour un déploiement Dynamic Engine](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/deploying-dynamic-engine-on-aws-eks "Dynamic Engine peut être déployé sur Amazon Elastic Kubernetes Service (EKS) avec des systèmes de stockage natifs EKS.").

## Pourquoi et quand exécuter cette tâche

Note InformationsImportant : Cette procédure couvre un modèle de déploiement EKS qui utilise le provisioning statique sauvegardé dans un stockage. Pour Amazon EKS Auto Mode, appliquez le bundle en mode géré dans [Modes de fonctionnement Kubernetes gérés](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/prerequisites-to-use-dynamic-engines).

Cette procédure crée un nouveau cluster EKS dans un cloud privé virtuel dédié (VPC Amazon), installe le pilote S3 CSI (Container Storage Interface) comme add-on EKS géré par AWS, crée un compartiment S3 pour sauvegarder les volumes persistants et provisionne des PersistentVolumes et des PersistentVolumeClaims statiques pour Dynamic Engine et ses environnements.

* Contrairement à la configuration d'Amazon EFS, S3 utilise le provisioning statique : il n'existe pas de ressource StorageClass. Vous devez créer des PersistentVolumes manuellement et les lier à des revendications PersistentVolumeClaims nommées avant de déployer Dynamic Engine.

## Procédure

1. Définissez des variables d'environnement pour votre déploiement Amazon EKS et S3 :
   ```
   export AWS_REGION=<your-aws-region>
   export EKS_CLUSTER_NAME=<your-eks-cluster-name>
   export S3_BUCKET_NAME=<your-s3-bucket-name>
   ```
2. Créez le compartiment S3 pour sauvegarder les volumes persistants. Sélectionnez le type de compartiment correspondant à vos besoins.

   Le compartiment à créer et le VPC Amazon doivent se trouver dans la même région AWS.
   * Compartiment à usage général : Utilisez un compartiment S3 standard disponible dans toutes les régions AWS . Un compartiment sert tous les volumes Dynamic Engine à l'aide de préfixes de chemin d'accès.

     ```
     cat <<EOF > $S3_BUCKET_NAME-classic-input.yaml
     Bucket: $S3_BUCKET_NAME
     CreateBucketConfiguration:
       LocationConstraint: ${AWS_REGION}
       Tags:
         - Key: owner
           Value: dyn-engine
         - Key: creator
           Value: ${USER}
         - Key: eks/cluster
           Value: ${EKS_CLUSTER_NAME}
     EOF

     S3_BUCKET_ARN=$(aws s3api create-bucket \
       --cli-input-yaml file://$S3_BUCKET_NAME-classic-input.yaml \
       --region $AWS_REGION \
       --output text \
       --query BucketArn)

     echo "S3 bucket created: $S3_BUCKET_ARN"
     ```

     Les trois blocs génèrent un fichier de configuration pour un nouveau compartiment S3 avec des balises de titularité, créent le compartiment via AWS CLI et impriment un message de confirmation avec l'identificateur unique du compartiment.

   * Compartiment de répertoires : Utilisez un compartiment de répertoires (également appelé compartiment S3 Express One Zone) pour réduire la latence au sein d'une seule Zone de disponibilité. Les compartiments de répertoires nécessitent un format de nommage spécifique : bucket-base-name--zone-id--x-s3, où zone-id est un ID de Zone de disponibilité ou de Zone locale. Ce type de compartiments est disponible uniquement dans des régions AWS et des Zones de disponibilité spécifiques.

     Note InformationsRemarque : Définissez AWS\_AZ\_ZONE\_ID sur l'ID de zone de votre Zone de disponibilité ciblz avant d'exécuter ce script. Par exemple, euw1-az1 correspond à la région eu-west-1.

     ```
     AWS_AZ_ZONE_ID=<your-az-zone-id>
     S3_BUCKET_NAME="${EKS_CLUSTER_NAME}--$AWS_AZ_ZONE_ID--x-s3"

     cat <<EOF > $S3_BUCKET_NAME-directory-input.yaml
     Bucket: $S3_BUCKET_NAME
     CreateBucketConfiguration:
       Location:
         Type: AvailabilityZone
         Name: $AWS_AZ_ZONE_ID
       Bucket:
         DataRedundancy: SingleAvailabilityZone
         Type: Directory
       Tags:
         - Key: owner
           Value: dyn-engine
         - Key: creator
           Value: ${USER}
         - Key: eks/cluster
           Value: ${EKS_CLUSTER_NAME}
     EOF

     S3_BUCKET_ARN=$(aws s3api create-bucket \
       --cli-input-yaml file://$S3_BUCKET_NAME-directory-input.yaml \
       --region $AWS_REGION \
       --output text \
       --query BucketArn)

     echo "S3 bucket created: $S3_BUCKET_ARN"
     ```

     Ces quatre blocs configurent et créent un compartiment (répertoire) S3 Express One Zone accroché à une Zone de disponibilité spécifique via les conventions de nommage et la configuration requises par AWS, puis impriment un message de confirmation.
3. Créez le fichier de configuration du cluster EKS.

   Les autorisations IAM varient selon qu'il s'agit de compartiments à usage général ou de compartiments de répertoires. Utilisez la configuration correspondant au type de compartiment que vous avez créé à l'étape précédente :
   * Compartiment à usage général : Accordez s3:ListBucket, s3:GetObject, s3:PutObject et s3:DeleteObject sur le compartiment ses objets :

     ```
     cat <<EOF > eks-config.yaml
     apiVersion: eksctl.io/v1alpha5
     kind: ClusterConfig

     metadata:
       name: ${EKS_CLUSTER_NAME}
       region: ${AWS_REGION}
       version: "1.34"

     addonsConfig:
       autoApplyPodIdentityAssociations: true

     addons:
       - name: eks-pod-identity-agent
       - name: aws-mountpoint-s3-csi-driver
         namespaceConfig:
           namespace: aws-mountpoint-s3
         podIdentityAssociations:
           - namespace: aws-mountpoint-s3
             serviceAccountName: s3-csi-driver-sa
             permissionPolicy:
               Statement:
                 - Effect: Allow
                   Action:
                     - s3:ListBucket
                   Resource: $S3_BUCKET_ARN
                 - Effect: Allow
                   Action:
                     - s3:GetObject
                     - s3:PutObject
                     - s3:DeleteObject
                   Resource: "$S3_BUCKET_ARN/*"

     vpc:
       cidr: 10.10.0.0/16
       autoAllocateIPv6: false
       hostnameType: resource-name
       clusterEndpoints:
         publicAccess: true
         privateAccess: true
       nat:
         gateway: HighlyAvailable

     managedNodeGroups:
       - name: ng-amd64
         amiFamily: AmazonLinux2023 # (default) or Bottlerocket
         minSize: 2
         maxSize: 4
         desiredCapacity: 2
         instanceSelector:
           vCPUs: 4
           memory: 16GiB
           cpuArchitecture: amd64
         privateNetworking: true

     EOF
     ```

   * Compartiment de répertoires : Accordez s3express:CreateSession sur le compartiment (autorisation basée sur la session S3 Express One Zone) :

     ```
     cat <<EOF > eks-config.yaml
     apiVersion: eksctl.io/v1alpha5
     kind: ClusterConfig

     metadata:
       name: ${EKS_CLUSTER_NAME}
       region: ${AWS_REGION}
       version: "1.34"

     addonsConfig:
       autoApplyPodIdentityAssociations: true

     addons:
       - name: eks-pod-identity-agent
       - name: aws-mountpoint-s3-csi-driver
         namespaceConfig:
           namespace: aws-mountpoint-s3
         podIdentityAssociations:
           - namespace: aws-mountpoint-s3
             serviceAccountName: s3-csi-driver-sa
             permissionPolicy:
               Statement:
                 - Effect: Allow
                   Action:
                     - s3express:CreateSession
                   Resource: $S3_BUCKET_ARN

     vpc:
       cidr: 10.10.0.0/16
       autoAllocateIPv6: false
       hostnameType: resource-name
       clusterEndpoints:
         publicAccess: true
         privateAccess: true
       nat:
         gateway: HighlyAvailable

     managedNodeGroups:
       - name: ng-amd64
         amiFamily: AmazonLinux2023 # (default) or Bottlerocket
         minSize: 2
         maxSize: 4
         desiredCapacity: 2
         instanceSelector:
           vCPUs: 4
           memory: 16GiB
           cpuArchitecture: amd64
         privateNetworking: true

     EOF
     ```

   Note InformationsRemarque : Les notes de configuration suivantes s'appliquent aux variantes de compartiment à usage général et de compartiment de répertoires. La seule différence entre elles réside dans la politique d'autorisations IAM accordée au pilote S3 CSI.

   Cette configuration :
   * Définit la version de Kubernetes sur 1.34. Il s'agit de la version d'exemple utilisée dans cette procédure. Mettez-la à jour en fonction de la version de votre cluster cible. Pour les versions supportées, consultez [Prérequis à l'utilisation de Dynamic Engine](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/prerequisites-to-use-dynamic-engines "Avant de déployer Dynamic Engine, vérifiez les autorisations d'accès, la compatibilité Kubernetes et les conditions du mode de déploiement, y compris les modes Kubernetes gérés.").
   * Installe l'add-on aws-mountpoint-s3-csi-driver dans l'espace de noms aws-mountpoint-s3 avec les autorisations IAM automatiquement configurées via les associations d'identités de pods. Cela accorde au pilote S3 CSI les autorisations dont il a besoin pour monter des objets S3 sous forme de volumes sans identifiants codés en dur. Contrairement à EFS, qui utilise une politique gérée par EKS, le pilote S3 CSI nécessite une politique IAM explicite dédiée à l'ARN de compartiment S3 spécifique ($S3\_BUCKET\_ARN). La politique est automatiquement liée à l'add-on par eksctl ; aucune étape AWS CLI supplémentaire n'est nécessaire.
   * Crée un VPC et place tous les nœuds dans des sous-réseaux privés (privateNetworking: true). Les nœuds atteignent Internet uniquement via des passerelles NAT. L'endpoint du cluster reste accessible depuis votre machine locale et au sein du VPC.
   * Provisionne des nœuds dimensionnés pour les workloads Dynamic Engine. Chaque nœud a 4 vCPU et une RAM de 16 GiB. Le groupe de nœuds comprend entre 2 et 4 nœuds (minSize: 2, maxSize: 4). L'architecture AMD64 (cpuArchitecture: amd64) est requise, car les images du conteneur Dynamic Engine sont créées pour AMD64 uniquement.
4. Créez le cluster EKS, liez votre kubectl local au cluster et vérifiez l'accès :
   ```
   eksctl create cluster -f eks-config.yaml
   aws eks update-kubeconfig --region "$AWS_REGION" --name "$EKS_CLUSTER_NAME"
   kubectl get nodes
   ```

   Attendez que tous les nœuds aient atteint le statut Ready (Prêt) avant de poursuivre.
5. Définissez les variables d'environnement de l'espace de noms de l'environnement Dynamic Engine et créez les trois PersistentVolumes et PersistentVolumeClaims à utiliser par les services Dynamic Engine ainsi que vos tâches Talend Management Console :
   ```
   ENV_ID=67f7d562ffd7c3525a902542
   DYNAMIC_ENGINE_ENV_NAMESPACE=qlik-processing-env-$ENV_ID
   # Ensure the target namespace exists before creating PVs/PVCs
   kubectl get namespace "$DYNAMIC_ENGINE_ENV_NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$DYNAMIC_ENGINE_ENV_NAMESPACE"
   declare -a pvcs=("archive" "job-data" "custom-resources")

   for pvc in "${pvcs[@]}"
   do
     echo "Creating PV/PVC for $pvc"
   cat <<EOF | kubectl apply -f -
   ---
   apiVersion: v1
   kind: PersistentVolume
   metadata:
     name: $pvc
   spec:
     capacity:
       storage: 1200Gi # Ignored for S3 volumes but required by Kubernetes API
     accessModes:
       - ReadWriteMany # Supported options: ReadWriteMany / ReadOnlyMany
     storageClassName: "" # Required for static provisioning
     claimRef: # To ensure no other PVCs can claim this PV
       namespace: $DYNAMIC_ENGINE_ENV_NAMESPACE # Namespace is required even though it's in "default" namespace.
       name: $pvc # Name of your PVC
     mountOptions:
       - allow-delete
       - allow-overwrite
       - region $AWS_REGION
       - prefix $pvc/
     csi:
       driver: s3.csi.aws.com # Required
       volumeHandle: $pvc # Must be unique
       volumeAttributes:
         bucketName: $S3_BUCKET_NAME
   ---
   apiVersion: v1
   kind: PersistentVolumeClaim
   metadata:
     name: $pvc
     namespace: $DYNAMIC_ENGINE_ENV_NAMESPACE
   spec:
     accessModes:
       - ReadWriteMany # Supported options: ReadWriteMany / ReadOnlyMany
     storageClassName: "" # Required for static provisioning
     resources:
       requests:
         storage: 1200Gi # Ignored, required
     volumeName: $pvc # Name of your PV
   EOF
   ```
   * storageClassName: "" : doit être vide pour un provisioning statique.
   * claimRef : lie ce PersistentVolume exclusivement à la revendication PersistentVolumeClaim nommée dans l'espace de noms spécifié. Nécessaire pour prévenir toute revendication indésirable de la part d'autres workloads.
   * mountOptions: allow-delete et allow-overwrite. Cela permet d'écrire des opérations sur des volumes sauvegardés par S3. Sans ces indicateurs, les pods peuvent monter le volume, mais les écritures échoueront.
   * prefix: $pvc/ : détermine le périmètre de chaque volume en fonction d'un préfixe de chemin d'accès distinct au sein du compartiment S3 partagé, isolant les données pour chaque volume.
   * volumeHandle : doit être unique pour tous les PersistentVolumes du cluster.
6. Créez un pod test qui monte l'ensemble des trois revendications PersistentVolumeClaims :
   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: v1
   kind: Pod
   metadata:
     name: test-pod-pvc
     namespace: $DYNAMIC_ENGINE_ENV_NAMESPACE
   spec:
     securityContext:
       fsGroup: 61000
       runAsUser: 61000
       runAsGroup: 61000
       runAsNonRoot: true
     containers:
       - name: app
         image: ghcr.io/talend/kube-base:5.3.0
         command: ["cat"]
         tty: true
         volumeMounts:
           - name: archive
             mountPath: /opt/talend/archive
           - name: job-data
             mountPath: /opt/talend/data
           - name: custom-resources
             mountPath: /opt/talend/custom-resources
     volumes:
       - name: archive
         persistentVolumeClaim:
           claimName: archive
       - name: job-data
         persistentVolumeClaim:
           claimName: job-data
       - name: custom-resources
         persistentVolumeClaim:
           claimName: custom-resources
   EOF
   ```

   Le pod test utilise runAsUser: 61000, runAsGroup: 61000 et fsGroup: 61000. Ces valeurs correspondent à l'UID/au GID d'exécution de Dynamic Engine et sont nécessaires pour que la titularité des fichiers soit correcte sur les volumes montés.
7. Vérifiez que le pod peut lire et écrire des données dans les volumes montés :
   ```
   kubectl exec -n $DYNAMIC_ENGINE_ENV_NAMESPACE test-pod-pvc -- \
     sh -c "echo 'Hello world' > /opt/talend/archive/test.txt \
     && cat /opt/talend/archive/test.txt \
     && rm -f /opt/talend/archive/test.txt"
   ```

   Si la commande aboutit à une erreur, le volume sauvegardé dans S3 est disponible et accessible en écriture.

## Résultats

Votre cluster EKS s'exécute avec le pilote S3 CSI installé et les trois PersistentVolumes (archive, job-data et custom-resources) sont créés et liés à leurs revendications PersistentVolumeClaims dans l'espace de noms qlik-processing-env-&lt;env-id&gt;. Le cluster est prêt pour le déploiement Dynamic Engine.

Note InformationsConseil : Le service docker-registry embarqué de Dynamic Engine effectue des écritures aléatoires, ce que le pilote S3 CSI (Mountpoint pour Amazon S3) ne supporte pas. C'est pourquoi le volume docker-registry ne peut pas utiliser la revendication PersistentVolumeClaim sauvegardée dans S3. Utilisez EFS ou d'autres systèmes externes qui supportent POSIX (Portable Operating System Interface - Interface de système d'exploitation portable) pour provisionner des volumes persistants pour docker-registry.

* Pour des détails sur la configuration de docker-registry, consultez [Configurer un registre Docker personnalisé pour des tâches Talend Management Console](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/configure-docker-registry "Configurez un registre Docker externe pour les Jobs d'intégration de données, les Jobs Big Data, les services de données et les Routes dans un environnement Dynamic Engine.").
* Pour des instructions sur l'utilisation de volumes persistants statiques existants, consultez [Déployer Dynamic Engine avec les revendications PersistentVolumeClaims existantes](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/deploy-dynamic-engine-with-static-pvc "Configurez les charts Dynamic Engine Helm de sorte qu'ils référencent les revendications PersistentVolumeClaims existantes par leur nom au lieu d'utiliser le provisioning StorageClass dynamique.").
* Pour des instructions sur l'utilisation de volumes persistants dynamiques (StorageClass), consultez [Provisionner une classe de stockage dédiée aux services d'environnements du Dynamic Engine](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/deploy-dynamic-engine-with-specific-storageclass "Configurez une classe de stockage spécifique pour les services d'environnement du Dynamic Engine au lieu d'utiliser la classe de stockage Kubernetes par défaut.").

## Que faire ensuite

Configurez et déployez des charts Dynamic Engine Helm pour référencer les revendications PersistentVolumeClaims que vous avez créées dans cette procédure. Pour des instructions détaillées sur l'utilisation de PVC existants, consultez [Déployer Dynamic Engine avec les revendications PersistentVolumeClaims existantes](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/deploy-dynamic-engine-with-static-pvc "Configurez les charts Dynamic Engine Helm de sorte qu'ils référencent les revendications PersistentVolumeClaims existantes par leur nom au lieu d'utiliser le provisioning StorageClass dynamique.").

### Dans cette section

* [Déployer Dynamic Engine avec les revendications PersistentVolumeClaims existantes](https://help.qlik.com/talend/fr-FR/dynamic-engine-configuration-guide/Cloud/deploy-dynamic-engine-with-static-pvc)