使用節點相似性、污點和容許,將 Kubernetes 網繭放置在 Amazon EKS 上 - AWS 方案指引

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用節點相似性、污點和容許,將 Kubernetes 網繭放置在 Amazon EKS 上

由希特斯·帕里赫(AWS)和拉格·比米迪馬里(AWS)創建

環境:PoC 或試點

技術:容器與微服務

工作負載:開源

AWS 服務:Amazon EKS

Summary

此模式示範如何使用 Kubernetes 節點相似性、節點和網繭容許,在 Amazon Web 服務 (AWS) 雲端上的 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集中有意排程應用程式 Amazon Web Services 繭上的特定工作者節點。

污染是一種節點屬性,可讓節點拒絕一組網繭。容許是一種網繭內容,可讓 Kubernetes 排程器在具有相符污染的節點上排程網繭。

不過,單獨的容許無法防止排程器將 Pod 放置在沒有任何污染的背景工作節點上。例如,具有容許功能的運算密集型 Pod 可能會無意中排程在一般用途未受污染的節點上。在該案例中,網繭的節點相似性內容會指示排程器將網繭置於符合節點相似性中指定之節點選取準則的節點上。

污染、容許和節點相似性一起指示排程器在具有相符污點的節點上一致地排程網繭,以及符合在網繭上指定的節點相似性節點選取準則的節點標籤。

此模式提供 Kubernetes 部署資訊清單檔案範例,以及建立 EKS 叢集、部署應用程式和驗證網繭放置的步驟。

先決條件和限制

先決條件

限制

  • 此模式不提供 Java 代碼,並假定您已經熟悉 Java。若要建立基本的 Java 微服務,請參閱在 Amazon EKS 上部署範例 Java 微服務

  • 本文中的步驟建立可累積成本的 AWS 資源。請務必在完成實作和驗證模式的步驟之後清理 AWS 資源。

架構

目標技術堆疊

  • Amazon EKS

  • Java

  • Docker

  • Amazon Elastic Container Registry (Amazon ECR)

目標架構

解決方案架構圖顯示具有兩個網繭 (部署 1 和部署 2) 的 Amazon EKS,以及兩個節點群組 (ng1 和 ng2),每個節點各有兩個節點。網繭和節點具有下列屬性。

 

部署 1 個網繭

部署 2 網繭

節點群組 1

節點群組 2

寬容

鍵:分類工作負載, 值:真, 效果: NoSchedule

關鍵:機器學習工作負載,值:真,效果: NoSchedule

 

 

節點相似性

鍵:阿爾法 .eksctl.io /節點組名稱 = ng1;

節點群組. 名稱 = ng1

 

污點

 

 

鍵:分類工作負載, 值:真, 效果: NoSchedule

關鍵:機器學習工作負載,值:真,效果: NoSchedule

具有兩個網繭和兩個節點群組的 Amazon EKS 組態。
  1. 部署 1 網繭已定義容許和節點相似性,這會指示 Kubernetes 排程器將部署網繭放在節點群組 1 (ng1) 節點上。

  2. 節點群組 2 (ng2) 沒有符合部署 1 的節點相似性節點選取器運算式的節點標籤,因此 Pod 不會排程在 ng2 節點上。

  3. 部署 2 Pod 沒有在部署資訊清單中定義任何容許或節點相似性。由於節點上的污點,排程器將拒絕排程節點群組 1 上的部署 2 Pod。

  4. 部署 2 Pod 將改為放置在節點群組 2 上,因為節點沒有任何污點。

此模式示範,透過使用污點和容許結合節點相似性,您可以控制 Pod 在特定工作節點集上的放置。

工具

AWS 服務

其他工具

  • Docker 是一組平台即服務 (PaaS) 產品,它們在作業系統層級使用虛擬化,在容器中提供軟體。

  • kubectl 是一種命令列介面,可協助您針對 Kubernetes 叢集執行命令。

史诗

任務描述所需技能

建立叢集 .yaml 檔案。

cluster.yaml使用下面的代碼創建一個名為的文件。

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
應用程式擁有者、AWS DevOps、雲端管理員、 DevOps 工程師

使用 eksctl 建立叢集。

執行cluster.yaml檔案以建立 EKS 叢集。建立叢集可能需要幾分鐘的時間。

eksctl create cluster -f cluster.yaml
AWS DevOps、AWS 系統管理員、應用程式開發人員
任務描述所需技能

建立 Amazon ECR 私有儲存庫。

