Placez des pods Kubernetes sur Amazon en EKS utilisant l'affinité, les entorses et les tolérances des nœuds - Recommandations AWS

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Placez des pods Kubernetes sur Amazon en EKS utilisant l'affinité, les entorses et les tolérances des nœuds

Créé par Hitesh Parikh (AWS) et Raghu Bhamidimarri () AWS

Environnement : PoC ou pilote

Technologies : Conteneurs et microservices

Charge de travail : Open source

AWSservices : Amazon EKS

Récapitulatif

Ce modèle illustre l'utilisation de l'affinité des nœuds Kubernetes, de l'altération des nœuds et des tolérances des pods pour planifier intentionnellement des pods d'applications sur des nœuds de travail spécifiques d'un cluster Amazon Elastic Kubernetes Service (Amazon) EKS sur le cloud Amazon Web Services (). AWS

Une souillure est une propriété de nœud qui permet aux nœuds de rejeter un ensemble de modules. Une tolérance est une propriété de Pod qui permet au planificateur Kubernetes de planifier des Pods sur des nœuds présentant les mêmes caractéristiques.

Cependant, les tolérances ne peuvent à elles seules empêcher un planificateur de placer un Pod sur un nœud de travail qui ne présente aucune trace. Par exemple, un pod à forte intensité de calcul assorti d'une tolérance peut involontairement être programmé sur un nœud non contaminé à usage général. Dans ce scénario, la propriété d'affinité de nœud d'un Pod indique au planificateur de placer le Pod sur un nœud qui répond aux critères de sélection de nœuds spécifiés dans l'affinité de nœud.

Ensemble, les entailles, les tolérances et l'affinité des nœuds indiquent au planificateur de planifier les pods de manière cohérente sur les nœuds avec les taches correspondantes et les étiquettes des nœuds qui correspondent aux critères de sélection des nœuds d'affinité de nœud spécifiés sur le pod.

Ce modèle fournit un exemple de fichier manifeste de déploiement de Kubernetes, ainsi que les étapes à suivre pour créer un EKS cluster, déployer une application et valider le placement du Pod.

Conditions préalables et limitations

Prérequis

Limites

  • Ce modèle ne fournit pas le code Java et suppose que vous êtes déjà familiarisé avec Java. Pour créer un microservice Java de base, consultez Déployer un exemple de microservice Java sur Amazon. EKS

  • Les étapes décrites dans cet article créent AWS des ressources qui peuvent entraîner des coûts. Assurez-vous de nettoyer les AWS ressources une fois que vous avez terminé les étapes de mise en œuvre et de validation du modèle.

Architecture

Pile technologique cible

  • Amazon EKS

  • Java

  • Docker

  • Amazon Elastic Container Registry (AmazonECR)

Architecture cible

Le schéma d'architecture de la solution montre Amazon EKS avec deux pods (déploiement 1 et déploiement 2) et deux groupes de nœuds (ng1 et ng2) avec deux nœuds chacun. Les pods et les nœuds possèdent les propriétés suivantes.

 

Déploiement : 1 pod

Déploiement 2 Pod

Groupe de nœuds 1 (ng1)

Groupe de nœuds 2 (ng2)

Tolérance

clé : classified_workload, valeur : true, effet : NoSchedule

clé : machine_learning_workload, valeur : vrai, effet : NoSchedule

Aucun

 

 

Affinité des nœuds

clé : alpha.eksctl.io/nodegroup-name = ng1 ;

Aucun

nodeGroups.nom = ng1

 

Souillure

 

 

clé : classified_workload, valeur : true, effet : NoSchedule

clé : machine_learning_workload, valeur : vrai, effet : NoSchedule

Aucun

EKSConfiguration Amazon avec deux pods et deux groupes de nœuds.
  1. Le pod Deployment 1 a des tolérances et une affinité de nœud définies, ce qui indique au planificateur Kubernetes de placer les pods de déploiement sur les nœuds du groupe de nœuds 1 (ng1).

  2. Le groupe de nœuds 2 (ng2) n'a pas d'étiquette de nœud correspondant à l'expression du sélecteur de nœuds d'affinité pour le déploiement 1. Les pods ne seront donc pas planifiés sur les nœuds ng2.

  3. Aucune tolérance ou affinité de nœud n'est définie dans le manifeste de déploiement pour le module Deployment 2. Le planificateur refusera de planifier le déploiement de 2 pods sur le groupe de nœuds 1 en raison des entorses sur les nœuds.

  4. Les pods Deployment 2 seront plutôt placés sur le groupe de nœuds 2, car les nœuds ne présentent aucune trace.

Ce modèle montre qu'en utilisant des contraintes et des tolérances, associées à l'affinité des nœuds, vous pouvez contrôler le placement des pods sur des ensembles spécifiques de nœuds de travail.

Outils

AWSservices

Autres outils

  • Docker est un ensemble de produits de plateforme en tant que service (PaaS) qui utilisent la virtualisation au niveau du système d'exploitation pour fournir des logiciels dans des conteneurs.

  • kubectl est une interface de ligne de commande qui vous permet d'exécuter des commandes sur des clusters Kubernetes.

