2.6. ノードテイントを使用した Pod 配置の制御

テイントおよび容認 (Toleration) により、ノードはノード上でスケジュールする必要のある (またはスケジュールすべきでない) Pod を制御できます。

2.6.1. テイントおよび容認 (Toleration) について

テイント により、ノードは Pod に一致する 容認 がない場合に Pod のスケジュールを拒否することができます。

テイントは Node 仕様 (NodeSpec) でノードに適用され、容認は Pod 仕様 (PodSpec) で Pod に適用されます。テイントをノードに適用する場合、スケジューラーは Pod がテイントを容認しない限り、Pod をそのノードに配置することができません。

ノード仕様のテイントの例

spec:
....
  template:
....
    spec:
      taints:
      - effect: NoExecute
        key: key1
        value: value1
....

Pod 仕様での容認の例

spec:
....
  template:
....
    spec
      tolerations:
      - key: "key1"
        operator: "Equal"
        value: "value1"
        effect: "NoExecute"
        tolerationSeconds: 3600
....

テイントおよび容認は、key、value、および effect で構成されています。

表2.1 テイントおよび容認コンポーネント

パラメーター説明

key

key には、253 文字までの文字列を使用できます。キーは文字または数字で開始する必要があり、文字、数字、ハイフン、ドットおよびアンダースコアを含めることができます。

value

value には、63 文字までの文字列を使用できます。値は文字または数字で開始する必要があり、文字、数字、ハイフン、ドットおよびアンダースコアを含めることができます。

effect

effect は以下のいずれかにすることができます。

NoSchedule[1]

  • テイントに一致しない新規 Pod はノードにスケジュールされません。
  • ノードの既存 Pod はそのままになります。

PreferNoSchedule

  • テイントに一致しない新規 Pod はノードにスケジュールされる可能性がありますが、スケジューラーはスケジュールしないようにします。
  • ノードの既存 Pod はそのままになります。

NoExecute

  • テイントに一致しない新規 Pod はノードにスケジュールできません。
  • 一致する容認を持たないノードの既存 Pod は削除されます。

operator

Equal

key/value/effect パラメーターは一致する必要があります。これはデフォルトになります。

Exists

key/effect パラメーターは一致する必要があります。いずれかに一致する value パラメーターを空のままにする必要があります。

  1. NoSchedule テイントをマスターノードに追加する場合、ノードには、デフォルトで追加される node-role.kubernetes.io/master=:NoSchedule テイントが必要です。

    以下は例になります。

    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        machine.openshift.io/machine: openshift-machine-api/ci-ln-62s7gtb-f76d1-v8jxv-master-0
        machineconfiguration.openshift.io/currentConfig: rendered-master-cdc1ab7da414629332cc4c3926e6e59c
    ...
    spec:
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    ...

容認はテイントと一致します。

  • operator パラメーターが Equal に設定されている場合:

    • key パラメーターは同じになります。
    • value パラメーターは同じになります。
    • effect パラメーターは同じになります。
  • operator パラメーターが Exists に設定されている場合:

    • key パラメーターは同じになります。
    • effect パラメーターは同じになります。

以下のテイントは OpenShift Container Platform に組み込まれています。

  • node.kubernetes.io/not-ready: ノードは準備状態にありません。これはノード条件 Ready=False に対応します。
  • node.kubernetes.io/unreachable: ノードはノードコントローラーから到達不能です。これはノード条件 Ready=Unknown に対応します。
  • node.kubernetes.io/out-of-disk: ノードには新しい Pod を追加するためのノード上の空きスペースが十分にありません。これはノード条件 OutOfDisk=True に対応します。
  • node.kubernetes.io/memory-pressure: ノードにはメモリー不足の問題が発生しています。これはノード条件 MemoryPressure=True に対応します。
  • node.kubernetes.io/disk-pressure: ノードにはディスク不足の問題が発生しています。これはノード条件 DiskPressure=True に対応します。
  • node.kubernetes.io/network-unavailable: ノードのネットワークは使用できません。
  • node.kubernetes.io/unschedulable: ノードはスケジュールが行えません。
  • node.cloudprovider.kubernetes.io/uninitialized: ノードコントローラーが外部のクラウドプロバイダーを使って起動すると、このテイントはノード上に設定され、使用不可能とマークされます。cloud-controller-manager のコントローラーがこのノードを初期化した後に、kubelet がこのテイントを削除します。