若要建立 Amazon ECR 儲存庫,請參閱建立私有存放庫。請注意回購的 URI。

AWS DevOps、 DevOps 工程師、應用程式開發者

創建碼頭文件。

如果您有要用來測試模式的現有 Docker 容器映像檔,則可以略過此步驟。

要創建一個 Dockerfile,請使用以下代碼片段作為參考。如果您遇到錯誤,請參閱疑難排解一節。

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 工程師

創建 pom.xml 和源文件,並構建和推送碼頭映像。

若要建立pom.xml檔案和 Java 來源檔案,請參閱在 Amazon EKS 模式上部署範例 Java 微服務

使用該模式中的說明來構建和推送 Docker 映像。

AWS DevOps、 DevOps 工程師、應用程式開發者
任務描述所需技能

建立部署的 .yaml 檔案。

若要建立deployment.yaml檔案,請使用 [其他資訊] 區段中的程式碼。

在程式碼中,節點相似性的索引鍵是您在建立節點群組時建立的任何標籤。此模式使用 eksctl 創建的默認標籤。如需自訂標籤的相關資訊,請參閱 Kubernetes 文件中的將網繭指派給節點

節點相似性索引鍵的值是由建立的節點群組名稱cluster.yaml

若要取得污點的索引鍵和值,請執行下列命令。

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

映像檔是您在先前步驟中建立的 Amazon ECR 儲存庫的 URI。

AWS DevOps、 DevOps 工程師、應用程式開發者

部署檔案。

若要部署到 Amazon EKS,請執行下列命令。

kubectl apply -f deployment.yaml
AWS 應用程式開發人員、 DevOps 工程師 DevOps

檢查部署。

  1. 若要檢查網繭是否已就緒,請執行下列命令。

    kubectl get pods -o wide

    如果 POD 已準備就緒,輸出應類似下列內容,並顯示STATUS為「執行中」。

    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>

    記下網繭的名稱和節點的名稱。您可以跳過下一步。

  2. (選擇性) 若要取得有關網繭的其他詳細資料並檢查網繭上的容許,請執行下列命令。

    kubectl describe pod <pod_name>

    輸出的範例位於 [其他資訊] 區段中。

  3. 若要驗證節點上的 Pod 放置是否正確,請執行下列命令。

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

    確認節點上的污點符合公差,且節點上的標籤符合中定義的節點相似性。deployment.yaml

    具有容許和節點相似性的 Pod 應放置在具有相符污點和節點相似性標籤的節點上。上一個指令會提供節點上的污點。以下為範例輸出。

    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

    此外,執行下列命令,以檢查所放置 Pod 的節點是否具有符合節點相似性節點標籤的標籤。

    kubectl get node <node name> --show-labels
  4. 若要確認應用程式是否正在執行其所要執行的動作,請執行下列命令來檢查 Pod 記錄。

    kubectl logs -f <name-of-the-pod>
AWS 應用程式開發人員、 DevOps 工程師 DevOps

建立沒有容許和節點相似性的第二個部署 .yaml 檔案。

此額外步驟是驗證在部署資訊清單檔案中未指定任何節點相似性或容許時,產生的 Pod 不會在具有污染物的節點上排程。(它應該安排在沒有任何污點的節點上)。使用下列程式碼建立名為的新部署檔案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
應用開發人員、AWS DevOps、 DevOps 工程師

部署第二個部署 .yaml 檔案,並驗證網繭放置

  1. 執行下列命令。

    kubectl apply -f deploy_no_taint.yaml
  2. 部署成功後,請執行先前執行的相同命令,以檢查節點群組中的 Pod 位置,而不會造成污染。

    kubectl describe node <node_name> | grep "Taints"

    輸出應該是以下內容。

    Taints: <none>

    這樣就完成了測試。

應用開發人員、AWS DevOps、 DevOps 工程師
任務描述所需技能

清除資源。

若要避免對仍在執行的資源產生 AWS 費用,請使用下列命令。

eksctl delete cluster --name <Name of the cluster> --region <region-code>
AWS 應用程 DevOps式開發人員

故障診斷

問題解決方案

如果您的系統使用 arm64 架構(特別是在 M1 Mac 上運行此體系結構),則其中一些命令可能無法運行。以下行可能會出錯。

FROM adoptopenjdk/openjdk11:jdk-11.0.14.1_1-alpine

如果您在運行 Docker 文件時出現錯誤,請用以下FROM行替換該行。

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

相關資源

其他資訊

部署. 羊

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

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