Épopées

TâcheDescriptionCompétences requises

Créez le fichier cluster.yaml.

Créez un fichier appelé cluster.yaml avec le code suivant.

apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: eks-taint-demo region: us-west-1 # Unmanaged nodegroups with and without taints. nodeGroups: - name: ng1 instanceType: m5.xlarge minSize: 2 maxSize: 3 taints: - key: classified_workload value: "true" effect: NoSchedule - key: machine_learning_workload value: "true" effect: NoSchedule - name: ng2 instanceType: m5.xlarge minSize: 2 maxSize: 3
Propriétaire de l'application AWS DevOps, administrateur du cloud, DevOps ingénieur

Créez le cluster à l'aide de eksctl.

Exécutez le cluster.yaml fichier pour créer le EKS cluster. La création du cluster peut prendre quelques minutes.

eksctl create cluster -f cluster.yaml
AWS DevOps, administrateur AWS système, développeur d'applications
TâcheDescriptionCompétences requises

Créez un référentiel ECR privé Amazon.

Pour créer un ECR dépôt Amazon, consultez Création d'un dépôt privé. Notez le URI nom du dépôt.

AWS DevOps, DevOps ingénieur, développeur d'applications

Créez le Dockerfile.

Si vous avez une image de conteneur Docker existante que vous souhaitez utiliser pour tester le modèle, vous pouvez ignorer cette étape.

Pour créer un Dockerfile, utilisez l'extrait suivant comme référence. Si vous rencontrez des erreurs, consultez la section Dépannage.

FROM adoptopenjdk/openjdk11:jdk-11.0.14.1_1-alpine RUN apk add maven WORKDIR /code # Prepare by downloading dependencies ADD pom.xml /code/pom.xml RUN ["mvn", "dependency:resolve"] RUN ["mvn", "verify"] # Adding source, compile and package into a fat jar ADD src /code/src RUN ["mvn", "package"] EXPOSE 4567 CMD ["java", "-jar", "target/eksExample-jar-with-dependencies.jar"]
AWS DevOps, DevOps ingénieur

Créez le fichier pom.xml et les fichiers source, puis créez et publiez l'image Docker.

Pour créer le pom.xml fichier et le fichier source Java, consultez la section Déployer un exemple de microservice Java sur le EKS modèle Amazon.

Utilisez les instructions de ce modèle pour créer et envoyer l'image Docker.

AWS DevOps, DevOps ingénieur, développeur d'applications
TâcheDescriptionCompétences requises

Créez le fichier deployment.yaml.

Pour créer le deployment.yaml fichier, utilisez le code de la section Informations supplémentaires.

Dans le code, la clé de l'affinité des nœuds est toute étiquette que vous créez lors de la création de groupes de nœuds. Ce modèle utilise l'étiquette par défaut créée par eksctl. Pour plus d'informations sur la personnalisation des étiquettes, consultez la section Affectation de pods à des nœuds dans la documentation de Kubernetes.

La valeur de la clé d'affinité de nœud est le nom du groupe de nœuds créé parcluster.yaml.

Pour obtenir la clé et la valeur de la tache, exécutez la commande suivante.

kubectl get nodes -o json | jq '.items[].spec.taints'

L'image est celle URI du ECR référentiel Amazon que vous avez créé lors d'une étape précédente.

AWS DevOps, DevOps ingénieur, développeur d'applications

Déployez le fichier.

Pour effectuer un déploiement sur AmazonEKS, exécutez la commande suivante.

kubectl apply -f deployment.yaml
Développeur d'applications, DevOps ingénieur, AWS DevOps

Vérifiez le déploiement.

  1. Pour vérifier si les pods le sontREADY, exécutez la commande suivante.

    kubectl get pods -o wide

    Si le POD est prêt, le résultat devrait ressembler à ce qui suit, avec le STATUS code « Running ».

    NAME        READY    STATUS    RESTARTS   AGE   IP  NODE  NOMINATED NODE   READINESS GATES <pod_name>   1/1     Running   0          12d   192.168.18.50   ip-192-168-20-110.us-west-1.compute.internal   <none>           <none>

    Notez le nom du Pod et le nom du nœud. Vous pouvez ignorer l'étape suivante.

  2. (Facultatif) Pour obtenir des informations supplémentaires sur le Pod et vérifier les tolérances sur le Pod, exécutez la commande suivante.

    kubectl describe pod <pod_name>

    Un exemple de sortie se trouve dans la section Informations supplémentaires.

  3. Pour vérifier que le placement du Pod sur le nœud est correct, exécutez la commande suivante.

    kubectl describe node <node name> | grep -A 1 "Taints"

    Vérifiez que la souillure du nœud correspond à la tolérance et que l'étiquette du nœud correspond à l'affinité du nœud définie dans. deployment.yaml

    Le pod avec les tolérances et l'affinité des nœuds doit être placé sur un nœud avec les nuances correspondantes et les étiquettes d'affinité des nœuds. La commande précédente vous indique les taches sur le nœud. Voici un exemple de sortie.

    kubectl describe node ip-192-168-29-181.us-west-1.compute.internal | grep -A 1 "Taints" Taints:             classifled_workload=true:NoSchedule                     machine_learning_workload=true:NoSchedule

    En outre, exécutez la commande suivante pour vérifier que le nœud sur lequel le Pod est placé possède une étiquette correspondant à celle du nœud d'affinité du nœud.

    kubectl get node <node name> --show-labels
  4. Pour vérifier que l'application fait ce qu'elle est censée faire, consultez les journaux du Pod en exécutant la commande suivante.

    kubectl logs -f <name-of-the-pod>