2.6.1.1. Pod のエビクションを遅延させる容認期間 (秒数) の使用方法

Pod 仕様または MachineSettolerationSeconds パラメーターを指定して、Pod がエビクションされる前にノードにバインドされる期間を指定できます。effect が NoExecute のテイントがノードに追加される場合、テイントを容認する Pod に tolerationSeconds パラメーターがある場合、Pod は期限切れになるまでエビクトされません。

出力例

spec:
....
  template:
....
    spec
      tolerations:
      - key: "key1"
        operator: "Equal"
        value: "value1"
        effect: "NoExecute"
        tolerationSeconds: 3600

ここで、この Pod が実行中であるものの、一致するテイントがない場合、Pod は 3,600 秒間バインドされたままとなり、その後にエビクトされます。テイントが期限前に削除される場合、Pod はエビクトされません。

2.6.1.2. 複数のテイントの使用方法

複数のテイントを同じノードに、複数の容認を同じ Pod に配置することができます。OpenShift Container Platform は複数のテイントと容認を以下のように処理します。

  1. Pod に一致する容認のあるテイントを処理します。
  2. 残りの一致しないテイントは Pod について以下の effect を持ちます。

    • effect が NoSchedule の一致しないテイントが 1 つ以上ある場合、OpenShift Container Platform は Pod をノードにスケジュールできません。
    • effect が NoSchedule の一致しないテイントがなく、effect が PreferNoSchedule の一致しない テイントが 1 つ以上ある場合、OpenShift Container Platform は Pod のノードへのスケジュールを試行しません。
    • effect が NoExecute のテイントが 1 つ以上ある場合、OpenShift Container Platform は Pod をノードからエビクトするか (ノードですでに実行中の場合)、または Pod のそのノードへのスケジュールが実行されません (ノードでまだ実行されていない場合)。

      • テイントを容認しない Pod はすぐにエビクトされます。
      • Pod の仕様に tolerationSeconds を指定せずにテイントを容認する Pod は永久にバインドされたままになります。
      • 指定された tolerationSeconds を持つテイントを容認する Pod は指定された期間バインドされます。

以下は例になります。

  • 以下のテイントをノードに追加します。

    $ oc adm taint nodes node1 key1=value1:NoSchedule
    $ oc adm taint nodes node1 key1=value1:NoExecute
    $ oc adm taint nodes node1 key2=value2:NoSchedule
  • Pod には以下の容認があります。

    spec:
    ....
      template:
    ....
        spec
          tolerations:
          - key: "key1"
            operator: "Equal"
            value: "value1"
            effect: "NoSchedule"
          - key: "key1"
            operator: "Equal"
            value: "value1"
            effect: "NoExecute"

この場合、3 つ目のテイントに一致する容認がないため、Pod はノードにスケジュールできません。Pod はこのテイントの追加時にノードですでに実行されている場合は実行が継続されます。 3 つ目のテイントは 3 つのテイントの中で Pod で容認されない唯一のテイントであるためです。

2.6.1.3. Pod のスケジューリングとノードの状態 (Taint Nodes By Condition) について

Taint Nodes By Condition (状態別のノードへのテイント) 機能はデフォルトで有効にされており、これはメモリー不足やディスク不足などの状態を報告するノードを自動的にテイントします。ノードが状態を報告すると、その状態が解消するまでテイントが追加されます。テイントに NoSchedule の effect がある場合、ノードが一致する容認を持つまでそのノードに Pod をスケジュールすることはできません。

