website/content/ja/docs/concepts/architecture/nodes.md

31 KiB
Raw Blame History

title content_type weight
ノード concept 10

Kubernetesはコンテナを Node 上で実行されるPodに配置することで、ワークロードを実行します。 ードはクラスターによりますが、1つのVMまたは物理的なマシンです。 各ノードは{{< glossary_tooltip text="Pod" term_id="pod" >}}やそれを制御する{{< glossary_tooltip text="コントロールプレーン" term_id="control-plane" >}}を実行するのに必要なサービスを含んでいます。

通常、1つのクラスターで複数のードを持ちます。学習用途やリソースの制限がある環境では、1ードかもしれません。

1つのード上のコンポーネントには、{{< glossary_tooltip text="kubelet" term_id="kubelet" >}}、{{< glossary_tooltip text="コンテナランタイム" term_id="container-runtime" >}}、{{< glossary_tooltip text="kube-proxy" term_id="kube-proxy" >}}が含まれます。

管理

ノードを{{< glossary_tooltip text="APIサーバー" term_id="kube-apiserver" >}}に加えるには2つの方法があります:

  1. ード上のkubeletが、コントロールプレーンに自己登録する。
  2. あなた、もしくは他のユーザーが手動でNodeオブジェクトを追加する。

Nodeオブジェクトの作成、もしくはード上のkubeletによる自己登録の後、コントロールプレーンはNodeオブジェクトが有効かチェックします。例えば、下記のjsonマニフェストでードを作成してみましょう:

{
  "kind": "Node",
  "apiVersion": "v1",
  "metadata": {
    "name": "10.240.79.157",
    "labels": {
      "name": "my-first-k8s-node"
    }
  }
}

Kubernetesは内部的にNodeオブジェクトを作成します。 APIサーバーに登録したkubeletがードのmetadata.nameフィールドが一致しているか検証します。ードが有効な場合、つまり必要なサービスがすべて実行されている場合は、Podを実行する資格があります。それ以外の場合、該当ードが有効になるまではいかなるクラスターの活動に対しても無視されます。

{{< note >}} Kubernetesは無効なNodeのオブジェクトを保持し、それが有効になるまで検証を続けます。

ヘルスチェックを止めるためには、あなた、もしくは{{< glossary_tooltip term_id="controller" text="コントローラー">}}が明示的にNodeを削除する必要があります。 {{< /note >}}

Nodeオブジェクトの名前は有効なDNSサブドメイン名である必要があります。

ノードの自己登録

kubeletのフラグ --register-nodeがtrueデフォルトのとき、kubeletは自分自身をAPIサーバーに登録しようとします。これはほとんどのディストリビューションで使用されている推奨パターンです。

自己登録については、kubeletは以下のオプションを伴って起動されます:

  • --kubeconfig - 自分自身をAPIサーバーに対して認証するための資格情報へのパス
  • --cloud-provider - 自身に関するメタデータを読むために{{< glossary_tooltip text="クラウドプロバイダー" term_id="cloud-provider" >}}と会話する方法
  • --register-node - 自身をAPIサーバーに自動的に登録
  • --register-with-taints - 与えられた{{< glossary_tooltip text="taint" term_id="taint" >}}のリストでノードを登録します (カンマ区切りの <key>=<value>:<effect>)。

register-nodeがfalseの場合、このオプションは機能しません

  • --node-ip - ードのIPアドレス
  • --node-labels - ノードをクラスターに登録するときに追加する{{< glossary_tooltip text="Label" term_id="label" >}}NodeRestriction許可プラグインによって適用されるラベルの制限を参照)
  • --node-status-update-frequency - kubeletがードのステータスをマスターにPOSTする頻度の指定

ノード認証モードおよびNodeRestriction許可プラグインが有効になっている場合、kubeletは自分自身のードリソースを作成/変更することのみ許可されています。

手動によるノード管理

クラスター管理者は{{< glossary_tooltip text="kubectl" term_id="kubectl" >}}を使用してNodeオブジェクトを作成および変更できます。

