Kubernetesアーキテクチャのさまざまなコンポーネントがどのように組み合わされているかを理解することで、問題のトラブルシューティング、健全なクラスタの維持、ワークフローの最適化をより的確に行うことができます。
Kubernetesを使ってコンテナをオーケストレーションするという説明は簡単ですが、それが実際に何を意味するのか、どのように実装するのかを理解するのは全く別の問題です。Kubernetesクラスタを実行または管理しているのであれば、Kubernetesが「」と呼ばれる1つのマシンと、その他の多くのマシンから構成されていることはご存知でしょう。それぞれのタイプには、オーケストレーションを可能にする複雑だが安定したスタックがあり、各コンポーネントに精通していることは、それがどのように機能するかを理解するのに役立ちます。
制御プレーン・コンポーネント
Kubernetesは""というマシンにインストールされ、Kubernetesデーモンが実行され、コンテナや.NETを起動するときにKubernetesと通信します。以下に、コントロールプレーンのコンポーネントについて説明します。
etcd
etcdは、コンテナグループ、レプリカコントローラ、キー、サービスなどのKubernetesオブジェクトデータの永続ストレージとして使用される、高速で分散された一貫性のあるキーバリューストアです。etcdに直接接続されているコンポーネントはKubernetes APIサーバだけです。他のすべてのコンポーネントは、APIサーバを介して間接的にetcdからデータを読み書きします。
etcdはまた、キーの変更を非同期で監視するためのイベントベースのインタフェースを提供する監視機能を実装しています。APIサーバコンポーネントは、etcdに通知され、etcdを望ましい状態に変更するために、これに大きく依存しています。
通常、可用性の高い環境を実現するためにetcdのインスタンスを3台、5台、7台と稼働させますが、それはなぜでしょうか。etcdは分散データストアであるため、水平方向にスケールさせることができますが、各インスタンスのデータが一貫していることを確認する必要があります。そのため、システムの現在の状態についてコンセンサスを得る必要があり、etcdはこのために RAFTコンセンサスアルゴリズムを使用しています。
RAFTアルゴリズムでは、次の状態に移行するためにクラスタの選出が必要です。etcdインスタンスが2台しかなく、そのうちの1台に障害が発生した場合、etcdクラスタは新しい状態に移行できません。etcdインスタンスが3台ある場合、1台が故障しても、まだ選挙に利用できるインスタンスが2台あります。
API サーバ
APIサーバーは、Kubernetesで唯一etcdと直接やり取りするコンポーネントです。Kubernetesの他のすべてのコンポーネントは、クライアントを含むクラスタの状態を処理するためにAPIサーバーを経由する必要があります:
- etcd にオブジェクトを格納する一貫した方法を提供します。
- クライアントが正しく設定されていないオブジェクトを保存しないように、オブジェクトの検証を実行します。
- リソースの作成、更新、変更、削除を行うための RESTful API を提供します。
- 楽観的同時実行ロックを提供し、更新が発生したときに他のクライアントがオブジェクトを書き換える機会がないようにします。
- クライアントから送信されたリクエストの認証と認可を行います。プラグインを使用してクライアントのユーザ名、ID、所属グループを抽出し、認証されたユーザが要求されたリソースに対して要求された操作を実行できるかどうかを判断します。
- ユーザクライアントが変更を監視する監視メカニズムが実装されています。これにより、スケジューラやコントローラマネージャなどのコンポーネントがAPIサーバと疎結合でやり取りできるようになります。
コントローラー・マネージャー
Kubernetesでは、コントローラはクラスタの状態を継続的に監視し、必要に応じて変更を行ったり要求したりします。各コントローラは、現在のクラスタ状態を目的の状態に変更しようとします。コントローラは少なくとも1つのKubernetesリソースタイプを追跡し、これらのオブジェクトのそれぞれには、希望する状態を表すフィールドがあります。
コントローラの例:
- コピーマネージャー
- DaemonSet、DaemonSetおよびタスクコントローラ
- 展開コントローラ
- ステートフルロードコントローラ
- ノードコントローラ
- サービスコントローラー
- アクセスポイントコントローラ
- 名前空間コントローラ
- コントローラ
コントローラは監視メカニズムを通じて変更の通知を受けます。コントローラはAPIサーバーのリソースの変更を監視し、新しいオブジェクトであれ、既存のオブジェクトの更新や削除であれ、それぞれの変更に対して操作を実行します。ほとんどの場合、これらの操作には他のリソースの作成や監視対象リソース自体の更新が含まれます。しかし、モニタリングの使用は、コントローラがイベントを見逃さないことを保証するものではないため、コントローラはまた、イベントを見逃さないように定期的に一連の操作を実行します。
スケジューラ
スケジューラは、コンテナ・グループをノードに割り当てる制御プレーン・プロセスです。新しく作成されたコンテナグループで、ノードが割り当てられていないものを監視します。スケジューラは、発見された各コンテナ・グループに、それを実行するのに最適なノードを割り当てます。
コンテナ・グループのスケジューリング要件を満たすノードをスケジューラブル・ノードと呼びます。適切なノードがない場合、コンテナ・グループはスケジューラが配置できるまでスケジュールされていない状態になります。スケジューラがスケジューリング可能なノードを見つけると、ノードをスコアリングする一連の関数を実行し、最もスコアの高いノードを選択します。このプロセスをバインディングと呼びます。
ノードは2つのステップで選択されます:
- 全ノードのリストをフィルタリングして、コンテナ・グループをスケジュールできるノードのリストを取得します。
- 最初のステップで得られたノードのリストをスコアリングしてソートし、最適なノードを選択します。最高得点のノードが複数ある場合は、ループ処理によってコンテナ・グループがすべてのノードに均等に配置されるようにします。
スケジュールを決定する際に考慮すべき要素には、以下のようなものがあります:
- コンテナグループがハードウェア/ソフトウェアリソースを要求していますか?ノードはメモリまたはディスクのプレッシャー状態を報告していますか?
- ノードに、コンテナ・グループ仕様のノード・セレクタと一致するラベルがありますか?
- コンテナ・グループが特定のローカル・ホスト・ポートへのバインドを要求した場合、そのポートは利用可能ですか?
- コンテナグループはノードの汚染を許容しますか?
- コンテナ・グループは、ノード・アフィニティまたはアンチ・アフィニティ・ルールを指定していますか?
スケジューラは、選択したノードにコンテナグループの実行を指示しません。スケジューラが行うのは、APIサーバー経由でコンテナグループの定義を更新することだけです。その後、API サーバーは監視メカニズムを通じてコンテナ・グループがディスパッチされたことを kubelet に通知し、ターゲット・ノード上の kubelet サービスはコンテナ・グループがそのノードにディスパッチされたことを確認し、コンテナ・グループを作成して実行します。
作業ノードコンポーネント
ワーカーノードはkubeletエージェントを実行し、コントロールプレーンが負荷に対応するためにエージェントを許可します。制御プレーンと同様に、ワーカーノードもこれを実現するためにいくつかの異なるコンポーネントを使用します。 以下のセクションでは、ワーカーノードのコンポーネントについて説明します。
Kubelet
Kubeletはクラスタ内の各ノードで実行されるエージェントで、作業ノードで実行されるすべての責任を負います。コンテナがポッド内で実行されていることを保証します。
kubeletサービスの主な機能は次のとおりです:
- APIサーバーにノード・リソースを作成して、実行するノードを登録します。
- APIサーバー上のノードにスケジューリングされたコンテナのグループを継続的に監視します。
- 設定されたコンテナランタイムを使用して、コンテナグループのコンテナを起動します。
- 実行中のコンテナを継続的に監視し、ステータス、イベント、リソース消費をAPIサーバーにレポートします。
- コンテナ生存プローブを実行し、プローブ失敗時にコンテナを再起動し、コンテナグループが API サーバーから削除されると終了します。
サービスエージェント
サービスエージェントは各ノード上で実行され、あるコンテナグループが別のコンテナグループと通信できるようにし、あるノードが別のノードと通信できるようにし、あるコンテナが別のコンテナと通信できるようにします。サービス・エージェントは、サービスやコンテナ・グループの定義に変更がないか API サーバを監視して、ネットワーク全体の設定を最新の状態に保つ役割を果たします。あるサービスが複数のコンテナグループでサポートされている場合、エージェントはこれらのコンテナグループ間でロードバランシングを実行します。
kube-proxyがプロキシと呼ばれるのは、元々は接続を受け付け、コンテナグループにプロキシするためのプロキシサーバであったためです。現在の実装では、iptablesルールを使用して、実際のプロキシサーバーを経由せずにランダムに選択されたバックエンドコンテナグループにパケットをリダイレクトします。
どのように機能するかについての高度な見解:
- サービスを作成すると、すぐに仮想IPアドレスが割り当てられます。
- APIサーバーは、ワーカーノード上で実行されているkube-proxyエージェントに新しいサービスがあることを通知します。
- 各kube-proxyは、各サービスのIP/ポートペアがインターセプトされ、宛先アドレスがサービスをサポートするコンテナグループの1つに変更されるようにiptablesルールを設定することで、サービスをアドレス指定可能にします。
- APIサーバーによるサービスまたはそのエンドポイントオブジェクトへの変更を監視します。
コンテナランタイム
コンテナランタイムには2種類あります:
- 下位レベルのコンテナ・ランタイム: 主にコンテナの実行と、名前空間とコンテナの設定を行います。
- 上位レベルのコンテナランタイム: フォーマット、解凍、管理、イメージの共有、開発者向けAPIの提供に重点を置いています。
コンテナランタイムが責任を負います:
- コンテナイメージがローカルに存在しない場合は、イメージリポジトリから抽出されます。
- イメージをコピーオンライトファイルシステムに展開し、すべてのコンテナレイヤーをスタックしてマージファイルシステムを作成します。
- コンテナのマウントポイントを準備します。
- オーバーライドコマンド、ユーザー入力コマンド、SECCOMP ルールの設定など、コンテナイメージのメタデータを設定することで、コンテナが期待どおりに動作するようになります。
- プロセス、ネットワーク、ファイルシステムなどの分離をコンテナに割り当てるようにカーネルに通知します。
- CPUやメモリの制限など、リソースの制限を割り当てるようにカーネルに通知します。
- カーネルブートコンテナにシステムコールを渡します。
- SElinux/AppArmorの設定が正しいことを確認してください。
コラボレーション
システムレベルのコンポーネントは、Kubernetesクラスタの各部分がその目的を果たし、機能を実行するように連携します。 編集に没頭すると、リクエストがクラスタ全体でどのように通信しているかを理解するのが難しくなることがあります。各部分がどのように組み合わされているかを理解することで、Kubernetes内部で何が起こっているかをより理解できるようになり、問題の診断、健全なクラスタの維持、ワークフローの最適化に役立ちます。
経由