スケジューラーは、Pod をスケジュールする前に、ノードでこれらのテイントの有無をチェックします。テイントがある場合、Pod は別のノードにスケジュールされます。スケジューラーは実際のノードの状態ではなくテイントをチェックするので、適切な Pod 容認を追加して、スケジューラーがこのようなノードの状態を無視するように設定します。

デーモンセットコントローラーは、以下の容認をすべてのデーモンに自動的に追加し、下位互換性を確保します。

  • node.kubernetes.io/memory-pressure
  • node.kubernetes.io/disk-pressure
  • node.kubernetes.io/out-of-disk (Critical Pod の場合のみ)
  • node.kubernetes.io/unschedulable (1.10 以降)
  • node.kubernetes.io/network-unavailable (ホストネットワークのみ)

デーモンセットには任意の容認を追加することも可能です。

2.6.1.4. Pod の状態別エビクションについて (Taint-Based Eviction)

Taint-Based Eviction 機能はデフォルトで有効にされており、これは not-ready および unreachable などの特定の状態にあるノードから Pod をエビクトします。ノードがこうした状態のいずれかになると、OpenShift Container Platform はテイントをノードに自動的に追加して、Pod のエビクトおよび別のノードでの再スケジュールを開始します。

Taint Based Eviction には NoExecute の effect があり、そのテイントを容認しない Pod はすぐにエビクトされ、これを容認する Pod はエビクトされません (Pod が tolerationsSeconds パラメーターを使用しない場合に限ります)。

tolerationSeconds パラメーターを使用すると、ノード状態が設定されたノードに Pod がどの程度の期間バインドされるかを指定することができます。tolerationSections の期間後もこの状態が続くと、テイントはノードに残り続け、一致する容認を持つ Pod はエビクトされます。tolerationSeconds の期間前にこの状態が解消される場合、一致する容認を持つ Pod は削除されません。

値なしで tolerationSeconds パラメーターを使用する場合、Pod は 「not ready」(準備未完了) および「unreachable」(到達不能) のノードの状態が原因となりエビクトされることはありません。

注記

OpenShift Container Platform は、レートが制限された方法で Pod をエビクトし、マスターがノードからパーティション化される場合などのシナリオで発生する大規模な Pod エビクションを防ぎます。

OpenShift Container Platform は、node.kubernetes.io/not-ready および node.kubernetes.io/unreachable の容認を、Pod 設定がいずれかの容認を指定しない限り、自動的に tolerationSeconds=300 に追加します。

spec:
....
  template:
....
    spec
      tolerations:
      - key: node.kubernetes.io/not-ready
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 300 1
      - key: node.kubernetes.io/unreachable
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 300
1
これらの容認は、ノード状態の問題のいずれかが検出された後、デフォルトの Pod 動作のバインドを 5 分間維持できるようにします。

これらの容認は必要に応じて設定できます。たとえば、アプリケーションに多数のローカル状態がある場合、ネットワークのパーティション化などに伴い、Pod をより長い時間ノードにバインドさせる必要があるかもしれません。 これにより、パーティションを回復させることができ、Pod のエビクションを回避できます。

デーモンセットによって起動する Podは、tolerationSeconds が指定されない以下のテイントの NoExecute 容認を使用して作成されます。

  • node.kubernetes.io/unreachable
  • node.kubernetes.io/not-ready

その結果、デーモンセット Pod は、これらのノードの状態が原因でエビクトされることはありません。

2.6.1.5. すべてのテイントの許容

ノードは、operator: "Exists" 容認を key および value パラメーターなしで追加することですべてのテイントを容認するように Pod を設定できます。この容認のある Pod はテイントを持つノードから削除されません。

すべてのテイントを容認するための Pod 仕様

spec:
....
  template:
....
    spec
      tolerations:
      - operator: "Exists"

2.6.2. テイントおよび容認 (Toleration) の追加