管理者が手動でNodeオブジェクトを作成したい場合は、kubeletフラグ --register-node = falseを設定してください。

管理者は--register-nodeの設定に関係なくNodeオブジェクトを変更することができます。 例えば、ードにラベルを設定し、それをunschedulableとしてマークすることが含まれます。

ード上のラベルは、スケジューリングを制御するためにPod上のードセレクターと組み合わせて使用できます。 例えば、Podをードのサブセットでのみ実行する資格があるように制限します。

ードをunschedulableとしてマークすると、新しいPodがそのードにスケジュールされるのを防ぎますが、ード上の既存のPodには影響しません。 これは、ノードの再起動などの前の準備ステップとして役立ちます。

ノードにスケジュール不可能のマークを付けるには、次のコマンドを実行します:

kubectl cordon $ノード名

{{< note >}} {{< glossary_tooltip term_id="daemonset" >}}によって作成されたPodはード上のunschedulable属性を考慮しません。 これは、再起動の準備中にアプリケーションからアプリケーションが削除されている場合でも、DaemonSetがマシンに属していることを前提としているためです。 {{< /note >}}

ノードのステータス

ノードのステータスは以下の情報を含みます:

kubectlを使用し、ノードのステータスや詳細を確認できます:

kubectl describe node <ノード名をここに挿入>

出力情報の各箇所について、以下で説明します。

Addresses

これらのフィールドの使い方は、お使いのクラウドプロバイダーやベアメタルの設定内容によって異なります。

  • HostName: ードのカーネルによって伝えられたホスト名です。kubeletの--hostname-overrideパラメーターによって上書きすることができます。
  • ExternalIP: 通常は、外部にルーティング可能(クラスターの外からアクセス可能)なードのIPアドレスです。
  • InternalIP: 通常は、クラスター内でのみルーティング可能なードのIPアドレスです。

Conditions

conditionsフィールドは全てのRunningなノードのステータスを表します。例として、以下のような状態を含みます:

{{< table caption = "ードのConditionと、各condition適用時の概要" >}}

ードのCondition 概要
Ready ードの状態が有効でPodを配置可能な場合にTrueになります。ードの状態に問題があり、Podが配置できない場合にFalseになります。ノードコントローラーが、node-monitor-grace-periodで設定された時間内(デフォルトでは40秒)に該当ノードと疎通できない場合、Unknownになります。
DiskPressure ノードのディスク容量が圧迫されているときにTrueになります。圧迫とは、ディスクの空き容量が少ないことを指します。それ以外のときはFalseです。
MemoryPressure ノードのメモリが圧迫されているときにTrueになります。圧迫とは、メモリの空き容量が少ないことを指します。それ以外のときはFalseです。
PIDPressure プロセスが圧迫されているときにTrueになります。圧迫とは、プロセス数が多すぎることを指します。それ以外のときはFalseです。
NetworkUnavailable ノードのネットワークが適切に設定されていない場合にTrueになります。それ以外のときはFalseです。
{{< /table >}}

{{< note >}} コマンドラインを使用してcordonされたNodeを表示する場合、ConditionはSchedulingDisabledを含みます。 SchedulingDisabledはKubernetesのAPIにおけるConditionではありません;その代わり、cordonされたードはUnschedulableとしてマークされます。 {{< /note >}}

Nodeの状態は、Nodeリソースの.statusの一部として表現されます。例えば、正常なードの場合は以下のようなjson構造が表示されます。

"conditions": [
  {
    "type": "Ready",
    "status": "True",
    "reason": "KubeletReady",
    "message": "kubelet is posting ready status",
    "lastHeartbeatTime": "2019-06-05T18:38:35Z",
    "lastTransitionTime": "2019-06-05T11:41:27Z"
  }
]

