Platzieren Sie Kubernetes-Pods auf Amazon EKS mithilfe von Knotenaffinität, Taints und Toleranzen - AWS Prescriptive Guidance

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Platzieren Sie Kubernetes-Pods auf Amazon EKS mithilfe von Knotenaffinität, Taints und Toleranzen

Erstellt von Hitesh Parikh (AWS) und Raghu Bhamidimarri (AWS)

Umgebung: PoC oder Pilotprojekt

Technologien: Container und Microservices

Workload: Open-Source

AWS-Services: Amazon EKS

Übersicht

Dieses Muster zeigt die Verwendung von Kubernetes-Knotenaffinität, Knoten-Taints und Pod-Tolerationen, um Anwendungs-Pods auf bestimmten Worker-Knoten in einem Amazon Elastic Kubernetes Service (Amazon EKS)-Cluster in der Amazon Web Services (AWS) Cloud absichtlich zu planen.

Ein Taint ist eine Knoteneigenschaft, mit der Knoten eine Reihe von Pods ablehnen können. Eine Toleranz ist eine Pod-Eigenschaft, mit der der Kubernetes-Scheduler Pods auf Knoten planen kann, die übereinstimmende Taints haben.

Toleranzen allein können jedoch nicht verhindern, dass ein Scheduler einen Pod auf einem Worker-Knoten platziert, der keine Taints hat. Beispielsweise kann ein rechenintensiver Pod mit einer Toleranz unbeabsichtigt auf einem universellen, nicht verunreinigten Knoten geplant werden. In diesem Szenario weist die Knotenaffinitätseigenschaft eines Pods den Scheduler an, den Pod auf einem Knoten zu platzieren, der die in der Knotenaffinität angegebenen Knotenauswahlkriterien erfüllt.

Taints, Toleranzen und Knotenaffinität weisen den Scheduler zusammen an, Pods konsistent auf den Knoten mit übereinstimmenden Taints und den Knotenbezeichnungen zu planen, die den auf dem Pod angegebenen Kriterien für die Knotenaffinität entsprechen.

Dieses Muster enthält ein Beispiel für eine Kubernetes-Bereitstellungsmanifestdatei und die Schritte zum Erstellen eines EKS-Clusters, Bereitstellen einer Anwendung und Validieren der Pod-Platzierung.

Voraussetzungen und Einschränkungen

Voraussetzungen

  • Ein AWS-Konto mit Anmeldeinformationen, die zum Erstellen von Ressourcen in Ihrem AWS-Konto konfiguriert sind

  • AWS-Befehlszeilenschnittstelle (AWS Command Line Interface, AWS CLI)

  • eksctl

  • kubectl

  • Docker installiert (für das verwendete Betriebssystem) und die Engine gestartet (Informationen zu den Docker-Lizenzanforderungen finden Sie auf der Docker-Website )

  • Java Version 11 oder höher

  • Ein Java-Microservice, der in Ihrer bevorzugten integrierten Entwicklungsumgebung (IDE) ausgeführt wird, z. B. AWS Cloud9, IntelliJ IDEA Community Edition oder Eclipse (wenn Sie keinen Java-Microservice haben, finden Sie im Abschnitt Bereitstellen eines Java-Microservice auf Amazon-EKS-Mustern und Microservices mit Spring Hilfe bei der Erstellung des Microservice).

Einschränkungen

  • Dieses Muster stellt den Java-Code nicht bereit und setzt voraus, dass Sie bereits mit Java vertraut sind. Informationen zum Erstellen eines einfachen Java-Microservice finden Sie unter Bereitstellen eines Java-Beispiel-Microservice auf Amazon EKS.

  • Die Schritte in diesem Artikel erstellen AWS-Ressourcen, für die Kosten anfallen können. Stellen Sie sicher, dass Sie die AWS-Ressourcen bereinigen, nachdem Sie die Schritte zur Implementierung und Validierung des Musters abgeschlossen haben.

Architektur

Zieltechnologie-Stack

  • Amazon EKS

  • Java

  • Docker

  • Amazon Elastic Container Registry (Amazon ECR)

Zielarchitektur

Das Lösungsarchitekturdiagramm zeigt Amazon EKS mit zwei Pods (Bereitstellung 1 und Bereitstellung 2) und zwei Knotengruppen (ng1 und ng2) mit jeweils zwei Knoten. Die Pods und Knoten haben die folgenden Eigenschaften.

 

Bereitstellung 1 Pod

Pod für Bereitstellung 2

Knotengruppe 1 (ng1)

Knotengruppe 2 (ng2)

Toleranz

Schlüssel: classified_workload, Wert: true, Effekt: NoSchedule

Schlüssel: machine_ Learning_workload, Wert: true, Effekt: NoSchedule

None

 

 

