Posiziona Kubernetes Pods su Amazon EKS utilizzando affinità, contaminazioni e tolleranze dei nodi - Prontuario AWS

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Posiziona Kubernetes Pods su Amazon EKS utilizzando affinità, contaminazioni e tolleranze dei nodi

Creato da Hitesh Parikh (AWS) e Raghu Bhamidimarri (AWS)

Ambiente: PoC o pilota

Tecnologie: contenitori e microservizi

Carico di lavoro: open source

Servizi AWS: Amazon EKS

Riepilogo

Questo modello dimostra l'uso dell'affinità dei nodi Kubernetes, dei nodi e delle tolleranze dei Pod per pianificare intenzionalmente i Pod delle applicazioni su nodi di lavoro specifici in un cluster Amazon Elastic Kubernetes Service (Amazon EKS) sul cloud Amazon Web Services (AWS).

Un taint è una proprietà del nodo che consente ai nodi di rifiutare un set di pod. Una tolleranza è una proprietà Pod che consente allo scheduler Kubernetes di pianificare i Pod sui nodi che presentano macchie corrispondenti.

Tuttavia, le tolleranze da sole non possono impedire a uno scheduler di posizionare un Pod su un nodo di lavoro che non presenta alcuna macchia. Ad esempio, un Pod ad alta intensità di calcolo con una tolleranza può essere programmato involontariamente su un nodo incontaminato per uso generico. In questo scenario, la proprietà di affinità del nodo di un Pod indica allo scheduler di posizionare il Pod su un nodo che soddisfa i criteri di selezione dei nodi specificati nell'affinità del nodo.

I caratteri, le tolleranze e l'affinità dei nodi insieme indicano allo scheduler di pianificare i Pod in modo coerente sui nodi con le tonalità corrispondenti e le etichette dei nodi che corrispondono ai criteri di selezione dei nodi di affinità dei nodi specificati nel Pod.

Questo modello fornisce un esempio di file manifest di implementazione di Kubernetes e i passaggi per creare un cluster EKS, distribuire un'applicazione e convalidare il posizionamento dei Pod.

Prerequisiti e limitazioni

Prerequisiti

Limitazioni

  • Questo pattern non fornisce il codice Java e presuppone che tu abbia già familiarità con Java. Per creare un microservizio Java di base, consulta Distribuire un microservizio Java di esempio su Amazon EKS.

  • I passaggi descritti in questo articolo creano risorse AWS che possono generare costi. Assicurati di ripulire le risorse AWS dopo aver completato i passaggi per implementare e convalidare il modello.

Architettura

Stack tecnologico Target

  • Amazon EKS

  • Java

  • Docker

  • Amazon Elastic Container Registry (Amazon ECR)

Architettura di destinazione

Il diagramma dell'architettura della soluzione mostra Amazon EKS con due pod (Deployment 1 e Deployment 2) e due gruppi di nodi (ng1 e ng2) con due nodi ciascuno. I pod e i nodi hanno le seguenti proprietà.

 

Distribuzione: 1 Pod

Implementazione 2 Pod

Gruppo di nodi 1 (ng1)

Gruppo di nodi 2 (ng2)

Tolleranza

chiave: classified_workload, valore: true, effetto: NoSchedule

chiave: machine_learning_workload, valore: true, effetto: NoSchedule

Nessuno

 

 

Affinità dei nodi

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

Nessuno

NodeGroups.name = ng1

 

Inquinamento

 

 

chiave: classified_workload, valore: true, effetto: NoSchedule

chiave: machine_learning_workload, valore: true, effetto: NoSchedule

Nessuno

  1. Il Deployment 1 Pod ha tolleranze e affinità di nodi definite, il che indica allo scheduler Kubernetes di posizionare i Pod di distribuzione sui nodi del gruppo di nodi 1 (ng1).

  2. Il gruppo di nodi 2 (ng2) non ha un'etichetta di nodo che corrisponda all'espressione del selettore del nodo di affinità dei nodi per Deployment 1, quindi i Pod non saranno pianificati sui nodi ng2.

  3. Il Deployment 2 Pod non ha alcuna tolleranza o affinità di nodo definita nel manifesto di distribuzione. Lo scheduler rifiuterà la pianificazione di Deployment 2 Pods sul gruppo di nodi 1 a causa delle contaminazioni sui nodi.

  4. I Deployment 2 Pods verranno invece posizionati sul gruppo di nodi 2, poiché i nodi non presentano alcuna macchia.

Questo modello dimostra che utilizzando contaminazioni e tolleranze, combinate con l'affinità dei nodi, è possibile controllare il posizionamento dei Pod su set specifici di nodi di lavoro.

Strumenti

Servizi AWS

Altri strumenti

  • Docker è un insieme di prodotti Platform as a Service (PaaS) che utilizzano la virtualizzazione a livello di sistema operativo per fornire software in container.

  • kubectl è un'interfaccia a riga di comando che consente di eseguire comandi sui cluster Kubernetes.

Epiche

AttivitàDescrizioneCompetenze richieste

Crea il file cluster.yaml.

Crea un file chiamato cluster.yaml con il codice seguente.

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
Proprietario dell'app, AWS DevOps, amministratore del cloud, DevOps ingegnere

Crea il cluster usando eksctl.

Esegui il cluster.yaml file per creare il cluster EKS. La creazione del cluster potrebbe richiedere alcuni minuti.

eksctl create cluster -f cluster.yaml
AWS DevOps, amministratore di sistema AWS, sviluppatore di app
AttivitàDescrizioneCompetenze richieste