Ready conditionがpod-eviction-timeout({{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}}に渡された引数)に設定された時間を超えてもUnknownFalseのままになっている場合、該当ード上にあるPodはードコントローラーによって削除がスケジュールされます。デフォルトの退役のタイムアウトの時間は5分です。ードが到達不能ないくつかの場合においては、APIサーバーが該当ードのkubeletと疎通できない状態になっています。その場合、APIサーバーがkubeletと再び通信を確立するまでの間、Podの削除を行うことはできません。削除がスケジュールされるまでの間、削除対象のPodは切り離されたードの上で稼働を続けることになります。

ードコントローラーはクラスター内でPodが停止するのを確認するまでは強制的に削除しないようになりました。到達不能なード上で動いているPodはTerminatingまたはUnknownのステータスになります。Kubernetesが基盤となるインフラストラクチャーを推定できない場合、クラスター管理者は手動でNodeオブジェクトを削除する必要があります。KubernetesからNodeオブジェクトを削除すると、そのードで実行されているすべてのPodオブジェクトがAPIサーバーから削除され、それらの名前が解放されます。

ードのライフサイクルコントローラーがconditionを表したtaintを自動的に生成します。 スケジューラーがPodをードに割り当てる際、ードのtaintを考慮します。Podが許容するtaintは例外です。

詳細は条件によるtaintの付与を参照してください。

CapacityとAllocatable

ードで利用可能なリソースCPU、メモリ、およびードでスケジュールできる最大Pod数について説明します。

capacityブロック内のフィールドは、ードが持っているリソースの合計量を示します。 allocatableブロックは、通常のPodによって消費されるード上のリソースの量を示します。

CapacityとAllocatableについて深く知りたい場合は、ード上でどのようにコンピュートリソースが予約されるかを読みながら学ぶことができます。

Info

カーネルのバージョン、Kubernetesのバージョンkubeletおよびkube-proxyのバージョン使用されている場合Dockerのバージョン、OS名など、ードに関する一般的な情報です。 この情報はードからkubeletを通じて取得され、Kubernetes APIに公開されます。

ハートビート