容認を Pod に、テイントをノードに追加することで、ノードはノード上でスケジュールする必要のある (またはスケジュールすべきでない) Pod を制御できます。既存の Pod およびノードの場合、最初に容認を Pod に追加してからテイントをノードに追加して、容認を追加する前に Pod がノードから削除されないようにする必要があります。

手順

  1. Pod 仕様を tolerations スタンザを含めるように編集して、容認を Pod に追加します。

    Equal 演算子を含む Pod 設定ファイルのサンプル

    spec:
    ....
      template:
    ....
        spec:
          tolerations:
          - key: "key1" 1
            value: "value1"
            operator: "Equal"
            effect: "NoExecute"
            tolerationSeconds: 3600 2

    1
    テイントおよび容認コンポーネント の表で説明されている toleration パラメーターです。
    2
    tolerationSeconds パラメーターは、エビクトする前に Pod をどの程度の期間ノードにバインドさせるかを指定します。

    以下は例になります。

    Exists 演算子を含む Pod 設定ファイルのサンプル

    spec:
    ....
      template:
    ....
        spec:
          tolerations:
          - key: "key1"
            operator: "Exists" 1
            effect: "NoExecute"
            tolerationSeconds: 3600

    1
    Exists Operator は value を取りません。

    この例では、テイントを、キーkey1、値 value1、およびテイント effect NoExecute を持つ node1 にテイントを配置します。

  2. テイントおよび容認コンポーネント の表で説明されているパラメーターと共に以下のコマンドを使用してテイントをノードに追加します。

    $ oc adm taint nodes <node_name> <key>=<value>:<effect>

    以下は例になります。

    $ oc adm taint nodes node1 key1=value1:NoExecute

    このコマンドは、キー key1、値 value1、および effect NoExecute を持つテイントを node1 に配置します。

    注記

    NoSchedule テイントをマスターノードに追加する場合、ノードには、デフォルトで追加される node-role.kubernetes.io/master=:NoSchedule テイントが必要です。

    以下は例になります。

    apiVersion: v1
    kind: Node
    metadata:
      annotations:
        machine.openshift.io/machine: openshift-machine-api/ci-ln-62s7gtb-f76d1-v8jxv-master-0
        machineconfiguration.openshift.io/currentConfig: rendered-master-cdc1ab7da414629332cc4c3926e6e59c
    ...
    spec:
      taints:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
    ...

    Pod の容認はノードのテイントに一致します。いずれかの容認のある Pod は node1 にスケジュールできます。

2.6.2.1. マシンセットを使用したテイントおよび容認の追加

マシンセットを使用してテイントをノードに追加できます。MachineSet オブジェクトに関連付けられるすべてのノードがテイントで更新されます。容認は、ノードに直接追加されたテイントと同様に、マシンセットによって追加されるテイントに応答します。

手順

  1. Pod 仕様を tolerations スタンザを含めるように編集して、容認を Pod に追加します。

    Equal 演算子を含む Pod 設定ファイルのサンプル

    spec:
    ....
      template:
    ....
        spec:
          tolerations:
          - key: "key1" 1
            value: "value1"
            operator: "Equal"
            effect: "NoExecute"
            tolerationSeconds: 3600 2

    1
    テイントおよび容認コンポーネント の表で説明されている toleration パラメーターです。
    2
    tolerationSeconds パラメーターは、エビクトする前に Pod をどの程度の期間ノードにバインドさせるかを指定します。

    以下は例になります。

    Exists 演算子を含む Pod 設定ファイルのサンプル

    spec:
    ....
      template:
    ....
        spec:
          tolerations:
          - key: "key1"
            operator: "Exists"
            effect: "NoExecute"
            tolerationSeconds: 3600

  2. テイントを MachineSet オブジェクトに追加します。

    1. テイントを付けるノードの MachineSet YAML を編集するか、または新規 MachineSet オブジェクトを作成できます。

      $ oc edit machineset <machineset>
    2. テイントを spec.template.spec セクションに追加します。

      ノード仕様のテイントの例

      spec:
      ....
        template:
      ....
          spec:
            taints:
            - effect: NoExecute
              key: key1
              value: value1
      ....

      この例では、キー key1、値 value1、およびテイント effect NoExecute を持つテイントをノードに配置します。

    3. マシンセットを0 にスケールダウンします。

      $ oc scale --replicas=0 machineset <machineset> -n openshift-machine-api

      マシンが削除されるまで待機します。

    4. マシンセットを随時スケールアップします。

      $ oc scale --replicas=2 machineset <machineset> -n openshift-machine-api

      マシンが起動するまで待ちます。テイントは MachineSet オブジェクトに関連付けられたノードに追加されます。