Développeur d'applications, DevOps ingénieur, AWS DevOps

Créez un deuxième fichier de déploiement .yaml sans tolérance ni affinité de nœud.

Cette étape supplémentaire consiste à valider que lorsqu'aucune affinité ou tolérance de nœud n'est spécifiée dans le fichier manifeste de déploiement, le pod résultant n'est pas planifié sur un nœud présentant des entaches. (Il doit être planifié sur un nœud qui ne présente aucune trace). Utilisez le code suivant pour créer un nouveau fichier de déploiement appelédeploy_no_taint.yaml.

apiVersion: apps/v1 kind: Deployment metadata: name: microservice-deployment-non-tainted spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: java-microservice-no-taint template: metadata: labels: app.kubernetes.io/name: java-microservice-no-taint spec: containers: - name: java-microservice-container-2 image: <account_number>.dkr.ecr<region>.amazonaws.com/<repository_name>:latest ports: - containerPort: 4567
Développeur d'applications AWS DevOps, DevOps ingénieur

Déployez le deuxième fichier .yaml de déploiement et validez le placement du Pod

  1. Exécutez la commande suivante.

    kubectl apply -f deploy_no_taint.yaml
  2. Une fois le déploiement réussi, exécutez les mêmes commandes que celles que vous avez exécutées précédemment pour vérifier le placement du Pod dans un groupe de nœuds sans aucune altération.

    kubectl describe node <node_name> | grep "Taints"

    Le résultat doit être le suivant.

    Taints: <none>

    Ceci termine le test.

Développeur d'applications AWS DevOps, DevOps ingénieur
TâcheDescriptionCompétences requises

Nettoyez les ressources.

Pour éviter d'encourir des AWS frais pour les ressources qui restent actives, utilisez la commande suivante.

eksctl delete cluster --name <Name of the cluster> --region <region-code>
AWS DevOps, Développeur d'applications

Résolution des problèmes

ProblèmeSolution

Certaines de ces commandes risquent de ne pas s'exécuter si votre système utilise l'architecture arm64 (en particulier si vous l'exécutez sur un Mac M1). Il se peut que la ligne suivante comporte une erreur.

FROM adoptopenjdk/openjdk11:jdk-11.0.14.1_1-alpine

Si vous rencontrez des erreurs lors de l'exécution du Dockerfile, remplacez la FROM ligne par la ligne suivante.

FROM bellsoft/liberica-openjdk-alpine-musl:17

Ressources connexes

Informations supplémentaires

deployment.yaml

apiVersion: apps/v1 kind: Deployment metadata: name: microservice-deployment spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: java-microservice template: metadata: labels: app.kubernetes.io/name: java-microservice spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: alpha.eksctl.io/nodegroup-name operator: In values: - <node-group-name-from-cluster.yaml> tolerations: #only this pod has toleration and is viable to go to ng with taint - key: "<Taint key>" #classified_workload in our case operator: Equal value: "<Taint value>" #true effect: "NoSchedule" - key: "<Taint key>" #machine_learning_workload in our case operator: Equal value: "<Taint value>" #true effect: "NoSchedule" containers: - name: java-microservice-container image: <account_number>.dkr.ecr<region>.amazonaws.com/<repository_name>:latest ports: - containerPort: 4567

décrire un exemple de sortie du pod

Name: microservice-deployment-in-tainted-nodes-5684cc495b-vpcfx Namespace: default Priority: 0 Node: ip-192-168-29-181.us-west-1.compute.internal/192.168.29.181 Start Time: Wed, 14 Sep 2022 11:06:47 -0400 Labels: app.kubernetes.io/name=java-microservice-taint pod-template-hash=5684cc495b Annotations: kubernetes.io/psp: eks.privileged Status: Running IP: 192.168.13.44 IPs: IP: 192.168.13.44 Controlled By: ReplicaSet/microservice-deployment-in-tainted-nodes-5684cc495b Containers: java-microservice-container-1: Container ID: docker://5c158df8cc160de8f57f62f3ee16b12725a87510a809d90a1fb9e5d873c320a4 Image: 934188034500.dkr.ecr.us-east-1.amazonaws.com/java-eks-apg Image ID: docker-pullable://934188034500.dkr.ecr.us-east-1.amazonaws.com/java-eks-apg@sha256:d223924aca8315aab20d54eddf3443929eba511b6433017474d01b63a4114835 Port: 4567/TCP Host Port: 0/TCP State: Running Started: Wed, 14 Sep 2022 11:07:02 -0400 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-ddvvw (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-ddvvw: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: classifled_workload=true:NoSchedule machine_learning_workload=true:NoSchedule node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: <none>