ハートビートは、Kubernetesードから送信され、ードが利用可能か判断するのに役立ちます。 以下の2つのハートビートがあります:

  • Nodeの.statusの更新
  • [Lease object](/docs/reference/generated/kubernetes-api/{{< latest-version >}}#lease-v1-coordination-k8s-io)です。 各ノードはkube-node-leaseという{{< glossary_tooltip term_id="namespace" text="namespace">}}に関連したLeaseオブジェクトを持ちます。 Leaseは軽量なリソースで、クラスターのスケールに応じてードのハートビートにおけるパフォーマンスを改善します。

kubeletがNodeStatusとLeaseオブジェクトの作成および更新を担当します。

  • kubeletは、ステータスに変化があったり、設定した間隔の間に更新がない時にNodeStatusを更新します。NodeStatus更新のデフォルト間隔は5分です。(到達不能の場合のデフォルトタイムアウトである40秒よりもはるかに長いです)
  • kubeletは10秒間隔(デフォルトの更新間隔)でLeaseオブジェクトの生成と更新を実施します。Leaseの更新はNodeStatusの更新とは独立されて行われます。Leaseの更新が失敗した場合、kubeletは200ミリ秒から始まり7秒を上限とした指数バックオフでリトライします。

ノードコントローラー

ノード{{< glossary_tooltip text="コントローラー" term_id="controller" >}}は、ードのさまざまな側面を管理するKubernetesのコントロールプレーンコンポーネントです。

ードコントローラーは、ードの存続期間中に複数の役割を果たします。1つ目は、ードが登録されたときにCIDRブロックをードに割り当てることですCIDR割り当てがオンになっている場合

2つ目は、ードコントローラーの内部ードリストをクラウドの利用可能なマシンのリストと一致させることです。 クラウド環境で実行している場合、ードに異常があると、ードコントローラーはクラウドプロバイダーにそのNodeのVMがまだ使用可能かどうかを問い合わせます。 使用可能でない場合、ノードコントローラーはノードのリストから該当ノードを削除します。

3つ目は、ードの状態を監視することです。 ノードが到達不能(例えば、ノードがダウンしているなどので理由で、ノードコントローラーがハートビートの受信を停止した場合)になると、ードコントローラーは、NodeStatusのNodeReady conditionをConditionUnknownに変更する役割があります。その後も該当ードが到達不能のままであった場合、Graceful Terminationを使って全てのPodを退役させます。デフォルトのタイムアウトは、ConditionUnknownの報告を開始するまで40秒、その後Podの追い出しを開始するまで5分に設定されています。 ノードコントローラーは、--node-monitor-periodに設定された秒数ごとに各ノードの状態をチェックします。

信頼性

ほとんどの場合、排除の速度は1秒あたり--node-eviction-rateに設定された数値デフォルトは秒間0.1です。つまり、10秒間に1つ以上のPodをードから追い出すことはありません。

特定のアベイラビリティーゾーン内のノードのステータスが異常になると、ノード排除の挙動が変わります。ノードコントローラーは、ゾーン内のノードの何%が異常NodeReady条件がConditionUnknownまたはConditionFalseであるであるかを同時に確認します。 異常なノードの割合が少なくとも --healthy-zone-thresholdに設定した値を下回る場合デフォルトは0.55)であれば、退役率は低下します。クラスターが小さい場合(すなわち、 --large-cluster-size-thresholdの設定値よりもード数が少ない場合。デフォルトは50、退役は停止し、そうでない場合、退役率は秒間で--secondary-node-eviction-rateの設定値デフォルトは0.01)に減少します。 これらのポリシーがアベイラビリティーゾーンごとに実装されているのは、1つのアベイラビリティーゾーンがマスターから分割される一方、他のアベイラビリティーゾーンは接続されたままになる可能性があるためです。 クラスターが複数のクラウドプロバイダーのアベイラビリティーゾーンにまたがっていない場合、アベイラビリティーゾーンは1つだけですクラスター全体

ードを複数のアベイラビリティゾーンに分散させる主な理由は、1つのゾーン全体が停止したときにワークロードを正常なゾーンに移動できることです。 したがって、ゾーン内のすべてのノードが異常である場合、ノードコントローラーは通常のレート --node-eviction-rateで退役します。 コーナーケースは、すべてのゾーンが完全にUnhealthyであるすなわち、クラスター内にHealthyなードがない場合です。 このような場合、ノードコントローラーはマスター接続に問題があると見なし、接続が回復するまですべての退役を停止します。

ードコントローラーは、Podがtaintを許容しない場合、 NoExecuteのtaintを持つード上で実行されているPodを排除する責務もあります。 さらに、ノードコントローラーはノードに到達できない、または準備ができていないなどのノードの問題に対応する{{< glossary_tooltip text="taint" term_id="taint" >}}を追加する責務があります。これはスケジューラーが、問題のあるードにPodを配置しない事を意味しています。

ノードのキャパシティ

NodeオブジェクトはードのリソースキャパシティCPUの数とメモリの量を監視します。 自己登録したードは、Nodeオブジェクトを作成するときにキャパシティを報告します。 手動によるノード管理を実行している場合は、ノードを追加するときにキャパシティを設定する必要があります。

Kubernetes{{< glossary_tooltip text="スケジューラー" term_id="kube-scheduler" >}}は、ード上のすべてのPodに十分なリソースがあることを確認します。スケジューラーは、ード上のコンテナが要求するリソースの合計がードキャパシティ以下であることを確認します。 これは、kubeletによって管理されたすべてのコンテナを含みますが、コンテナランタイムによって直接開始されたコンテナやkubeletの制御外で実行されているプロセスは含みません。

{{< note >}} Pod以外のプロセス用にリソースを明示的に予約したい場合は、Systemデーモン用にリソースを予約を参照してください。 {{< /note >}}

ノードのトポロジー