2.6.2.2. テイントおよび容認 (Toleration) 使ってユーザーをノードにバインドする

ノードのセットを特定のユーザーセットによる排他的な使用のために割り当てる必要がある場合、容認をそれらの Pod に追加します。次に、対応するテイントをそれらのノードに追加します。容認が設定された Pod は、テイントが付けられたノードまたはクラスター内の他のノードを使用できます。

Pod がテイントが付けられたノードのみにスケジュールされるようにするには、ラベルを同じノードセットに追加し、ノードのアフィニティーを Pod に追加し、Pod がそのラベルの付いたノードのみにスケジュールできるようにします。

手順

ノードをユーザーの使用可能な唯一のノードとして設定するには、以下を実行します。

  1. 対応するテイントをそれらのノードに追加します。

    以下は例になります。

    $ oc adm taint nodes node1 dedicated=groupName:NoSchedule
  2. カスタム受付コントローラーを作成して容認を Pod に追加します。

2.6.2.3. テイントおよび容認 (Toleration) を使って特殊ハードウェアを持つノードを制御する

ノードの小規模なサブセットが特殊ハードウェアを持つクラスターでは、テイントおよび容認 (Toleration) を使用して、特殊ハードウェアを必要としない Pod をそれらのノードから切り離し、特殊ハードウェアを必要とする Pod をそのままにすることができます。また、特殊ハードウェアを必要とする Pod に対して特定のノードを使用することを要求することもできます。

これは、特殊ハードウェアを必要とする Pod に容認を追加し、特殊ハードウェアを持つノードにテイントを付けることで実行できます。

手順

特殊ハードウェアを持つノードが特定の Pod 用に予約されるようにするには、以下を実行します。

  1. 容認を特別なハードウェアを必要とする Pod に追加します。

    以下は例になります。

    spec:
    ....
      template:
    ....
        spec:
          tolerations:
          - key: "disktype"
            value: "ssd"
            operator: "Equal"
            effect: "NoSchedule"
            tolerationSeconds: 3600
  2. 以下のコマンドのいずれかを使用して、特殊ハードウェアを持つノードにテイントを設定します。

    $ oc adm taint nodes <node-name> disktype=ssd:NoSchedule

    または、以下を実行します。

    $ oc adm taint nodes <node-name> disktype=ssd:PreferNoSchedule

2.6.3. テイントおよび容認 (Toleration) の削除

必要に応じてノードからテイントを、Pod から容認をそれぞれ削除できます。最初に容認を Pod に追加してからテイントをノードに追加して、容認を追加する前に Pod がノードから削除されないようにする必要があります。

手順

テイントおよび容認 (Toleration) を削除するには、以下を実行します。

  1. ノードからテイントを削除するには、以下を実行します。

    $ oc adm taint nodes <node-name> <key>-

    以下は例になります。

    $ oc adm taint nodes ip-10-0-132-248.ec2.internal key1-

    出力例

    node/ip-10-0-132-248.ec2.internal untainted

  2. Pod から容認を削除するには、容認を削除するための Pod 仕様を編集します。

    spec:
    ....
      template:
    ....
        spec:
          tolerations:
          - key: "key2"
            operator: "Exists"
            effect: "NoExecute"
            tolerationSeconds: 3600