ノードアフィニティ、テイント、許容範囲を使用して Kubernetes ポッドを Amazon EKS に配置します。 - AWS 規範ガイダンス

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

ノードアフィニティ、テイント、許容範囲を使用して Kubernetes ポッドを Amazon EKS に配置します。

Hitesh Parikh (AWS) とRaghu Bhamidimarri (AWS) によって作成されました

環境:PoC またはパイロット

テクノロジー:コンテナとマイクロサービス

ワークロード:オープンソース

AWS サービス:Amazon EKS

[概要]

このパターンは、Kubernetes ノードアフィニティ、ノードテイント、ポッドトレレーションを使用して、Amazon Web Services (AWS) クラウド上の Amazon Elastic Kubernetes Service (Amazon EKS) クラスター内の特定のワーカーノードにアプリケーションポッドを意図的にスケジュールする方法を示しています。

テイントは、ノードが一連のポッドを拒否できるようにするノードプロパティです。トレレーションは、Kubernetes スケジューラーがテイントが一致するノードにポッドをスケジュールできるようにするポッドプロパティです。

ただし、許容値だけでは、スケジューラーがテイントのないワーカーノードにポッドを配置するのを防ぐことはできません。たとえば、許容範囲のある計算負荷の高いポッドが、テイントされていない汎用のノードに意図せずスケジュールされる可能性があります。このシナリオでは、ポッドのノードアフィニティプロパティは、ノードアフィニティで指定されたノード選択基準を満たすノードにポッドを配置するようにスケジューラーに指示します。

テイント、トレレーション、ノードアフィニティが一体となって、ポッドで指定されたノードアフィニティノード選択基準に一致するテイントとノードラベルを持つノード上で一貫してポッドをスケジュールするようにスケジューラーに指示します。

このパターンは、Kubernetes デプロイマニフェストファイルの例と、EKS クラスターの作成、アプリケーションのデプロイ、ポッド配置の検証の手順を示しています。

前提条件と制限

前提条件

機能制限

  • このパターンは Java コードを提供するものではなく、既に Java に精通していることを前提としています。基本的な Java マイクロサービスを作成するには、Amazon EKS へのサンプル Java マイクロサービスのデプロイ を参照してください。

  • この記事のステップでは、コストが発生する可能性のある AWS リソースを作成します。パターンを実装して検証する手順を完了したら、必ず AWS リソースをクリーンアップしてください。

アーキテクチャ

ターゲットテクノロジースタック

  • Amazon EKS

  • Java

  • Docker

  • Amazon Elastic Container Registry (Amazon ECR)

ターゲット アーキテクチャ

ソリューションアーキテクチャ図は、2 つのポッド (デプロイ 1 とデプロイ 2) と、それぞれ 2 つのノードを持つ 2 つのノードグループ (ng1 と ng2) で構成される Amazon EKS を示しています。トリガー と には、以下のプロパティがあります。

 

デプロイ 1 ポッド

デプロイ 2 ポッド

ノードグループ 1 (ng1)

ノードグループ 2 (ng2)

容認

key: classified_workload、value: true、 effect: NoSchedule

key: machine_ learning_workload、value: true、 effect: NoSchedule

なし

 

 

ノードアフィニティ

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

なし

nodeGroups.name = ng1

 

テイント

 

 

key: classified_workload、value: true、 effect: NoSchedule

key: machine_ learning_workload、value: true、 effect: NoSchedule

なし

  1. Deployment 1 Pod には許容範囲とノードアフィニティが定義されています。これにより、Kubernetes スケジューラーにデプロイメントポッドをノードグループ 1 (ng1) ノードに配置するよう指示されます。

  2. ノードグループ 2 (ng2) にはデプロイ 1 のノードアフィニティノードセレクター式と一致するノードラベルがないため、ポッドは ng2 ノードでスケジュールされません。

  3. Deployment 2 ポッドには、デプロイマニフェストで許容範囲やノードアフィニティが定義されていません。ノードにテイントがあるため、スケジューラーはノードグループ 1 でのデプロイ 2 ポッドのスケジュールを拒否します。

  4. ノードにはテイントがないため、デプロイ 2 ポッドは代わりにノードグループ 2 に配置されます。

このパターンは、テイントとトレレーションをノードアフィニティと組み合わせて使用することで、特定のワーカーノードセットでのポッドの配置を制御できることを示しています。

ツール

AWS サービス

その他のツール

  • Docker は、オペレーティングシステムレベルの仮想化を使用してソフトウェアをコンテナで配信するサービスとしてのPlatform as a Service (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 エンジニア、アプリ開発者

Dockerfile を作成します。

パターンのテストに使用する 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 とソースファイルを作成し、Docker イメージをビルドしてプッシュします。

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
アプリ開発者、 DevOps エンジニア、AWS DevOps

デプロイを確認してください。

  1. 次のコマンドを実行して、ポッドの準備が整っているかどうかを確認します。

    kubectl get pods -o wide

    ポッドの準備が整うと、出力は Running 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. 次のコマンドを実行して、ノードのポッドの配置が正しいことを確認します。

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

    ノードのテイントが許容範囲と一致し、ノードのラベルが deployment.yaml で定義されたノードアフィニティと一致することを確認します。

    許容範囲とノードアフィニティが設定されたポッドは、テイントとノードアフィニティラベルが一致するノードに配置する必要があります。前のコマンドでは、ノード上のテイントが表示されます。以下に出力例を示します。

    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

    さらに、以下のコマンドを実行して、ノードが配置されているノードのラベルがノードアフィニティノードのラベルと一致していることを確認します。

    kubectl get node <node name> --show-labels
  4. アプリケーションが意図したとおりに動作していることを確認するには、以下のコマンドを実行してノードのログを確認します。

    kubectl logs -f <name-of-the-pod>
アプリ開発者、 DevOps エンジニア、AWS DevOps

許容範囲やノードアフィニティなしで 2 つ目のデプロイ.yaml ファイルを作成します。

この追加ステップは、デプロイメントマニフェストファイルにノードアフィニティや許容値が指定されていない場合に、生成されるポッドがテイントのあるノードにスケジュールされないことを検証することです。(テイントのないノードでスケジュールする必要があります)。次のコードを使用して、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 エンジン

2 番目のデプロイ.yaml ファイルをデプロイし、ポッドの配置を検証します。

  1. 以下のコマンドを実行します。

    kubectl apply -f deploy_no_taint.yaml
  2. デプロイが成功したら、前に実行したのと同じコマンドを実行して、ノードグループ内のポッドの配置をテイントなく確認します。

    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

Dockerfile の実行中にエラーが発生した場合は、FROM その行を次の行に置き換えてください。

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

関連リソース

追加情報

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

ポッドのサンプル出力を説明してください

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>