{{< feature-state state="alpha" for_k8s_version="v1.16" >}} TopologyManagerフィーチャーゲートを有効にすると、 kubeletはリソースの割当を決定する際にトポロジーのヒントを利用できます。 詳細は、ノードのトポロジー管理ポリシーを制御するを参照してください。

ノードの正常終了

{{< feature-state state="beta" for_k8s_version="v1.21" >}}

kubeletは、ードのシステムシャットダウンを検出すると、ード上で動作しているPodを終了させます。

Kubelet は、ノードのシャットダウン時に、ポッドが通常の通常のポッド終了プロセスに従うようにします。

Graceful Node Shutdownはsystemdに依存しているため、systemd inhibitor locksを 利用してノードのシャットダウンを一定時間遅らせることができます。

Graceful Node Shutdownは、v1.21でデフォルトで有効になっているGracefulNodeShutdown フィーチャーゲートで制御されます。

なお、デフォルトでは、後述の設定オプションShutdownGracePeriodおよびShutdownGracePeriodCriticalPodsの両方がゼロに設定されているため、Graceful node shutdownは有効になりません。この機能を有効にするには、この2つのkubeletの設定を適切に設定し、ゼロ以外の値を設定する必要があります。

Graceful shutdownでは、kubeletは以下の2段階でPodを終了させます。

  1. そのード上で動作している通常のPodを終了させます。
  2. そのノード上で動作しているcritical podsを終了させます。

Graceful Node Shutdownには、2つのKubeletConfigurationオプションを設定します。:

  • ShutdownGracePeriod:
    • ードがシャットダウンを遅らせるべき合計期間を指定します。これは、通常のPodとcritical podsの両方のPod終了の合計猶予期間です。
  • ShutdownGracePeriodCriticalPods:
    • ノードのシャットダウン時にcritical podsを終了させるために使用する期間を指定します。この値は、ShutdownGracePeriodよりも小さくする必要があります。

例えば、ShutdownGracePeriod=30sShutdownGracePeriodCriticalPods=10sとすると、 kubeletはードのシャットダウンを30秒遅らせます。シャットダウンの間、最初の20(30-10)秒は通常のポッドを優雅に終了させるために確保され、 残りの10秒は重要なポッドを終了させるために確保されることになります。

{{< note >}} Graceful Node Shutdown中にPodが退避された場合、それらのPodの.statusFailedになります。 kubectl get podsを実行すると、退避させられたPodのステータスが Shutdown と表示されます。 また、kubectl describe podを実行すると、ードのシャットダウンのためにPodが退避されたことがわかります。

Status:         Failed
Reason:         Shutdown
Message:        Node is shutting, evicting pods

失敗したポッドオブジェクトは、明示的に削除されるか、GCによってクリーンアップされるまで保存されます。 これは、ノードが突然終了した場合とは異なった振る舞いです。

{{< /note >}}

ノードの非正常終了

{{< feature-state state="beta" for_k8s_version="v1.26" >}}

コマンドがkubeletのinhibitor locksメカニズムをトリガーしない場合や、ShutdownGracePeriodやShutdownGracePeriodCriticalPodsが適切に設定されていないといったユーザーによるミス等が原因で、ードがシャットダウンしたことをkubeletのNode Shutdownマネージャーが検知できないことがあります。詳細は上記セクションノードの正常終了を参照ください。

ードのシャットダウンがkubeletのNode Shutdownマネージャーに検知されない場合、StatefulSetを構成するPodはシャットダウン状態のード上でterminating状態のままになってしまい、他の実行中のードに移動することができなくなってしまいます。これは、ードがシャットダウンしているため、その上のkubeletがPodを削除できず、それにより、StatefulSetが新しいPodを同じ名前で作成できなくなってしまうためです。Podがボリュームを使用している場合、VolumeAttachmentsはシャットダウン状態のードによって削除されないため、Podが使用しているボリュームは他の実行中のードにアタッチすることができなくなってしまいます。その結果として、StatefulSet上で実行中のアプリケーションは適切に機能しなくなってしまいます。シャットダウンしていたードが復旧した場合、そのード上のPodはkubeletに削除され、他の実行中のード上に作成されます。また、シャットダウン状態のードが復旧できなかった場合は、そのード上のPodは永久にterminating状態のままとなります。