Knotenaffinität

Schlüssel: alpha.eksctl.io/nodegroup-name = ng1;

None

nodeGroups.name = ng1

 

Taint

 

 

Schlüssel: classified_workload, Wert: true, Effekt: NoSchedule

Schlüssel: machine_ Learning_workload, Wert: true, Effekt: NoSchedule

None

  1. Für den Deployment 1 Pod sind Toleranzen und Knotenaffinität definiert, die den Kubernetes-Scheduler anweist, die Bereitstellungs-Pods auf den Knoten der Knotengruppe 1 (ng1) zu platzieren.

  2. Knotengruppe 2 (ng2) hat keine Knotenbezeichnung, die dem Knotenaffinitätsknoten-Selektorausdruck für Bereitstellung 1 entspricht, sodass die Pods nicht auf ng2-Knoten geplant werden.

  3. Für den Bereitstellung-2-Pod sind keine Toleranzen oder Knotenaffinitäten im Bereitstellungsmanifest definiert. Der Scheduler lehnt die Planung von Bereitstellung-2-Pods auf Knotengruppe 1 aufgrund der Taints auf den Knoten ab.

  4. Die Bereitstellung-2-Pods werden stattdessen in Knotengruppe 2 platziert, da die Knoten keine Taints haben.

Dieses Muster zeigt, dass Sie durch die Verwendung von Taints und Toleranzen in Kombination mit der Knotenaffinität die Platzierung von Pods auf bestimmten Gruppen von Worker-Knoten steuern können.

Tools

AWS-Services

Andere Tools

  • Docker ist eine Reihe von Platform as a Service (PaaS)-Produkten, die Virtualisierung auf Betriebssystemebene verwenden, um Software in Containern bereitzustellen.

  • kubectl ist eine Befehlszeilenschnittstelle, mit der Sie Befehle für Kubernetes-Cluster ausführen können.

Polen

AufgabeBeschreibungErforderliche Fähigkeiten

Erstellen Sie die Datei cluster.yaml.

Erstellen Sie eine Datei mit dem Namen cluster.yaml mit dem folgenden Code.

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
App-Besitzer, AWS DevOps, Cloud-Administrator, DevOps Techniker

Erstellen Sie den Cluster mit eksctl.

Führen Sie die cluster.yaml Datei aus, um den EKS-Cluster zu erstellen. Das Erstellen des Clusters kann einige Minuten dauern.

eksctl create cluster -f cluster.yaml
AWS DevOps, AWS-Systemadministrator, App-Entwickler
AufgabeBeschreibungErforderliche Fähigkeiten

Erstellen Sie ein privates Amazon-ECR-Repository.

Informationen zum Erstellen eines Amazon-ECR-Repositorys finden Sie unter Erstellen eines privaten Repositorys. Notieren Sie sich den URI des Repo.

AWS DevOps, DevOps Techniker, App-Entwickler

Erstellen Sie das Dockerfile.

Wenn Sie über ein vorhandenes Docker-Container-Image verfügen, das Sie zum Testen des Musters verwenden möchten, können Sie diesen Schritt überspringen.

Verwenden Sie den folgenden Ausschnitt als Referenz, um ein Dockerfile zu erstellen. Wenn Sie auf Fehler stoßen, lesen Sie den Abschnitt Fehlerbehebung.

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 Engineering

Erstellen Sie die Quelldateien pom.xml und sowie das Docker-Image und übertragen Sie es.

Informationen zum Erstellen der -pom.xmlDatei und der Java-Quelldatei finden Sie unter Bereitstellen eines Java-Microservice-Beispielmusters auf Amazon EKS.

Verwenden Sie die Anweisungen in diesem Muster, um das Docker-Image zu erstellen und zu pushen.

AWS DevOps, DevOps Techniker, App-Entwickler
AufgabeBeschreibungErforderliche Fähigkeiten

Erstellen Sie die Datei deployment.yaml.

Um die deployment.yaml Datei zu erstellen, verwenden Sie den Code im Abschnitt Zusätzliche Informationen.

Im Code ist der Schlüssel für die Knotenaffinität jede Bezeichnung, die Sie beim Erstellen von Knotengruppen erstellen. Dieses Muster verwendet die von eksctl erstellte Standardbezeichnung. Informationen zum Anpassen von Labels finden Sie unter Zuweisen von Pods zu Knoten in der Kubernetes-Dokumentation.

Der Wert für den Knotenaffinitätsschlüssel ist der Name der Knotengruppe, die von erstellt wurdecluster.yaml.

Führen Sie den folgenden Befehl aus, um den Schlüssel und den Wert für den Taint abzurufen.

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

Das Image ist der URI des Amazon-ECR-Repositorys, das Sie in einem früheren Schritt erstellt haben.

