すべてのプロダクト
Search
ドキュメントセンター

Elastic Container Instance:Elastic Container Instance ベースの Pod をゾーン全体に分散し、アフィニティを設定する

最終更新日:Dec 28, 2024

高可用性と高パフォーマンスは、分散ジョブにとって不可欠です。Container Service for Kubernetes (ACK) Pro クラスタまたは ACK Serverless Pro クラスタでは、Kubernetes ネイティブのスケジューリングセマンティクスに基づいて、分散タスクをゾーン全体に分散できます。また、Kubernetes ネイティブのスケジューリングセマンティクスに基づいてアフィニティを設定し、特定のゾーンに分散タスクをデプロイすることもできます。これにより、タスクデプロイの効率が向上します。このトピックでは、Elastic Container Instance ベースの Pod をゾーン全体に分散する方法と、Pod のアフィニティを設定する方法について説明します。

背景情報

特定のシナリオでは、高可用性または高パフォーマンスを実現するために、複数のゾーンまたは特定のゾーンに Pod をデプロイする必要があります。このような場合は、Pod トポロジスプレッド制約 (topologySpreadConstraints)、ノードアフィニティ (nodeAffinity)、Pod アフィニティ (podAffinity) などの Kubernetes ネイティブのスケジューリング機能を使用できます。

重要

Elastic Container Instance ベースの Pod をゾーン全体に分散したり、Pod のアフィニティを設定したりできるのは、nodeAffinitypodAffinitytopologySpreadConstraints パラメータが Pod に設定されている場合、または Pod が既存のリソースポリシーと一致する場合のみです。

詳細については、次の Kubernetes 公式ドキュメントを参照してください。

前提条件

使用上の注意

  • topologyKey パラメータを topology.kubernetes.io/zone に設定する必要があります。

  • このトピックで説明されている機能は、次のシナリオでは有効になりません。

    • k8s.aliyun.com/eci-schedule-strategy: "VSwitchOrdered" アノテーションを使用して、指定された vSwitch 順序に従う複数ゾーンのスケジューリング戦略を Pod に宣言している場合。

    • k8s.aliyun.com/eci-fail-strategy: "fail-fast" アノテーションを使用して、Pod の障害処理ポリシーを fail-fast に設定している場合。

設定例

以下のセクションでは、Kubernetes バージョンが 1.22 の ACK Serverless Pro クラスタを使用して、Pod をゾーン全体に分散する方法とアフィニティを設定する方法について説明します。

例 1: topologySpreadConstraints を使用して Pod をゾーン全体に分散する

説明

次の例は、トポロジスプレッド制約を設定する方法を示しています。デフォルトでは、Scheduler はすべての Pod をすべてのゾーンに均等にスケジュールしますが、Pod の生成結果は考慮しません。詳細については、厳密な Elastic Container Instance ベースの Pod トポロジスプレッド を参照してください。

  1. ワークロードの設定にトポロジスプレッド制約を追加します。

    Pod の設定の Spec パラメータ、または Deployment や Job などのワークロードの設定の Spec パラメータにトポロジスプレッド制約を指定するには、次の手順を実行します。

      topologySpreadConstraints:
        - maxSkew: <integer>
          minDomains: <integer> # このパラメータはオプションであり、Kubernetes 1.25 以降ではベータ段階です。
          topologyKey: <string>
          whenUnsatisfiable: <string>
          labelSelector: <object>
          matchLabelKeys: <list> # このパラメータはオプションであり、Kubernetes 1.27 以降ではベータ段階です。
          nodeAffinityPolicy: [Honor|Ignore] # このパラメータはオプションであり、Kubernetes 1.26 以降ではベータ段階です。
          nodeTaintsPolicy: [Honor|Ignore] # このパラメータはオプションであり、Kubernetes 1.26 以降ではベータ段階です。

    この例では、Pod が複数のゾーンに均等に分散される Deployment を作成します。パラメータの詳細については、topologySpreadConstraints field を参照してください。次のコードブロックは、Deployment の YAML テンプレートを示しています。

    YAML コンテンツを表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: with-pod-topology-spread
      labels:
        app: with-pod-topology-spread
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: with-pod-topology-spread
      template:
        metadata:
          labels:
            app: with-pod-topology-spread
        spec:
          topologySpreadConstraints:
            - maxSkew: 1
              topologyKey: topology.kubernetes.io/zone
              whenUnsatisfiable: DoNotSchedule
              labelSelector:
                matchLabels:
                  app: with-pod-topology-spread
          containers:
          - name: with-pod-topology-spread
            image: registry.k8s.io/pause:2.0
            resources:
              requests:
                cpu: "1"
                memory: "256Mi"
  2. ワークロードを作成します。

    deployment.yaml という名前のファイルを作成し、上記の YAML テンプレートをファイルにコピーします。次に、次のコマンドを実行して、クラスタに Deployment を作成します。

    kubectl apply -f deployment.yaml
  3. ワークロードのスケジューリング結果を確認します。

    • 次のコマンドを実行して、Deployment が Pod をデプロイするノードをクエリします。

      kubectl get po -lapp=with-pod-topology-spread -ocustom-columns=NAME:.metadata.name,NODE:.spec.nodeName --no-headers | grep -v "<none>"
    • 次のコマンドを実行して、各ゾーンで Deployment によって作成された Pod の数をクエリします。

      kubectl get po -lapp=with-pod-topology-spread -ocustom-columns=NODE:.spec.nodeName --no-headers | grep -v "<none>" | xargs -I {} kubectl get no {} -ojson | jq '.metadata.labels["topology.kubernetes.io/zone"]' | sort | uniq -c

