クラスターのアーキテクチャ
Kubernetesの背後にあるアーキテクチャのコンセプト。
Kubernetesクラスターは、コントロールプレーンと、コンテナ化されたアプリケーションを実行するワーカーマシン群(ノードと呼ばれます)で構成されます。
各クラスターには、Podを実行するために少なくとも1つのワーカーノードが必要です。
ワーカーノードは、アプリケーションのワークロードを構成するPodをホストします。
コントロールプレーンは、クラスター内のワーカーノードとPodを管理します。
本番環境では、コントロールプレーンは通常複数のコンピューターにまたがって実行され、クラスターは通常複数のノードを実行することで、耐障害性と高可用性を提供します。
このドキュメントでは、完全に機能するKubernetesクラスターに必要なさまざまなコンポーネントの概要を説明します。
図1. Kubernetesクラスターのコンポーネント。
このアーキテクチャについて
図1は、Kubernetesクラスターのリファレンスアーキテクチャの一例を示しています。
コンポーネントの実際の配置は、具体的なクラスターの構成や要件によって異なる場合があります。
この図では、各ノードでkube-proxy コンポーネントが実行されています。
Service APIと関連する動作をクラスターネットワーク上で利用可能にするためには、各ノードにネットワークプロキシコンポーネントが必要です。
ただし、一部のネットワークプラグインは、独自のサードパーティ製プロキシ実装を提供しています。
そのようなネットワークプラグインを使用する場合、ノードでkube-proxyを実行する必要はありません。
コントロールプレーンコンポーネント コントロールプレーンのコンポーネントは、クラスターに関する全体的な判断(たとえばスケジューリングなど)を行うほか、クラスターのイベントの検知と対応(たとえば、Deploymentのreplicas フィールドが満たされていない場合に新しいPod を起動するなど)を行います。
コントロールプレーンコンポーネントは、クラスター内の任意のマシンで実行できます。
ただし、単純化のため、セットアップスクリプトは通常すべてのコントロールプレーンコンポーネントを同じマシン上で起動し、そのマシンではユーザーのコンテナを実行しません。
複数のマシンにまたがって実行されるコントロールプレーンのセットアップ例については、kubeadmを使用した高可用性クラスターの作成 を参照してください。
kube-apiserver APIサーバーは、Kubernetes APIを外部に提供するKubernetesコントロールプレーン のコンポーネントです。
APIサーバーはKubernetesコントロールプレーンのフロントエンドになります。
Kubernetes APIサーバーの主な実装はkube-apiserver です。
kube-apiserverは水平方向にスケールするように設計されています—つまり、インスタンスを追加することでスケールが可能です。
複数のkube-apiserverインスタンスを実行することで、インスタンス間でトラフィックを分散させることが可能です。
etcd 一貫性、高可用性を持ったキーバリューストアで、Kubernetesの全てのクラスター情報の保存場所として利用されています。
etcdをKubernetesのデータストアとして使用する場合、必ずデータのバックアップ プランを作成して下さい。
公式ドキュメント でetcdに関する詳細な情報を見つけることができます。
kube-scheduler コントロールプレーン上で動作するコンポーネントで、新しく作られたPod にノード が割り当てられているか監視し、割り当てられていなかった場合にそのPodを実行するノードを選択します。
スケジューリングの決定は、PodあるいはPod群のリソース要求量、ハードウェア/ソフトウェア/ポリシーによる制約、アフィニティおよびアンチアフィニティの指定、データの局所性、ワークロード間の干渉、有効期限などを考慮して行われます。
kube-controller-manager コントロールプレーン上で動作するコンポーネントで、複数のコントローラー プロセスを実行します。
論理的には、各コントローラー は個別のプロセスですが、複雑さを減らすために一つの実行ファイルにまとめてコンパイルされ、単一のプロセスとして動きます。
コントローラーにはさまざまな種類があります。
いくつか例を挙げます:
Nodeコントローラー: ノードがダウンした際に、それを検知して対応する役割を担います。
Jobコントローラー: 一度限りのタスクを表すJobオブジェクトを監視し、それらのタスクを完了まで実行するためのPodを作成します。
EndpointSliceコントローラー: (ServiceとPodの間のリンクを提供するために)EndpointSliceオブジェクトを作成します。
ServiceAccountコントローラー: 新しい名前空間に対してデフォルトのServiceAccountを作成します。
上記はすべてを網羅したリストではありません。
cloud-controller-manager クラウド特有の制御ロジックを組み込むKubernetesの
コントロールプレーン コンポーネントです。
クラウドコントロールマネージャーは、クラスターをクラウドプロバイダーAPIとリンクし、クラスターのみで相互作用するコンポーネントからクラウドプラットフォームで相互作用するコンポーネントを分離します。
cloud-controller-managerは、利用しているクラウドプロバイダーに固有のコントローラーのみを実行します。
オンプレミス環境でKubernetesを実行している場合や、自分のPC内の学習環境で実行している場合、クラスターにcloud-controller-managerは存在しません。
kube-controller-managerと同様に、cloud-controller-managerは、論理的に独立した複数の制御ループを、単一のプロセスとして実行する1つのバイナリにまとめています。
パフォーマンスの向上や障害への耐性を高めるために、水平方向にスケール(複数のコピーを実行)できます。
次のコントローラーは、クラウドプロバイダーに依存する可能性があります。
Nodeコントローラー: ノードが応答を停止した後、そのノードがクラウド上で削除されたかどうかを判断するためにクラウドプロバイダーを確認します。
Routeコントローラー: 基盤となるクラウドインフラ内でルートを設定します。
Serviceコントローラー: クラウドプロバイダーのロードバランサーの作成、更新、削除を行います。
Nodeコンポーネント ノードコンポーネントはすべてのノード上で実行され、実行中のPodの維持やKubernetesの実行環境の提供を行います。
kubelet クラスター内の各ノード 上で実行されるエージェント。
コンテナ がPod 内で実行されていることを保証します。
kubelet は、さまざまなメカニズムを通じて提供される一連のPodSpecを受け取り、そのPodSpecに記述されたコンテナが実行され、正常であることを保証します。
kubeletは、Kubernetesによって作成されていないコンテナを管理しません。
kube-proxy(オプション)
kube-proxyはクラスター内の各node で動作しているネットワークプロキシで、KubernetesのService コンセプトの一部を実装しています。
kube-proxy は、Nodeのネットワークルールをメンテナンスします。これらのネットワークルールにより、クラスターの内部または外部のネットワークセッションからPodへのネットワーク通信が可能になります。
kube-proxyは、オペレーティングシステムにパケットフィルタリング層があり、かつ使用可能な場合、パケットフィルタリング層を使用します。それ以外の場合は自身でトラフィックを転送します。
Serviceに対するパケット転送を自身で実装し、kube-proxyと同等の動作を提供する
ネットワークプラグイン を使用している場合、クラスター内のノードでkube-proxyを実行する必要はありません。
コンテナランタイム Kubernetesがコンテナを効果的に実行するために不可欠なコンポーネントです。
Kubernetes環境においてコンテナの実行とライフサイクルの管理を担います。
Kubernetesはcontainerd 、CRI-O などのコンテナランタイムと、Kubernetes CRI (Container Runtime Interface) のすべての実装をサポートします。
アドオン アドオンは、Kubernetesのリソース(DaemonSet やDeployment など)を使用してクラスターの機能を実装します。
これらはクラスターレベルの機能を提供するため、アドオンの名前空間に属するリソースはkube-system名前空間に配置されます。
いくつかのアドオンについて以下で説明します。
利用可能なアドオンのより詳細な一覧については、アドオン を参照してください。
DNS 他のアドオンは厳密には必須ではありませんが、多くの例がクラスターDNSに依存しているため、すべてのKubernetesクラスターはクラスターDNS を備えるべきです。
クラスターDNSは、環境内にある他のDNSサーバーに加えて稼働するDNSサーバーであり、KubernetesのService用のDNSレコードを提供します。
Kubernetesによって起動されたコンテナは、自動的にこのDNSサーバーをDNS検索に含めます。
Web UI(Dashboard) Dashboard は、Kubernetesクラスターのための汎用的なWebベースのUIです。
ユーザーはこれを使って、クラスター内で稼働しているアプリケーションやクラスター自体の管理やトラブルシューティングを行えます。
コンテナリソースの監視 コンテナリソースの監視 は、コンテナに関する一般的な時系列メトリクスを中央のデータベースに記録し、そのデータを閲覧するためのUIを提供します。
クラスターレベルのロギング クラスターレベルのロギング の仕組みは、コンテナのログを検索・閲覧用のインターフェースを備えた中央のログストアに保存する役割を担います。
ネットワークプラグイン ネットワークプラグイン は、Container Network Interface(CNI)仕様を実装するソフトウェアコンポーネントです。
PodへのIPアドレスの割り当てや、クラスター内でPod同士が通信できるようにする役割を担います。
アーキテクチャのバリエーション Kubernetesの中核となるコンポーネントは一貫していますが、それらがデプロイされ管理される方法はさまざまです。
これらのバリエーションを理解することは、特定の運用上のニーズを満たすKubernetesクラスターを設計し維持するうえで非常に重要です。
コントロールプレーンのデプロイオプション コントロールプレーンコンポーネントは、いくつかの方法でデプロイできます。
従来のデプロイ
コントロールプレーンコンポーネントは専用のマシンやVM上で直接実行され、多くの場合systemdのサービスとして管理されます。
static Pod
コントロールプレーンコンポーネントはstatic Podとしてデプロイされ、特定のノード上のkubeletによって管理されます。
これはkubeadmのようなツールで使われる一般的なアプローチです。
セルフホスト
コントロールプレーンはKubernetesクラスター自体の内部でPodとして実行され、DeploymentやStatefulSet、その他のKubernetesのプリミティブによって管理されます。
マネージドKubernetesサービス
クラウドプロバイダーは多くの場合コントロールプレーンを抽象化し、そのコンポーネントを自身のサービス提供の一部として管理します。
ワークロード配置に関する考慮事項 コントロールプレーンコンポーネントを含むワークロードの配置は、クラスターのサイズ、パフォーマンス要件、運用ポリシーによって異なる場合があります:
より小規模なクラスターや開発用のクラスターでは、コントロールプレーンコンポーネントとユーザーのワークロードが同じノード上で実行されることがあります。
より大規模な本番クラスターでは、多くの場合特定のノードをコントロールプレーンコンポーネント専用にし、ユーザーのワークロードから分離します。
一部の組織では、重要なアドオンや監視ツールをコントロールプレーンのノード上で実行します。
kubeadm、kops、Kubesprayといったツールは、クラスターのデプロイと管理に対してそれぞれ異なるアプローチを提供しており、コンポーネントの配置や管理の方法もそれぞれ独自のものです。
カスタマイズと拡張性 Kubernetesのアーキテクチャは、大幅なカスタマイズを可能にします。
カスタムスケジューラーをデプロイして、デフォルトのKubernetesスケジューラーと並行して動作させたり、完全に置き換えたりできます。
APIサーバーは、CustomResourceDefinitionやAPIアグリゲーションによって拡張できます。
クラウドプロバイダーは、cloud-controller-managerを使用してKubernetesと深く統合できます。
Kubernetesのアーキテクチャの柔軟性により、組織は運用の複雑さ、パフォーマンス、管理のオーバーヘッドといった要素のバランスを取りながら、クラスターを特定のニーズに合わせて調整できます。
次の項目 以下についてさらに学べます。
1 - ノード
Kubernetesはコンテナを Node 上で実行されるPodに配置することで、ワークロードを実行します。
ノードはクラスターによりますが、1つのVMまたは物理的なマシンです。
各ノードはPod やそれを制御するコントロールプレーン を実行するのに必要なサービスを含んでいます。
通常、1つのクラスターで複数のノードを持ちます。学習用途やリソースの制限がある環境では、1ノードかもしれません。
1つのノード上のコンポーネント には、kubelet 、コンテナランタイム 、kube-proxy が含まれます。
管理 ノードをAPIサーバー に加えるには2つの方法があります:
ノード上のkubeletが、コントロールプレーンに自己登録する。
あなた、もしくは他のユーザーが手動で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を実行する資格があります。それ以外の場合、該当ノードが有効になるまではいかなるクラスターの活動に対しても無視されます。
備考: Kubernetesは無効なNodeのオブジェクトを保持し、それが有効になるまで検証を続けます。
ヘルスチェックを止めるためには、あなた、もしくはコントローラー が明示的にNodeを削除する必要があります。
Nodeオブジェクトの名前は有効なDNSサブドメイン名 である必要があります。
ノードの自己登録 kubeletのフラグ --register-nodeがtrue(デフォルト)のとき、kubeletは自分自身をAPIサーバーに登録しようとします。これはほとんどのディストリビューションで使用されている推奨パターンです。
自己登録については、kubeletは以下のオプションを伴って起動されます:
--kubeconfig - 自分自身をAPIサーバーに対して認証するための資格情報へのパス
--cloud-provider - 自身に関するメタデータを読むためにクラウドプロバイダー と会話する方法
--register-node - 自身をAPIサーバーに自動的に登録
--register-with-taints - 与えられたtaint のリストでノードを登録します (カンマ区切りの <key>=<value>:<effect>)。
register-nodeがfalseの場合、このオプションは機能しません
--node-ip - ノードのIPアドレス
--node-labels - ノードをクラスターに登録するときに追加するLabel (NodeRestriction許可プラグイン によって適用されるラベルの制限を参照)
--node-status-update-frequency - kubeletがノードのステータスをマスターにPOSTする頻度の指定
ノード認証モード およびNodeRestriction許可プラグイン が有効になっている場合、kubeletは自分自身のノードリソースを作成/変更することのみ許可されています。
手動によるノード管理 クラスター管理者はkubectl を使用してNodeオブジェクトを作成および変更できます。
管理者が手動でNodeオブジェクトを作成したい場合は、kubeletフラグ --register-node = falseを設定してください。
管理者は--register-nodeの設定に関係なくNodeオブジェクトを変更することができます。
例えば、ノードにラベルを設定し、それをunschedulableとしてマークすることが含まれます。
ノード上のラベルは、スケジューリングを制御するためにPod上のノードセレクターと組み合わせて使用できます。
例えば、Podをノードのサブセットでのみ実行する資格があるように制限します。
ノードをunschedulableとしてマークすると、新しいPodがそのノードにスケジュールされるのを防ぎますが、ノード上の既存のPodには影響しません。
これは、ノードの再起動などの前の準備ステップとして役立ちます。
ノードにスケジュール不可能のマークを付けるには、次のコマンドを実行します:
備考: DaemonSet によって作成されたPodはノード上のunschedulable属性を考慮しません。
これは、再起動の準備中にアプリケーションからアプリケーションが削除されている場合でも、DaemonSetがマシンに属していることを前提としているためです。
ノードのステータス ノードのステータスは以下の情報を含みます:
kubectlを使用し、ノードのステータスや詳細を確認できます:
kubectl describe node <ノード名をここに挿入>
出力情報の各箇所について、以下で説明します。
Addresses これらのフィールドの使い方は、お使いのクラウドプロバイダーやベアメタルの設定内容によって異なります。
HostName: ノードのカーネルによって伝えられたホスト名です。kubeletの--hostname-overrideパラメーターによって上書きすることができます。
ExternalIP: 通常は、外部にルーティング可能(クラスターの外からアクセス可能)なノードのIPアドレスです。
InternalIP: 通常は、クラスター内でのみルーティング可能なノードのIPアドレスです。
Conditions conditionsフィールドは全てのRunningなノードのステータスを表します。例として、以下のような状態を含みます:
ノードの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です。
備考: コマンドラインを使用してcordonされたNodeを表示する場合、ConditionはSchedulingDisabledを含みます。
SchedulingDisabledはKubernetesのAPIにおけるConditionではありません;その代わり、cordonされたノードはUnschedulableとしてマークされます。
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(kube-controller-manager に渡された引数)に設定された時間を超えてもUnknownやFalseのままになっている場合、該当ノード上にある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 です。
各ノードはkube-node-leaseというnamespace に関連したLeaseオブジェクトを持ちます。
Leaseは軽量なリソースで、クラスターのスケールに応じてノードのハートビートにおけるパフォーマンスを改善します。
kubeletがNodeStatusとLeaseオブジェクトの作成および更新を担当します。
kubeletは、ステータスに変化があったり、設定した間隔の間に更新がない時にNodeStatusを更新します。NodeStatus更新のデフォルト間隔は5分です。(到達不能の場合のデフォルトタイムアウトである40秒よりもはるかに長いです)
kubeletは10秒間隔(デフォルトの更新間隔)でLeaseオブジェクトの生成と更新を実施します。Leaseの更新はNodeStatusの更新とは独立されて行われます。Leaseの更新が失敗した場合、kubeletは200ミリ秒から始まり7秒を上限とした指数バックオフでリトライします。
ノードコントローラー ノードコントローラー は、ノードのさまざまな側面を管理する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を排除する責務もあります。
さらに、ノードコントローラーはノードに到達できない、または準備ができていないなどのノードの問題に対応するtaint を追加する責務があります。これはスケジューラーが、問題のあるノードにPodを配置しない事を意味しています。
ノードのキャパシティ Nodeオブジェクトはノードのリソースキャパシティ(CPUの数とメモリの量)を監視します。
自己登録 したノードは、Nodeオブジェクトを作成するときにキャパシティを報告します。
手動によるノード管理 を実行している場合は、ノードを追加するときにキャパシティを設定する必要があります。
Kubernetesスケジューラー は、ノード上のすべてのPodに十分なリソースがあることを確認します。スケジューラーは、ノード上のコンテナが要求するリソースの合計がノードキャパシティ以下であることを確認します。
これは、kubeletによって管理されたすべてのコンテナを含みますが、コンテナランタイムによって直接開始されたコンテナやkubeletの制御外で実行されているプロセスは含みません。
ノードのトポロジー
FEATURE STATE:
Kubernetes v1.16 [alpha]
TopologyManagerの
フィーチャーゲート を有効にすると、
kubeletはリソースの割当を決定する際にトポロジーのヒントを利用できます。
詳細は、
ノードのトポロジー管理ポリシーを制御する を参照してください。
ノードの正常終了
FEATURE STATE:
Kubernetes v1.21 [beta]
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を終了させます。
そのノード上で動作している通常のPodを終了させます。
そのノード上で動作しているcritical pods を終了させます。
Graceful Node Shutdownには、2つのKubeletConfiguration オプションを設定します。:
ShutdownGracePeriod:
ノードがシャットダウンを遅らせるべき合計期間を指定します。これは、通常のPodとcritical pods の両方のPod終了の合計猶予期間です。
ShutdownGracePeriodCriticalPods:
ノードのシャットダウン時にcritical pods を終了させるために使用する期間を指定します。この値は、ShutdownGracePeriodよりも小さくする必要があります。
例えば、ShutdownGracePeriod=30s、ShutdownGracePeriodCriticalPods=10sとすると、
kubeletはノードのシャットダウンを30秒遅らせます。シャットダウンの間、最初の20(30-10)秒は通常のポッドを優雅に終了させるために確保され、
残りの10秒は重要なポッドを終了させるために確保されることになります。
備考: Graceful Node Shutdown中にPodが退避された場合、それらのPodの.statusはFailedになります。
kubectl get podsを実行すると、退避させられたPodのステータスが Shutdown と表示されます。
また、kubectl describe podを実行すると、ノードのシャットダウンのためにPodが退避されたことがわかります。
Status: Failed
Reason: Shutdown
Message: Node is shutting, evicting pods
失敗したポッドオブジェクトは、明示的に削除されるか、GCによってクリーンアップ されるまで保存されます。
これは、ノードが突然終了した場合とは異なった振る舞いです。
ノードの非正常終了
FEATURE STATE:
Kubernetes v1.26 [beta]
コマンドが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段階で終了します:
一致するout-of-service tolerationを持たないPodを強制的に削除する。
上記のPodに対して即座にボリュームデタッチ操作を行う。
備考:
node.kubernetes.io/out-of-service taintを付与する前に、ノードがシャットダウンしているか電源がオフになっていることを確認してください(再起動中ではないこと)。
Podの別ノードへの移動後、シャットダウンしていたノードが回復した場合は、ユーザーが手動で付与したout-of-service taintをユーザー自ら手動で削除する必要があります。
スワップメモリの管理
FEATURE STATE:
Kubernetes v1.22 [alpha]
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-2400 と
design proposal をご覧いただき、テストにご協力、ご意見をお聞かせください。
次の項目
2 - ノードとコントロールプレーン間の通信
本ドキュメントは、APIサーバー とKubernetesクラスター 間の通信経路をまとめたものです。
その目的は、信頼できないネットワーク上(またはクラウドプロバイダー上の完全なパブリックIP)でクラスターが実行できるよう、ユーザーがインストールをカスタマイズしてネットワーク構成を強固にできるようにすることです。
ノードからコントロールプレーンへの通信 Kubernetesには「ハブアンドスポーク」というAPIパターンがあります。ノード(またはノードが実行するPod)からのすべてのAPIの使用は、APIサーバーで終了します。他のコントロールプレーンコンポーネントは、どれもリモートサービスを公開するようには設計されていません。APIサーバーは、1つ以上の形式のクライアント認証 が有効になっている状態で、セキュアなHTTPSポート(通常は443)でリモート接続をリッスンするように設定されています。
特に匿名リクエスト やサービスアカウントトークン が許可されている場合は、1つ以上の認可 形式を有効にする必要があります。
ノードは、有効なクライアント認証情報とともに、APIサーバーに安全に接続できるように、クラスターのパブリックルート証明書 でプロビジョニングされる必要があります。適切なやり方は、kubeletに提供されるクライアント認証情報が、クライアント証明書の形式であることです。kubeletクライアント証明書の自動プロビジョニングについては、kubelet TLSブートストラップ を参照してください。
APIサーバーに接続したいPod は、サービスアカウントを利用することで、安全に接続することができます。これにより、Podのインスタンス化時に、Kubernetesはパブリックルート証明書と有効なBearerトークンを自動的にPodに挿入します。
kubernetesサービス(デフォルトの名前空間)は、APIサーバー上のHTTPSエンドポイントに(kube-proxy 経由で)リダイレクトされる仮想IPアドレスで構成されます。
また、コントロールプレーンのコンポーネントは、セキュアなポートを介してAPIサーバーとも通信します。
その結果、ノードやノード上で動作するPodからコントロールプレーンへの接続は、デフォルトでセキュアであり、信頼されていないネットワークやパブリックネットワークを介して実行することができます。
コントロールプレーンからノードへの通信 コントロールプレーン(APIサーバー)からノードへの主要な通信経路は2つあります。
1つ目は、APIサーバーからクラスター内の各ノードで実行されるkubelet プロセスへの通信経路です。
2つ目は、APIサーバーの プロキシ 機能を介した、APIサーバーから任意のノード、Pod、またはサービスへの通信経路です。
APIサーバーからkubeletへの通信 APIサーバーからkubeletへの接続は、以下の目的で使用されます:
Podのログの取得。
実行中のPodへのアタッチ(通常はkubectlを使用)。
kubeletのポート転送機能の提供。
これらの接続は、kubeletのHTTPSエンドポイントで終了します。デフォルトでは、APIサーバーはkubeletのサービング証明書を検証しないため、接続は中間者攻撃の対象となり、信頼されていないネットワークやパブリックネットワークを介して実行するのは安全ではありません 。
この接続を検証するには、--kubelet-certificate-authorityフラグを使用して、kubeletのサービング証明書を検証するために使用するルート証明書バンドルを、APIサーバーに提供します。
それができない場合は、信頼できないネットワークやパブリックネットワークを介した接続を回避するため、必要に応じてAPIサーバーとkubeletの間でSSHトンネル を使用します。
最後に、kubelet APIを保護するために、Kubelet認証/認可 を有効にする必要があります。
APIサーバーからノード、Pod、サービスへの通信 APIサーバーからノード、Pod、またはサービスへの接続は、デフォルトで平文のHTTP接続になるため、認証も暗号化もされません。API URL内のノード、Pod、サービス名にhttps:を付けることで、セキュアなHTTPS接続を介して実行できますが、HTTPSエンドポイントから提供された証明書を検証したり、クライアント認証情報を提供したりすることはありません。そのため、接続の暗号化はされますが、完全性の保証はありません。これらの接続を、信頼されていないネットワークやパブリックネットワークを介して実行するのは、現在のところ安全ではありません 。
SSHトンネル Kubernetesは、コントロールプレーンからノードへの通信経路を保護するために、SSHトンネル をサポートしています。この構成では、APIサーバーがクラスター内の各ノードへのSSHトンネルを開始(ポート22でリッスンしているSSHサーバーに接続)し、kubelet、ノード、Pod、またはサービス宛てのすべてのトラフィックをトンネル経由で渡します。
このトンネルにより、ノードが稼働するネットワークの外部にトラフィックが公開されないようになります。
備考: SSHトンネルは現在非推奨であるため、自分が何をしているのか理解していないのであれば、使用すべきではありません。この通信経路の代替となるものとして、
Konnectivityサービス があります。
Konnectivityサービス
FEATURE STATE:
Kubernetes v1.18 [beta]
SSHトンネルの代替として、Konnectivityサービスは、コントロールプレーンからクラスターへの通信に、TCPレベルのプロキシを提供します。Konnectivityサービスは、コントロールプレーンネットワークのKonnectivityサーバーと、ノードネットワークのKonnectivityエージェントの、2つの部分で構成されています。
Konnectivityエージェントは、Konnectivityサーバーへの接続を開始し、ネットワーク接続を維持します。
Konnectivityサービスを有効にすると、コントロールプレーンからノードへのトラフィックは、すべてこの接続を経由するようになります。
Konnectivityサービスのセットアップ に従って、クラスターにKonnectivityサービスをセットアップしてください。
次の項目
3 - リース
しばしば分散システムでは共有リソースをロックしたりノード間の活動を調整する機構として"リース"が必要になります。
Kubernetesでは、"リース"のコンセプトはcoordination.k8s.ioAPIグループのLeaseオブジェクトに表されていて、ノードのハートビートやコンポーネントレベルのリーダー選出といったシステムにとって重要な機能に利用されています。
ノードハートビート Kubernetesでは、kubeletのノードハートビートをKubernetes APIサーバーに送信するのにLease APIが使われています。
各Nodeごとに、kube-node-lease名前空間にノードとマッチする名前のLeaseオブジェクトが存在します。
内部的には、kubeletのハートビートはこのLeaseオブジェクトに対するUPDATEリクエストであり、Leaseのspec.renewTimeフィールドを更新しています。
Kubernetesのコントロールプレーンはこのフィールドのタイムスタンプを見て、Nodeが利用可能かを判断しています。
詳しくはNode Leaseオブジェクト をご覧ください。
リーダー選出 Kubernetesでは、あるコンポーネントのインスタンスが常に一つだけ実行されていることを保証するためにもリースが利用されています。
これはkube-controller-managerやkube-schedulerといったコントロールプレーンのコンポーネントで、一つのインスタンスのみがアクティブに実行され、その他のインスタンスをスタンバイ状態とする必要があるような冗長構成を組むために利用されています。
APIサーバーのアイデンティティー
FEATURE STATE:
Kubernetes v1.26 [beta]
Kubernetes v1.26から、各kube-apiserverはLease APIを利用して自身のアイデンティティーをその他のシステムに向けて公開するようになりました。
それ自体は特に有用ではありませんが、何台のkube-apiserverがKubernetesコントロールプレーンを稼働させているのかをクライアントが知るためのメカニズムを提供します。
kube-apiserverリースが存在することで、各kube-apiserver間の調整が必要となる可能性がある将来の機能が使えるようになります。
kube-system名前空間のapiserver-<sha256-hash>という名前のリースオブジェクトを確認することで、各kube-apiserverが所有しているLeaseを確認することができます。
また、k8s.io/component=kube-apiserverラベルセレクターを利用することもできます。
$ kubectl -n kube-system get lease -l k8s.io/component= kube-apiserver
NAME HOLDER AGE
apiserver-c4vwjftbvpc5os2vvzle4qg27a kube-apiserver-c4vwjftbvpc5os2vvzle4qg27a_9cbf54e5-1136-44bd-8f9a-1dcd15c346b4 5m33s
apiserver-dz2dqprdpsgnm756t5rnov7yka kube-apiserver-dz2dqprdpsgnm756t5rnov7yka_84f2a85d-37c1-4b14-b6b9-603e62e4896f 4m23s
apiserver-fyloo45sdenffw2ugwaz3likua kube-apiserver-fyloo45sdenffw2ugwaz3likua_c5ffa286-8a9a-45d4-91e7-61118ed58d2e 4m43s
リースの名前に使われているSHA256ハッシュはkube-apiserverのOSホスト名に基づいています。各kube-apiserverはクラスター内で一意なホスト名を使用するように構成する必要があります。
同じホスト名を利用する新しいkube-apiserverインスタンスは、新しいリースオブジェクトを作成せずに、既存のLeaseを新しいインスタンスのアイデンティティーを利用して引き継ぎます。
kube-apiserverが使用するホスト名はkubernetes.io/hostnameラベルの値で確認できます。
$ kubectl -n kube-system get lease kube-apiserver-c4vwjftbvpc5os2vvzle4qg27a -o yaml
apiVersion : coordination.k8s.io/v1
kind : Lease
metadata :
creationTimestamp : "2022-11-30T15:37:15Z"
labels :
k8s.io/component : kube-apiserver
kubernetes.io/hostname : kind-control-plane
name : kube-apiserver-c4vwjftbvpc5os2vvzle4qg27a
namespace : kube-system
resourceVersion : "18171"
uid : d6c68901-4ec5-4385-b1ef-2d783738da6c
spec :
holderIdentity : kube-apiserver-c4vwjftbvpc5os2vvzle4qg27a_9cbf54e5-1136-44bd-8f9a-1dcd15c346b4
leaseDurationSeconds : 3600
renewTime : "2022-11-30T18:04:27.912073Z"
すでに存在しなくなったkube-apiserverの期限切れリースは、1時間後に新しいkube-apiserverによってガベージコレクションされます。
4 - コントローラー
ロボット工学やオートメーションの分野において、 制御ループ とは、あるシステムの状態を制御する終了状態のないループのことです。
ここでは、制御ループの一例として、部屋の中にあるサーモスタットを挙げます。
あなたが温度を設定すると、それはサーモスタットに 目的の状態(desired state) を伝えることになります。実際の部屋の温度は 現在の状態 です。サーモスタットは、装置をオンまたはオフにすることによって、現在の状態を目的の状態に近づけるように動作します。
Kubernetesにおいて、コントローラーは
クラスター の状態を監視し、必要に応じて変更を加えたり要求したりする制御ループです。それぞれのコントローラーは現在のクラスターの状態を望ましい状態に近づけるように動作します。
コントローラーパターン コントローラーは少なくとも1種類のKubernetesのリソースを監視します。これらのオブジェクト には目的の状態を表すspecフィールドがあります。リソースのコントローラーは、現在の状態を目的の状態に近づける責務を持ちます。
コントローラーは自分自身でアクションを実行する場合もありますが、KubernetesではコントローラーがAPIサーバー に意味のある副作用を持つメッセージを送信することが一般的です。以下では、このような例を見ていきます。
APIサーバー経由でコントロールする Job コントローラーはKubernetesのビルトインのコントローラーの一例です。ビルトインのコントローラーは、クラスターのAPIサーバーとやりとりをして状態を管理します。
Jobは、1つ以上のPod を起動して、タスクを実行した後に停止する、Kubernetesのリソースです。
(1度スケジュール されると、Podオブジェクトはkubeletに対する目的の状態の一部になります。)
Jobコントローラーが新しいタスクを見つけると、その処理が完了するように、クラスター上のどこかで、一連のNode上のkubeletが正しい数のPodを実行することを保証します。ただし、Jobコントローラーは、自分自身でPodやコンテナを実行することはありません。代わりに、APIサーバーに対してPodの作成や削除を依頼します。コントロールプレーン 上の他のコンポーネントが(スケジュールして実行するべき新しいPodが存在するという)新しい情報を基に動作することによって、最終的に目的の処理が完了します。
新しいJobが作成されたとき、目的の状態は、そのJobが完了することです。JobコントローラーはそのJobに対する現在の状態を目的の状態に近づけるようにします。つまり、そのJobが行ってほしい処理を実行するPodを作成し、Jobが完了に近づくようにします。
コントローラーは、コントローラーを設定するオブジェクトも更新します。たとえば、あるJobが完了した場合、Jobコントローラーは、JobオブジェクトにFinishedというマークを付けます。
(これは、部屋が設定温度になったことを示すために、サーモスタットがランプを消灯するのに少し似ています。)
直接的なコントロール Jobとは対照的に、クラスターの外部に変更を加える必要があるコントローラーもあります。
たとえば、クラスターに十分な数のNode が存在することを保証する制御ループの場合、そのコントローラーは、必要に応じて新しいNodeをセットアップするために、現在のクラスターの外部とやりとりをする必要があります。
外部の状態とやりとりをするコントローラーは、目的の状態をAPIサーバーから取得した後、外部のシステムと直接通信し、現在の状態を目的の状態に近づけます。
(クラスター内のノードを水平にスケールさせるコントローラー が実際に存在します。)
ここで重要な点は、コントローラーが目的の状態を実現するために変更を加えてから、現在の状態をクラスターのAPIサーバーに報告することです。他の制御ループは、その報告されたデータを監視し、独自のアクションを実行できます。
サーモスタットの例では、部屋が非常に寒い場合、別のコントローラーが霜防止ヒーターをオンにすることもあります。Kubernetesクラスターを使用すると、コントロールプレーンは、Kubernetesを拡張して 実装することにより、IPアドレス管理ツールやストレージサービス、クラウドプロバイダーAPI、およびその他のサービスと間接的に連携します。
目的の状態 vs 現在の状態 Kubernetesはシステムに対してクラウドネイティブな見方をするため、常に変化し続けるような状態を扱えるように設計されています。
処理を実行したり、制御ループが故障を自動的に修正したりしているどの時点でも、クラスターは変化中である可能性があります。つまり、クラスターは決して安定した状態にならない可能性があるということです。
コントローラーがクラスターのために実行されていて、有用な変更が行われるのであれば、全体的な状態が安定しているかどうかは問題にはなりません。
設計 設計理念として、Kubernetesは多数のコントローラーを使用しており、各コントローラーはクラスターの状態の特定の側面をそれぞれ管理しています。最もよくあるパターンは、特定の制御ループ(コントローラー)が目的の状態として1種類のリソースを使用し、目的の状態を実現することを管理するために別の種類のリソースを用意するというものです。たとえば、Jobのコントローラーは、Jobオブジェクト(新しい処理を見つけるため)およびPodオブジェクト(Jobを実行し、処理が完了したか確認するため)を監視します。この場合、なにか別のものがJobを作成し、JobコントローラーはPodを作成します。
相互にリンクされた単一のモノリシックな制御ループよりは、複数の単純なコントローラーが存在する方が役に立ちます。コントローラーは故障することがあるため、Kubernetesは故障を許容するように設計されています。
備考: 同じ種類のオブジェクトを作成または更新するコントローラーが、複数存在する場合があります。実際には、Kubernetesコントローラーは、自分が制御するリソースに関連するリソースにのみ注意を払うように作られています。
たとえば、DeploymentとJobがありますが、これらは両方ともPodを作成するものです。しかし、JobコントローラーはDeploymentが作成したPodを削除することはありません。各コントローラーが2つのPodを区別できる情報(ラベル )が存在するためです。
コントローラーを実行する方法 Kubernetesには、kube-controller-manager 内部で動作する一組のビルトインのコントローラーが用意されています。これらビルトインのコントローラーは、コアとなる重要な振る舞いを提供します。
DeploymentコントローラーとJobコントローラーは、Kubernetes自体の一部として同梱されているコントローラーの例です(それゆえ「ビルトイン」のコントローラーと呼ばれます)。Kubernetesは回復性のあるコントロールプレーンを実行できるようにしているため、ビルトインのコントローラーの一部が故障しても、コントロールプレーンの別の部分が作業を引き継いでくれます。
Kubernetesを拡張するためにコントロールプレーンの外で動作するコントローラーもあります。もし望むなら、新しいコントローラーを自分で書くこともできます。自作のコントローラーをPodセットとして動作させたり、Kubernetesの外部で動作させることもできます。どのような動作方法が最も適しているかは、そのコントローラーがどのようなことを行うのかに依存します。
次の項目
5 - クラウドコントローラーマネージャー
FEATURE STATE:
Kubernetes v1.11 [beta]
クラウドインフラストラクチャ技術により、パブリック、プライベート、ハイブリッドクラウド上でKubernetesを動かすことができます。Kubernetesは、コンポーネント間の密なつながりが不要な自動化されたAPI駆動インフラストラクチャを信条としています。
cloud-controller-managerは クラウド特有の制御ロジックを組み込むKubernetesのコントロールプレーン コンポーネントです。
クラウドコントロールマネージャーは、クラスターをクラウドプロバイダーAPIとリンクし、クラスターのみで相互作用するコンポーネントからクラウドプラットフォームで相互作用するコンポーネントを分離します。
Kubernetesと基盤となるクラウドインフラストラクチャ間の相互運用ロジックを分離することで、クラウドプロバイダーはcloud-controller-managerコンポーネントにより、メインのKubernetesプロジェクトとは異なるペースで機能をリリースできるようになります。
cloud-controller-managerは、プラグイン機構を用い、異なるクラウドプロバイダーに対してそれぞれのプラットフォームとKubernetesの結合を可能にする構成になっています。
設計
クラウドコントローラーマネージャーは、複製されたプロセスの集合としてコントロールプレーンで実行されます(通常、Pod内のコンテナとなります)。各cloud-controller-managerは、シングルプロセスで複数のコントローラー を実装します。
備考: コントロールプレーンの一部ではなく、Kubernetesの
アドオン としてクラウドコントローラーマネージャーを実行することもできます。
クラウドコントローラーマネージャーの機能 クラウドコントローラーマネージャーのコントローラーは以下を含んでいます。
ノードコントローラー ノードコントローラーは、クラウドインフラストラクチャで新しいサーバーが作成された際に、Node オブジェクトを作成する責務を持ちます。ノードコントローラーは、クラウドプロバイダーのテナント内で動作しているホストの情報を取得します。ノードコントローラーは下記に示す機能を実行します:
Nodeオブジェクトを、コントローラーがクラウドプロバイダーAPIを通じて見つけた各サーバーで初期化する。
Nodeオブジェクトに、ノードがデプロイされているリージョンや利用可能なリソース(CPU、メモリなど)のようなクラウド特有な情報を注釈付けやラベル付けをする。
ノードのホスト名とネットワークアドレスを取得する。
ノードの正常性を検証する。ノードが応答しなくなった場合、クラウドプロバイダーのAPIを利用しサーバーがdeactivated / deleted / terminatedであるかを確認する。クラウドからノードが削除されていた場合、KubernetesクラスターからNodeオブジェクトを削除する。
いくつかのクラウドプロバイダーは、これをノードコントローラーと個別のノードライフサイクルコントローラーに分けて実装しています。
ルートコントローラー ルートコントローラーは、クラスター内の異なるノード上で稼働しているコンテナが相互に通信できるように、クラウド内のルートを適切に設定する責務を持ちます。
クラウドプロバイダーによっては、ルートコントローラーはPodネットワークのIPアドレスのブロックを割り当てることもあります。
サービスコントローラー Service は、マネージドロードバランサー、IPアドレスネットワークパケットフィルターや対象のヘルスチェックのようなクラウドインフラストラクチャコンポーネントとの統合を行います。サービスコントローラーは、ロードバランサーや他のインフラストラクチャコンポーネントを必要とするServiceリソースを宣言する際にそれらのコンポーネントを設定するため、クラウドプロバイダーのAPIと対話します。
認可 このセクションでは、クラウドコントローラーマネージャーが操作を行うために様々なAPIオブジェクトに必要な権限を分類します。
ノードコントローラー ノードコントローラーはNodeオブジェクトのみに対して働きます。Nodeオブジェクトに対して、readとmodifyの全権限が必要です。
v1/Node:
get
list
create
update
patch
watch
delete
ルートコントローラー ルートコントローラーは、Nodeオブジェクトの作成を待ち受け、ルートを適切に設定します。Nodeオブジェクトについて、get権限が必要です。
v1/Node:
サービスコントローラー サービスコントローラーは、Serviceオブジェクトのcreate 、update 、delete イベントを待ち受け、その後、サービスのロードバランサーを適切に設定します。
Serviceにアクセスするため、list 、watch の権限が必要です。Serviceを更新するため、statusサブリソースへのpatch 、update の権限が必要です。
v1/Service:
list
get
watch
patch
update
その他 クラウドコントローラーマネージャーのコア機能の実装は、Eventオブジェクトのcreate権限と、セキュアな処理を保証するため、ServiceAccountのcreate権限が必要です。
v1/Event:
v1/ServiceAccount:
クラウドコントローラーマネージャーのRBAC ClusterRoleはこのようになります:
apiVersion : rbac.authorization.k8s.io/v1
kind : ClusterRole
metadata :
name : cloud-controller-manager
rules :
- apiGroups :
- ""
resources :
- events
verbs :
- create
- patch
- update
- apiGroups :
- ""
resources :
- nodes
verbs :
- '*'
- apiGroups :
- ""
resources :
- nodes/status
verbs :
- patch
- apiGroups :
- ""
resources :
- services
verbs :
- list
- watch
- apiGroups :
- ""
resources :
- services/status
verbs :
- patch
- update
- apiGroups :
- ""
resources :
- serviceaccounts
verbs :
- create
- apiGroups :
- ""
resources :
- persistentvolumes
verbs :
- get
- list
- update
- watch
次の項目
6 - cgroup v2について
Linuxでは、コントロールグループ がプロセスに割り当てられるリソースを制限しています。
コンテナ化されたワークロードの、CPU/メモリーの要求と制限を含むPodとコンテナのリソース管理 を強制するために、
kubelet と基盤となるコンテナランタイムはcgroupをインターフェースとして接続する必要があります。
Linuxではcgroup v1とcgroup v2の2つのバージョンのcgroupがあります。
cgroup v2は新世代のcgroup APIです。
cgroup v2とは何か?
FEATURE STATE:
Kubernetes v1.25 [stable]
cgroup v2はLinuxのcgroup APIの次のバージョンです。
cgroup v2はリソース管理機能を強化した統合制御システムを提供しています。
以下のように、cgroup v2はcgroup v1からいくつかの点を改善しています。
統合された単一階層設計のAPI
より安全なコンテナへのサブツリーの移譲
Pressure Stall Information などの新機能
強化されたリソース割り当て管理と複数リソース間の隔離
異なるタイプのメモリー割り当ての統一(ネットワークメモリー、カーネルメモリーなど)
ページキャッシュの書き戻しといった、非即時のリソース変更
Kubernetesのいくつかの機能では、強化されたリソース管理と隔離のためにcgroup v2のみを使用しています。
例えば、MemoryQoS 機能はメモリーQoSを改善し、cgroup v2の基本的な機能に依存しています。
cgroup v2を使う cgroup v2を使うおすすめの方法は、デフォルトでcgroup v2が有効で使うことができるLinuxディストリビューションを使うことです。
あなたのディストリビューションがcgroup v2を使っているかどうかを確認するためには、Linux Nodeのcgroupバージョンを特定する を参照してください。
必要要件 cgroup v2を使うには以下のような必要要件があります。
OSディストリビューションでcgroup v2が有効であること
Linuxカーネルバージョンが5.8以上であること
コンテナランタイムがcgroup v2をサポートしていること。例えば、
kubeletとコンテナランタイムがsystemd cgroupドライバー を使うように設定されていること
Linuxディストリビューションのcgroup v2サポート cgroup v2を使っているLinuxディストリビューションの一覧はcgroup v2ドキュメント をご覧ください。
Container-Optimized OS (M97以降)
Ubuntu (21.10以降, 22.04以降推奨)
Debian GNU/Linux (Debian 11 bullseye以降)
Fedora (31以降)
Arch Linux (April 2021以降)
RHEL and RHEL-like distributions (9以降)
あなたのディストリビューションがcgroup v2を使っているかどうかを確認するためには、あなたのディストリビューションのドキュメントを参照するか、Linux Nodeのcgroupバージョンを特定する の説明に従ってください。
カーネルのcmdlineの起動時引数を修正することで、手動であなたのLinuxディストリビューションのcgroup v2を有効にすることもできます。
あなたのディストリビューションがGRUBを使っている場合は、
/etc/default/grubの中のGRUB_CMDLINE_LINUXにsystemd.unified_cgroup_hierarchy=1を追加し、sudo update-grubを実行してください。
ただし、おすすめの方法はデフォルトですでにcgroup v2が有効になっているディストリビューションを使うことです。
cgroup v2への移行 cgroup v2に移行するには、必要要件 を満たすことを確認し、
cgroup v2がデフォルトで有効であるカーネルバージョンにアップグレードします。
kubeletはOSがcgroup v2で動作していることを自動的に検出し、それに応じて処理を行うため、追加設定は必要ありません。
ノード上やコンテナ内からユーザーが直接cgroupファイルシステムにアクセスしない限り、cgroup v2に切り替えたときのユーザー体験に目立った違いはないはずです。
cgroup v2はcgroup v1とは違うAPIを利用しているため、cgroupファイルシステムに直接アクセスしているアプリケーションはcgroup v2をサポートしている新しいバージョンに更新する必要があります。例えば、
サードパーティーの監視またはセキュリティエージェントはcgroupファイルシステムに依存していることがあります。
エージェントをcgroup v2をサポートしているバージョンに更新してください。
Podやコンテナを監視するためにcAdvisor をスタンドアローンのDaemonSetとして起動している場合、v0.43.0以上に更新してください。
Javaアプリケーションをデプロイする場合は、完全にcgroup v2をサポートしているバージョンを利用してください:
uber-go/automaxprocs パッケージを利用している場合は、利用するバージョンがv1.5.1以上であることを確認してください。
Linux Nodeのcgroupバージョンを特定する cgroupバージョンは利用されているLinuxディストリビューションと、OSで設定されているデフォルトのcgroupバージョンに依存します。
あなたのディストリビューションがどちらのcgroupバージョンを利用しているのかを確認するには、stat -fc %T /sys/fs/cgroup/コマンドをノード上で実行してください。
stat -fc %T /sys/fs/cgroup/
cgroup v2では、cgroup2fsと出力されます。
cgroup v1では、tmpfsと出力されます。
次の項目
7 - Kubernetesの自己修復機能
Kubernetesは、ワークロードの健全性と可用性を維持するための自己修復機能を備えています。
ノードが使用不能になった際にはワークロードを再スケジュールし、障害の発生したコンテナを自動的に置き換え、システムの望ましい状態が維持されるようにします。
自己修復機能
コンテナレベルの再起動: Pod内のコンテナが失敗した場合、KubernetesはrestartPolicy に基づいてコンテナを再起動します。
レプリカの置換: Deployment やStatefulSet に属するPodが失敗した場合、Kubernetesは指定されたレプリカ数を維持するために代替のPodを作成します。DaemonSet に属するPodが失敗した場合、コントロールプレーンが同じノード上で実行するための代替Podを作成します。
永続ストレージの復旧: PersistentVolume(PV)をアタッチしたPodが実行されているノードが障害を起こした場合、Kubernetesはそのボリュームを別のノード上の新しいPodに再アタッチできます。
Serviceにおける負荷分散: Service の背後にあるPodが失敗した場合、KubernetesはそのPodをServiceのエンドポイントから自動的に除外し、正常なPodのみにトラフィックをルーティングします。
Kubernetesの自己修復を実現する主なコンポーネントには、次のようなものがあります:
kubelet : コンテナが実行されていることを確認し、失敗したコンテナを再起動します。
ReplicaSet、StatefulSet、DaemonSetコントローラー: Podの望ましいレプリカ数を維持します。
PersistentVolumeコントローラー: ステートフルなワークロードに対してボリュームのアタッチおよびデタッチを管理します。
考慮事項
次の項目
8 - コンテナランタイムインターフェース(CRI)
CRIは、クラスターコンポーネントを再コンパイルすることなく、kubeletがさまざまなコンテナランタイムを使用できるようにするプラグインインターフェースです。
kubelet がPod とそのコンテナを起動できるように、クラスター内の各ノードで動作するcontainer runtime が必要です。
kubeletとContainerRuntime間の通信のメインプロトコルです。
Kubernetes Container Runtime Interface(CRI)は、クラスターコンポーネント kubelet とcontainer runtime 間の通信用のメインgRPC プロトコルを定義します。
API
FEATURE STATE:
Kubernetes v1.23 [stable]
kubeletは、gRPCを介してコンテナランタイムに接続するときにクライアントとして機能します。ランタイムおよびイメージサービスエンドポイントは、コンテナランタイムで使用可能である必要があります。コンテナランタイムは、--image-service-endpointコマンドラインフラグ を使用して、kubelet内で個別に設定できます。
Kubernetes v1.36の場合、kubeletはCRI v1の使用を優先します。
コンテナランタイムがCRIのv1をサポートしていない場合、kubeletはサポートされている古いバージョンのネゴシエーションを試みます。
kubelet v1.36はCRI v1alpha2をネゴシエートすることもできますが、このバージョンは非推奨と見なされます。
kubeletがサポートされているCRIバージョンをネゴシエートできない場合、kubeletはあきらめて、ノードとして登録されません。
アップグレード Kubernetesをアップグレードする場合、kubeletはコンポーネントの再起動時に最新のCRIバージョンを自動的に選択しようとします。
それが失敗した場合、フォールバックは上記のように行われます。
コンテナランタイムがアップグレードされたためにgRPCリダイヤルが必要な場合は、コンテナランタイムも最初に選択されたバージョンをサポートする必要があります。
そうでない場合、リダイヤルは失敗することが予想されます。これには、kubeletの再起動が必要です。
次の項目
9 - ガベージコレクション
ガベージコレクションは、Kubernetesがクラスターリソースをクリーンアップするために使用するさまざまなメカニズムの総称です。これにより、次のようなリソースのクリーンアップが可能になります:
オーナーの依存関係 Kubernetesの多くのオブジェクトは、owner reference を介して相互にリンクしています。
owner referenceは、どのオブジェクトが他のオブジェクトに依存しているかをコントロールプレーンに通知します。
Kubernetesは、owner referenceを使用して、コントロールプレーンやその他のAPIクライアントに、オブジェクトを削除する前に関連するリソースをクリーンアップする機会を提供します。
ほとんどの場合、Kubernetesはowner referenceを自動的に管理します。
Ownershipは、一部のリソースでも使用されるラベルおよびセレクター メカニズムとは異なります。
たとえば、EndpointSliceオブジェクトを作成するService を考えます。
Serviceはラベル を使用して、コントロールプレーンがServiceに使用されているEndpointSliceオブジェクトを判別できるようにします。
ラベルに加えて、Serviceに代わって管理される各EndpointSliceには、owner referenceがあります。
owner referenceは、Kubernetesのさまざまな部分が制御していないオブジェクトへの干渉を回避するのに役立ちます。
備考: namespace間のowner referenceは、設計上許可されていません。
namespaceの依存関係は、クラスタースコープまたはnamespaceのオーナーを指定できます。
namespaceのオーナーは、依存関係と同じnamespaceに存在する必要があります 。
そうでない場合、owner referenceは不在として扱われ、すべてのオーナーが不在であることが確認されると、依存関係は削除される可能性があります。
クラスタースコープの依存関係は、クラスタースコープのオーナーのみを指定できます。
v1.20以降では、クラスタースコープの依存関係がnamespaceを持つkindをオーナーとして指定している場合、それは解決できないowner referenceを持つものとして扱われ、ガベージコレクションを行うことはできません。
V1.20以降では、ガベージコレクタは無効な名前空間間のownerReference、またはnamespaceのkindを参照するownerReferenceをもつクラスター・スコープの依存関係を検出した場合、無効な依存関係のOwnerRefInvalidNamespaceとinvolvedObjectを理由とする警告イベントが報告されます。
以下のコマンドを実行すると、そのようなイベントを確認できます。
kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace
カスケード削除 Kubernetesは、ReplicaSetを削除したときに残されたPodなど、owner referenceがなくなったオブジェクトをチェックして削除します。
オブジェクトを削除する場合、カスケード削除と呼ばれるプロセスで、Kubernetesがオブジェクトの依存関係を自動的に削除するかどうかを制御できます。
カスケード削除には、次の2つのタイプがあります。
フォアグラウンドカスケード削除
バックグラウンドカスケード削除
また、Kubernetes finalizer を使用して、ガベージコレクションがowner referenceを持つリソースを削除する方法とタイミングを制御することもできます。
フォアグラウンドカスケード削除 フォアグラウンドカスケード削除では、削除するオーナーオブジェクトは最初に削除進行中 の状態になります。
この状態では、オーナーオブジェクトに次のことが起こります。
Kubernetes APIサーバーは、オブジェクトのmetadata.deletionTimestampフィールドを、オブジェクトに削除のマークが付けられた時刻に設定します。
Kubernetes APIサーバーは、metadata.finalizersフィールドをforegroundDeletionに設定します。
オブジェクトは、削除プロセスが完了するまで、KubernetesAPIを介して表示されたままになります。
オーナーオブジェクトが削除進行中の状態に入ると、コントローラーは依存関係を削除します。
すべての依存関係オブジェクトを削除した後、コントローラーはオーナーオブジェクトを削除します。
この時点で、オブジェクトはKubernetesAPIに表示されなくなります。
フォアグラウンドカスケード削除中に、オーナーの削除をブロックする依存関係は、ownerReference.blockOwnerDeletion=trueフィールドを持つ依存関係のみです。
詳細については、フォアグラウンドカスケード削除の使用 を参照してください。
バックグラウンドカスケード削除 バックグラウンドカスケード削除では、Kubernetes APIサーバーがオーナーオブジェクトをすぐに削除し、コントローラーがバックグラウンドで依存オブジェクトをクリーンアップします。
デフォルトでは、フォアグラウンド削除を手動で使用するか、依存オブジェクトを孤立させることを選択しない限り、Kubernetesはバックグラウンドカスケード削除を使用します。
詳細については、バックグラウンドカスケード削除の使用 を参照してください。
孤立した依存関係 Kubernetesがオーナーオブジェクトを削除すると、残された依存関係はorphan オブジェクトと呼ばれます。
デフォルトでは、Kubernetesは依存関係オブジェクトを削除します。この動作をオーバーライドする方法については、オーナーオブジェクトの削除と従属オブジェクトの孤立 を参照してください。
未使用のコンテナとイメージのガベージコレクション kubelet は未使用のイメージに対して5分ごとに、未使用のコンテナに対して1分ごとにガベージコレクションを実行します。
外部のガベージコレクションツールは、kubeletの動作を壊し、存在するはずのコンテナを削除する可能性があるため、使用しないでください。
未使用のコンテナとイメージのガベージコレクションのオプションを設定するには、設定ファイル を使用してkubeletを調整し、KubeletConfiguration リソースタイプを使用してガベージコレクションに関連するパラメーターを変更します。
コンテナイメージのライフサイクル Kubernetesは、kubeletの一部であるイメージマネージャー を通じて、cadvisor の協力を得て、すべてのイメージのライフサイクルを管理します。kubeletは、ガベージコレクションを決定する際に、次のディスク使用制限を考慮します。
HighThresholdPercent
LowThresholdPercent
設定されたHighThresholdPercent値を超えるディスク使用量はガベージコレクションをトリガーします。
ガベージコレクションは、最後に使用された時間に基づいて、最も古いものから順にイメージを削除します。
kubeletは、ディスク使用量がLowThresholdPercent値に達するまでイメージを削除します。
コンテナのガベージコレクション kubeletは、次の変数に基づいて未使用のコンテナをガベージコレクションします。
MinAge: kubeletがガベージコレクションできるコンテナの最低期間。0を設定すると無効化されます。
MaxPerPodContainer: 各Podが持つことができるデッドコンテナの最大数。0未満に設定すると無効化されます。
MaxContainers: クラスターが持つことができるデッドコンテナの最大数。0未満に設定すると無効化されます。
これらの変数に加えて、kubeletは、通常、最も古いものから順に、定義されていない削除されたコンテナをガベージコレクションします。
MaxPerPodContainerとMaxContainersは、Podごとのコンテナの最大数(MaxPerPodContainer)を保持すると、グローバルなデッドコンテナの許容合計(MaxContainers)を超える状況で、互いに競合する可能性があります。
この状況では、kubeletはMaxPerPodContainerを調整して競合に対処します。最悪のシナリオは、MaxPerPodContainerを1にダウングレードし、最も古いコンテナを削除することです。
さらに、削除されたPodが所有するコンテナは、MinAgeより古くなると削除されます。
備考: kubeletがガベージコレクションするのは、自分が管理するコンテナのみです。
ガベージコレクションの設定 これらのリソースを管理するコントローラーに固有のオプションを設定することにより、リソースのガベージコレクションを調整できます。次のページは、ガベージコレクションを設定する方法を示しています。
次の項目
10 - Mixed Version Proxy
FEATURE STATE:
Kubernetes v1.36 [beta](enabled by default)
Kubernetes 1.36には、APIサーバー が他の ピア APIサーバーにリソースリクエストをプロキシできるようにするアルファ機能が含まれています。
また、クライアントがディスカバリを通じてクラスター全体で提供されるリソースの全体像を取得することもできます。
これは、1つのクラスター内で異なるバージョンのKubernetesを実行する複数のAPIサーバーがある場合に役立ちます(例えば、Kubernetesの新しいリリースへの長期間にわたるロールアウト中など)。
これにより、クラスター管理者は、より安全にアップグレードできる高可用性クラスターを設定できます:
重要なタスクでリソースの包括的なリストを表示するためにディスカバリに依存するコントローラーが、常にすべてのリソースの完全なビューを取得できるようにします。
この完全なクラスター全体のディスカバリを ピア集約ディスカバリ と呼びます。
(アップグレード中に行われる)リソースリクエストを正しいkube-apiserverに転送します。
このプロキシにより、ユーザーはアップグレードプロセスに起因する予期しない404 Not Foundエラーを見ることがなくなります。
このメカニズムは Mixed Version Proxy と呼ばれます。
ピア集約ディスカバリとMixed Version Proxyの有効化 APIサーバー を起動する際に、UnknownVersionInteroperabilityProxyフィーチャーゲート が有効になっていることを確認してください:
kube-apiserver \
--feature-gates= UnknownVersionInteroperabilityProxy = true \
# この機能に必要なコマンドライン引数
--peer-ca-file= <kube-apiserver CA証明書へのパス>
--proxy-client-cert-file= <アグリゲータープロキシ証明書へのパス>,
--proxy-client-key-file= <アグリゲータープロキシ鍵へのパス>,
--requestheader-client-ca-file= <アグリゲーターCA証明書へのパス>,
# requestheader-allowed-namesは、任意のCommon Nameを許可するために空白に設定できます
--requestheader-allowed-names= <プロキシクライアント証明書を検証するための有効なCommon Names>,
# この機能のオプションフラグ
--peer-advertise-ip= ` ピアがリクエストをプロキシするために使用するこのkube-apiserverのIP`
--peer-advertise-port= ` ピアがリクエストをプロキシするために使用するこのkube-apiserverのポート`
# …その他のフラグは通常通り
APIサーバー間のプロキシトランスポートと認証
ソースkube-apiserverは、既存のAPIサーバークライアント認証フラグ --proxy-client-cert-fileと--proxy-client-key-fileを再利用して、ピア(宛先kube-apiserver)によって検証される自身のIDを提示します。
宛先APIサーバーは、--requestheader-client-ca-fileコマンドライン引数を使用して指定した設定に基づいてピア接続を検証します。
宛先サーバーのサービング証明書を認証するには、ソース APIサーバーに--peer-ca-fileコマンドライン引数を使用して認証局バンドルを設定する必要があります。
ピアAPIサーバー接続の設定 ピアがリクエストをプロキシするために使用するkube-apiserverのネットワークロケーションを設定するには、kube-apiserverに--peer-advertise-ipと--peer-advertise-portコマンドライン引数を使用するか、APIサーバー設定ファイルでこれらのフィールドを指定します。
これらのフラグが指定されていない場合、ピアはkube-apiserverの--advertise-addressまたは--bind-addressコマンドライン引数の値を使用します。
それらも設定されていない場合、ホストのデフォルトインターフェースが使用されます。
ピア集約ディスカバリ この機能を有効にすると、ディスカバリリクエストはデフォルトで包括的なディスカバリドキュメント(クラスター内のすべてのapiserverによって提供されるすべてのリソースをリストする)を提供するように自動的に有効になります。
ピア集約されていないディスカバリドキュメントをリクエストしたい場合は、ディスカバリリクエストに次のAcceptヘッダーを追加することでそれを示すことができます:
application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList;profile=nopeer
Mixed version proxying Mixed version proxyingを有効にすると、アグリゲーションレイヤー は次の処理を行う特別なフィルターをロードします:
APIサーバーがそのAPIを提供できない場合(APIが導入される前のバージョンであるか、そのAPIサーバーでAPIが無効になっているため)、リソースリクエストがAPIサーバーに到達すると、そのAPIサーバーはリクエストされたAPIを提供できるピアAPIサーバーにリクエストを送信しようとします。
これは、ローカルサーバーが認識しないAPIグループ/バージョン/リソースを識別し、リクエストを処理できるピアAPIサーバーにそれらのリクエストをプロキシしようとすることで実現されます。
ピアAPIサーバーが応答に失敗した場合、ソース APIサーバーは503(「Service Unavailable」)エラーで応答します。
内部での動作 APIサーバーがリソースリクエストを受信すると、最初にどのAPIサーバーがリクエストされたリソースを提供できるかを確認します。
この確認は、ピア集約されていないディスカバリドキュメントを使用して行われます。
リクエストを受信したAPIサーバーから取得したピア集約されていないディスカバリドキュメントにリソースがリストされている場合(例えば、GET /api/v1/pods/some-pod)、リクエストはローカルで処理されます。
リクエスト内のリソース(例えば、GET /apis/resource.k8s.io/v1beta1/resourceclaims)が、リクエストを処理しようとしているAPIサーバー(処理APIサーバー )から取得したピア集約されていないディスカバリドキュメントに見つからない場合、おそらくresource.k8s.io/v1beta1 APIがより新しいKubernetesバージョンで導入され、処理APIサーバー がそれをサポートしていない古いバージョンを実行しているためです。
その場合、処理APIサーバー はすべてのピアAPIサーバーからピア集約されていないディスカバリドキュメントを確認して、関連するAPIグループ/バージョン/リソース(この場合はresource.k8s.io/v1beta1/resourceclaims)を提供するピアAPIサーバーを取得します。
処理APIサーバー は、リクエストされたリソースを認識している一致するピアkube-apiserverの1つにリクエストをプロキシします。
そのAPIグループ/バージョン/リソースを認識しているピアがいない場合、処理APIサーバーは自身のハンドラーチェーンにリクエストを渡し、最終的に404(「Not Found」)レスポンスを返すはずです。
処理APIサーバーがピアAPIサーバーを識別して選択したが、そのピアが応答に失敗した場合(ネットワーク接続の問題、またはリクエストの受信とコントローラーがピアの情報をコントロールプレーンに登録する間のデータ競合などの理由)、処理APIサーバーは503(「Service Unavailable」)エラーで応答します。