クラスターのアーキテクチャ 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
コマンドラインフラグまたはfailSwapOn
KubeletConfiguration を 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.io
APIグループの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のcontrol plane コンポーネントです。クラウドコントロールマネージャーは、クラスターをクラウドプロバイダーAPIをリンクし、クラスターのみで相互作用するコンポーネントからクラウドプラットフォームで相互作用するコンポーネントを分離します。
Kubernetesと下のクラウドインフラストラクチャー間の相互運用ロジックを分離することで、cloud-controller-managerコンポーネントはクラウドプロバイダを主なKubernetesプロジェクトと比較し異なるペースで機能をリリース可能にします。
cloud-controller-managerは、プラグイン機構を用い、異なるクラウドプロバイダーに対してそれぞれのプラットフォームとKubernetesの結合を可能にする構成になっています。
設計
クラウドコントローラーマネージャーは、複製されたプロセスの集合としてコントロールプレーンで実行されます。(通常、Pod内のコンテナとなります)各cloud-controller-managerは、シングルプロセスで複数のcontrollers を実装します。
備考: コントロールプレーンの一部ではなく、Kubernetesの
addon としてクラウドコントローラーマネージャーを実行することもできます。
クラウドコントローラーマネージャーの機能 クラウドコントローラーマネージャーのコントローラーは以下を含んでいます。
ノードコントローラー ノードコントローラーは、クラウドインフラストラクチャーで新しいサーバーが作成された際に、Node オブジェクトを作成する責務を持ちます。ノードコントローラーは、クラウドプロバイダーのテナント内で動作しているホストの情報を取得します。ノードコントローラーは下記に示す機能を実行します:
Nodeオブジェクトを、コントローラーがクラウドプロバイダーAPIを通じて見つけた各サーバーで初期化する Nodeオブジェクトに、ノードがデプロイされているリージョンや利用可能なリソース(CPU、メモリなど)のようなクラウド特有な情報を注釈付けやラベル付けをする ノードのホスト名とネットワークアドレスを取得する ノードの正常性を検証する。ノードが応答しなくなった場合、クラウドプロバイダーのAPIを利用しサーバーがdeactivated / deleted / terminatedであるかを確認する。クラウドからノードが削除されていた場合、KubernetesクラスターからNodeオブジェクトを削除する いくつかのクラウドプロバイダーは、これをノードコントローラーと個別のノードライフサイクルコントローラーに分けて実装しています。
ルートコントローラー ルートコントローラーは、クラスター内の異なるノード上で稼働しているコンテナが相互に通信できるように、クラウド内のルートを適切に設定する責務を持ちます。
クラウドプロバイダーによっては、ルートコントローラーはPodネットワークのIPアドレスのブロックを割り当てることもあります。
サービスコントローラー Services は、マネージドロードバランサー、IPアドレスネットワークパケットフィルタや対象のヘルスチェックのようなクラウドインフラストラクチャーコンポーネントのインテグレーションを行います。サービスコントローラーは、ロードバランサーや他のインフラストラクチャーコンポーネントを必要とするServiceリソースを宣言する際にそれらのコンポーネントを設定するため、クラウドプロバイダーのAPIと対話します。
認可 このセクションでは、クラウドコントローラーマネージャーが操作を行うために様々なAPIオブジェクトに必要な権限を分類します。
ノードコントローラー ノードコントローラーはNodeオブジェクトのみに対して働きます。Nodeオブジェクトに対して、readとmodifyの全権限が必要です。
v1/Node
:
Get List Create Update Patch Watch Delete ルートコントローラー ルートコントローラーは、Nodeオブジェクトの作成を待ち受け、ルートを適切に設定します。Nodeオブジェクトについて、get権限が必要です。
v1/Node
:
サービスコントローラー サービスコントローラーは、Serviceオブジェクトの作成、更新、削除イベントを待ち受け、その後、サービスのEndpointを適切に設定します。
サービスにアクセスするため、list、watchの権限が必要です。サービスを更新するため、patch、updateの権限が必要です。
サービスのEndpointリソースを設定するため、create、list、get、watchそしてupdateの権限が必要です。
v1/Service
:
その他 クラウドコントローラーマネージャーのコア機能の実装は、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
- patch
- update
- watch
- apiGroups :
- ""
resources :
- serviceaccounts
verbs :
- create
- apiGroups :
- ""
resources :
- persistentvolumes
verbs :
- get
- list
- update
- watch
- apiGroups :
- ""
resources :
- endpoints
verbs :
- create
- get
- list
- watch
- update
次の項目 Cloud Controller Manager Administration
はクラウドコントラーマネージャーの実行と管理を説明しています。
どのようにあなた自身のクラウドコントローラーマネージャーが実装されるのか、もしくは既存プロジェクトの拡張について知りたいですか?
クラウドコントローラーマネージャーは、いかなるクラウドからもプラグインとしての実装を許可するためにGoインターフェースを使います。具体的には、kubernetes/cloud-provider の cloud.go
で定義されているCloudProvider
を使います。
本ドキュメントでハイライトした共有コントローラー(Node、Route、Service)の実装と共有クラウドプロバイダーインターフェースに沿ったいくつかの足場は、Kubernetesコアの一部です。クラウドプロバイダに特化した実装は、Kubernetesのコアの外部として、またCloudProvider
インターフェースを実装します。
プラグイン開発ついての詳細な情報は、Developing Cloud Controller Manager を見てください。
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 - コンテナランタイムインターフェース(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.32の場合、kubeletはCRI v1
の使用を優先します。
コンテナランタイムがCRIのv1
をサポートしていない場合、kubeletはサポートされている古いバージョンのネゴシエーションを試みます。
kubelet v1.32はCRI v1alpha2
をネゴシエートすることもできますが、このバージョンは非推奨と見なされます。
kubeletがサポートされているCRIバージョンをネゴシエートできない場合、kubeletはあきらめて、ノードとして登録されません。
アップグレード Kubernetesをアップグレードする場合、kubeletはコンポーネントの再起動時に最新のCRIバージョンを自動的に選択しようとします。
それが失敗した場合、フォールバックは上記のように行われます。
コンテナランタイムがアップグレードされたためにgRPCリダイヤルが必要な場合は、コンテナランタイムも最初に選択されたバージョンをサポートする必要があります。
そうでない場合、リダイヤルは失敗することが予想されます。これには、kubeletの再起動が必要です。
次の項目 8 - ガベージコレクション ガベージコレクションは、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がガベージコレクションするのは、自分が管理するコンテナのみです。ガベージコレクションの設定 これらのリソースを管理するコントローラーに固有のオプションを設定することにより、リソースのガベージコレクションを調整できます。次のページは、ガベージコレクションを設定する方法を示しています。
次の項目