例 2: nodeAffinity と podAffinity を使用して特定のゾーンに Pod をデプロイする

  1. ワークロードの設定にアフィニティを追加します。

    この例では、Pod が単一ゾーンにデプロイされる Deployment を作成します。パラメータの詳細については、Node affinity を参照してください。次のコードブロックは、Deployment の YAML テンプレートを示しています。

    YAML コンテンツを表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: with-affinity
      labels:
        app: with-affinity
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: with-affinity
      template:
        metadata:
          labels:
            app: with-affinity
        spec:
          affinity:
            podAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - with-affinity
                topologyKey: topology.kubernetes.io/zone
          containers:
          - name: with-affinity
            image: registry.k8s.io/pause:2.0

    特定のゾーンに Pod をデプロイする場合は、podAffinity パラメータを削除し、nodeAffinity パラメータに次の制約を追加します。次の設定では、Pod を北京ゾーン A にデプロイする必要があることを指定しています。

    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - cn-beijing-a

    次のコードブロックは、nodeAffinity パラメータを含むサンプルコードを示しています。Pod は北京ゾーン A にのみデプロイされます。

    YAML コンテンツを表示

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: with-affinity
      labels:
        app: with-affinity
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: with-affinity
      template:
        metadata:
          labels:
            app: with-affinity
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - cn-beijing-a
          containers:
          - name: with-affinity
            image: registry.k8s.io/pause:2.0
  2. ワークロードを作成します。

    deployment.yaml という名前のファイルを作成し、上記の YAML テンプレートをファイルにコピーします。次に、次のコマンドを実行して、クラスタに Deployment を作成します。

    kubectl apply -f deployment.yaml
  3. ワークロードのスケジューリング結果を確認します。

    • 次のコマンドを実行して、Deployment が Pod をデプロイするノードをクエリします。

      kubectl get po -lapp=with-affinity -ocustom-columns=NAME:.metadata.name,NODE:.spec.nodeName --no-headers | grep -v "<none>"
    • 次のコマンドを実行して、各ゾーンで Deployment によって作成された Pod の数をクエリします。

      kubectl get po -lapp=with-affinity -ocustom-columns=NODE:.spec.nodeName --no-headers | grep -v "<none>" | xargs -I {} kubectl get no {} -ojson | jq '.metadata.labels["topology.kubernetes.io/zone"]' | sort | uniq -c

厳密な Elastic Container Instance ベースの Pod トポロジスプレッド

デフォルトでは、Elastic Container Instance ベースの Pod をゾーン全体に強制的に分散する場合、kube-scheduler はワークロードの Pod をすべてのゾーンに均等にデプロイします。ただし、Elastic Container Instance ベースの Pod は一部のゾーンで作成に失敗する可能性があります。次の図は、maxSkew パラメータが 1 に設定されている場合のスケジューリング結果を示しています。maxSkew の詳細については、maxSkew を参照してください。

ゾーン B とゾーン C で Elastic Container Instance ベースの Pod の作成に失敗した場合、2 つの Elastic Container Instance ベースの Pod がゾーン A で実行され、ゾーン B またはゾーン C では Elastic Container Instance ベースの Pod は実行されません。これは、maxSkew パラメータで指定された制約に違反しています。

ACK Serverless Pro クラスタ では、厳密な Elastic Container Instance ベースの Pod トポロジスプレッドを有効にして、Pod がゾーン全体に厳密に分散されるようにすることができます。厳密な Elastic Container Instance ベースの Pod トポロジスプレッドを有効にすると、kube-scheduler はまず、ゾーン A、ゾーン B、ゾーン C のそれぞれに Pod をスケジュールします。kube-scheduler は、スケジュールされた Pod が作成されるまで、保留中の Pod をスケジュールしません。次の図を参照してください。

Pod A1 が作成された場合でも、保留中の Pod はスケジュールされません。これは、ゾーン B またはゾーン C で Pod の作成に失敗した場合、maxSkew パラメータで指定された制約に違反するためです。Pod B1 が作成されると、kube-scheduler はゾーン C に Pod をスケジュールします。緑色の網掛けが付いた Pod は作成されています。

厳密な Elastic Container Instance ベースの Pod トポロジスプレッドを無効にする場合は、whenUnsatisfiable パラメータを ScheduleAnyway に設定します。詳細については、Spread constraint definition を参照してください。