上記の状況を脱却するには、ユーザーが手動でNoExecuteまたはNoSchedule effectを設定してnode.kubernetes.io/out-of-service taintをードに付与することで、故障中の状態に設定することができます。kube-controller-manager において NodeOutOfServiceVolumeDetachフィーチャーゲートが有効になっており、かつードがtaintによって故障中としてマークされている場合は、ードに一致するtolerationがないPodは強制的に削除され、ード上のterminating状態のPodに対するボリュームデタッチ操作が直ちに実行されます。これにより、故障中のード上のPodを異なるード上にすばやく復旧させることが可能になります。

non-graceful shutdownの間に、Podは以下の2段階で終了します:

  1. 一致するout-of-service tolerationを持たないPodを強制的に削除する。
  2. 上記のPodに対して即座にボリュームデタッチ操作を行う。

{{< note >}}

  • node.kubernetes.io/out-of-service taintを付与する前に、ードがシャットダウンしているか電源がオフになっていることを確認してください(再起動中ではないこと)。
  • Podの別ードへの移動後、シャットダウンしていたードが回復した場合は、ユーザーが手動で付与したout-of-service taintをユーザー自ら手動で削除する必要があります。 {{< /note >}}

スワップメモリの管理

{{< feature-state state="alpha" for_k8s_version="v1.22" >}}

Kubernetes 1.22以前では、ノードはスワップメモリの使用をサポートしておらず、ノード上でスワップが検出された場合、 kubeletはデフォルトで起動に失敗していました。1.22以降では、スワップメモリのサポートをノードごとに有効にすることができます。

ードでスワップを有効にするには、kubeletの NodeSwap フィーチャーゲートを有効にし、 --fail-swap-onコマンドラインフラグまたはfailSwapOnKubeletConfigurationを false に設定する必要があります。

ユーザーはオプションで、ノードがスワップメモリをどのように使用するかを指定するために、memorySwap.swapBehaviorを設定することもできます。ノードがスワップメモリをどのように使用するかを指定します。例えば、以下のようになります。

memorySwap:
  swapBehavior: LimitedSwap

swapBehaviorで使用できる設定オプションは以下の通りです。:

  • LimitedSwap: Kubernetesのワークロードが、使用できるスワップ量に制限を設けます。Kubernetesが管理していないード上のワークロードは、依然としてスワップを使用できます。
  • UnlimitedSwap: Kubernetesのワークロードが使用できるスワップ量に制限を設けません。システムの限界まで、要求されただけのスワップメモリを使用することができます。

memorySwapの設定が指定されておらず、フィーチャーゲートが有効な場合、デフォルトのkubeletはLimitedSwapの設定と同じ動作を適用します。

LimitedSwap設定の動作は、ノードがコントロールグループ(「cgroups」とも呼ばれる)のv1とv2のどちらで動作しているかによって異なります。

Kubernetesのワークロードでは、メモリとスワップを組み合わせて使用することができ、ポッドのメモリ制限が設定されている場合はその制限まで使用できます。

  • cgroupsv1: Kubernetesのワークロードは、メモリとスワップを組み合わせて使用することができ、ポッドのメモリ制限が設定されている場合はその制限まで使用できます。
  • cgroupsv2: Kubernetesのワークロードは、スワップメモリを使用できません。

詳しくは、KEP-2400design proposalをご覧いただき、テストにご協力、ご意見をお聞かせください。

{{% heading "whatsnext" %}}

  • ノードコンポーネントについて学習する。
  • [Node APIオブジェクト](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#node-v1-core)について読む。
  • アーキテクチャ設計文書のNodeという章を読む。
  • TaintとTolerationについて読む。