AWS DevOps, DevOps Techniker, App-Entwickler

Stellen Sie die Datei bereit.

Führen Sie den folgenden Befehl aus, um in Amazon EKS bereitzustellen.

kubectl apply -f deployment.yaml
App-Entwickler, DevOps Techniker, AWS DevOps

Überprüfen Sie die Bereitstellung.

  1. Führen Sie den folgenden Befehl aus, um zu überprüfen, ob die Pods READY sind.

    kubectl get pods -o wide

    Wenn das POD bereit ist, sollte die Ausgabe in etwa wie folgt aussehen, wobei als Wird ausgeführt STATUS angezeigt wird.

    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>

    Notieren Sie sich den Namen des Pods und den Namen des Knotens. Sie können den nächsten Schritt überspringen.

  2. (Optional) Führen Sie den folgenden Befehl aus, um zusätzliche Details zum Pod zu erhalten und die Toleranzen auf dem Pod zu überprüfen.

    kubectl describe pod <pod_name>

    Ein Beispiel für die Ausgabe finden Sie im Abschnitt Zusätzliche Informationen.

  3. Führen Sie den folgenden Befehl aus, um zu überprüfen, ob die Pod-Platzierung auf dem Knoten korrekt ist.

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

    Vergewissern Sie sich, dass der Taint auf dem Knoten mit der Toleranz übereinstimmt und die Bezeichnung auf dem Knoten mit der in definierten Knotenaffinität übereinstimmtdeployment.yaml.

    Der Pod mit Toleranzen und Knotenaffinität sollte auf einem Knoten mit den übereinstimmenden Taints und den Knotenaffinitätsbeschriftungen platziert werden. Mit dem vorherigen Befehl erhalten Sie die Taints auf dem Knoten. Im Folgenden finden Sie eine Beispielausgabe.

    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

    Führen Sie außerdem den folgenden Befehl aus, um zu überprüfen, ob der Knoten, auf dem der Pod platziert ist, eine Bezeichnung hat, die der Knotenaffinitätsknotenbezeichnung entspricht.

    kubectl get node <node name> --show-labels
  4. Um zu überprüfen, ob die Anwendung das macht, was sie tun soll, überprüfen Sie die Pod-Protokolle, indem Sie den folgenden Befehl ausführen.

    kubectl logs -f <name-of-the-pod>
App-Entwickler, DevOps Techniker, AWS DevOps

Erstellen Sie eine zweite Bereitstellungs-.yaml-Datei ohne Toleranz und Knotenaffinität.

Dieser zusätzliche Schritt dient zur Validierung, dass der resultierende Pod nicht auf einem Knoten mit Taints geplant ist, wenn in der Bereitstellungsmanifestdatei keine Knotenaffinität oder -toleranz angegeben ist. (Er sollte auf einem Knoten geplant werden, der keine Taints hat). Verwenden Sie den folgenden Code, um eine neue Bereitstellungsdatei namens zu erstellendeploy_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
App-Entwickler, AWS DevOps, DevOps Techniker

Stellen Sie die zweite Bereitstellungs-.yaml-Datei bereit und validieren Sie die Pod-Platzierung

  1. Führen Sie den folgenden Befehl aus.

    kubectl apply -f deploy_no_taint.yaml
  2. Nachdem die Bereitstellung erfolgreich war, führen Sie dieselben Befehle aus, die Sie zuvor ausgeführt haben, um die Pod-Platzierung in einer Knotengruppe ohne Taint zu überprüfen.

    kubectl describe node <node_name> | grep "Taints"

    Die Ausgabe sollte wie folgt aussehen.

    Taints: <none>

    Damit ist der Test abgeschlossen.

App-Entwickler, AWS DevOps, DevOps Techniker
AufgabeBeschreibungErforderliche Fähigkeiten

Bereinigen Sie die Ressourcen.

Verwenden Sie den folgenden Befehl, um AWS-Gebühren für Ressourcen zu vermeiden, die noch ausgeführt werden.

eksctl delete cluster --name <Name of the cluster> --region <region-code>
AWS DevOps, App-Entwickler

Fehlerbehebung

ProblemLösung

Einige dieser Befehle werden möglicherweise nicht ausgeführt, wenn Ihr System arm64-Architektur verwendet (insbesondere wenn Sie dies auf einem M1-Mac ausführen). In der folgenden Zeile kann ein Fehler auftreten.

FROM adoptopenjdk/openjdk11:jdk-11.0.14.1_1-alpine

Wenn beim Ausführen der Dockerfile-Datei Fehler auftreten, ersetzen Sie die FROM Zeile durch die folgende Zeile.

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

Zugehörige Ressourcen

Zusätzliche Informationen

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

Beispielausgabe für das Beschreiben eines Pods

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>