Crea un repository privato Amazon ECR.

Per creare un repository Amazon ECR, consulta Creazione di un repository privato. Nota l'URI del repository.

AWS DevOps, DevOps ingegnere, sviluppatore di app

Crea il Dockerfile.

Se disponi di un'immagine del contenitore Docker esistente che desideri utilizzare per testare il pattern, puoi saltare questo passaggio.

Per creare un Dockerfile, usa il seguente frammento come riferimento. Se riscontri errori, consulta la sezione Risoluzione dei problemi.

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 ingegnere

Crea il file pom.xml e i file sorgente, crea e invia l'immagine Docker.

Per creare il pom.xml file e il file sorgente Java, consulta Distribuire un microservizio Java di esempio sul modello Amazon EKS.

Usa le istruzioni contenute in quel modello per creare e inviare l'immagine Docker.

AWS DevOps, DevOps ingegnere, sviluppatore di app
AttivitàDescrizioneCompetenze richieste

Crea il file deployment.yaml.

Per creare il deployment.yaml file, usa il codice nella sezione Informazioni aggiuntive.

Nel codice, la chiave per l'affinità dei nodi è qualsiasi etichetta creata durante la creazione di gruppi di nodi. Questo modello utilizza l'etichetta predefinita creata da eksctl. Per informazioni sulla personalizzazione delle etichette, consulta Assegnazione di pod ai nodi nella documentazione di Kubernetes.

Il valore per la chiave di affinità del nodo è il nome del gruppo di nodi creato da. cluster.yaml

Per ottenere la chiave e il valore per il taint, esegui il comando seguente.

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

L'immagine è l'URI del repository Amazon ECR creato in un passaggio precedente.

AWS DevOps, DevOps ingegnere, sviluppatore di app

Distribuisci il file.

Per eseguire la distribuzione su Amazon EKS, esegui il comando seguente.

kubectl apply -f deployment.yaml
Sviluppatore di app, DevOps ingegnere, AWS DevOps

Controlla la distribuzione.

  1. Per verificare se i pod sono PRONTI, esegui il seguente comando.

    kubectl get pods -o wide

    Se il POD è pronto, l'output dovrebbe essere simile al seguente, con STATUS as 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>

    Nota il nome del Pod e il nome del nodo. Puoi saltare il passaggio successivo.

  2. (Facoltativo) Per ottenere ulteriori dettagli sul Pod e verificare le tolleranze sul Pod, esegui il comando seguente.

    kubectl describe pod <pod_name>

    Un esempio dell'output si trova nella sezione Informazioni aggiuntive.

  3. Per verificare che il posizionamento del Pod sul nodo sia corretto, esegui il comando seguente.

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

    Verificate che la tinta sul nodo corrisponda alla tolleranza e che l'etichetta sul nodo corrisponda all'affinità del nodo definita in. deployment.yaml

    Il Pod con tolleranze e affinità di nodo deve essere posizionato su un nodo con le sfumature corrispondenti e le etichette di affinità del nodo. Il comando precedente fornisce le macchie sul nodo. Di seguito è riportato un esempio di output.

    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

    Inoltre, esegui il comando seguente per verificare che il nodo su cui è posizionato il Pod abbia un'etichetta che corrisponda all'etichetta del nodo di affinità del nodo.

    kubectl get node <node name> --show-labels
  4. Per verificare che l'applicazione stia facendo ciò per cui è destinata, controllate i log del Pod eseguendo il comando seguente.

    kubectl logs -f <name-of-the-pod>
Sviluppatore di app, DevOps ingegnere, AWS DevOps

Crea un secondo file.yaml di distribuzione senza tolleranza e affinità tra i nodi.

Questo passaggio aggiuntivo serve a verificare che, quando non viene specificata alcuna affinità o tolleranza del nodo nel file manifesto di distribuzione, il Pod risultante non sia pianificato su un nodo con macchie. (Dovrebbe essere pianificato su un nodo che non presenta alcun problema). Usa il codice seguente per creare un nuovo file di distribuzione chiamatodeploy_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
Sviluppatore di app, AWS DevOps, DevOps ingegnere

Distribuisci il secondo file.yaml di distribuzione e convalida il posizionamento dei Pod

  1. Esegui il comando seguente.

    kubectl apply -f deploy_no_taint.yaml
  2. Una volta completata la distribuzione, esegui gli stessi comandi che eseguivi in precedenza per verificare il posizionamento del Pod in un gruppo di nodi privo di contaminazioni.

    kubectl describe node <node_name> | grep "Taints"

    L'output dovrebbe essere il seguente.

    Taints: <none>

    Questo completa il test.

Sviluppatore di app, AWS DevOps, DevOps ingegnere
AttivitàDescrizioneCompetenze richieste

Elimina le risorse.

Per evitare di incorrere in costi AWS per le risorse rimaste in esecuzione, usa il seguente comando.

eksctl delete cluster --name <Name of the cluster> --region <region-code>
AWS DevOps, sviluppatore di app

Risoluzione dei problemi

ProblemaSoluzione

Alcuni di questi comandi potrebbero non funzionare se il sistema utilizza l'architettura arm64 (specialmente se la esegui su un Mac M1). La riga seguente potrebbe non funzionare correttamente.

FROM adoptopenjdk/openjdk11:jdk-11.0.14.1_1-alpine

Se riscontri errori durante l'esecuzione del Dockerfile, sostituisci la FROM riga con la riga seguente.

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

Risorse correlate

Informazioni aggiuntive

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

descrivi l'output di esempio del 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>