序章

Kubernetesは、クラスタ化された環境でコンテナ化されたアプリケーションを管理するために、最初はGoogleによって開発された強力なオープンソースシステムです。 これは、さまざまなインフラストラクチャ全体で関連する分散コンポーネントとサービスを管理するためのより良い方法を提供することを目的としています。

このガイドでは、Kubernetesの基本的な概念のいくつかについて説明します。 システムのアーキテクチャー、システムが解決する問題、およびコンテナー化されたデプロイメントとスケーリングを処理するためにシステムが使用するモデルについて説明します。

Kubernetesとは何ですか?

Kubernetes は、基本レベルで、マシンのクラスター全体でコンテナー化されたアプリケーションを実行および調整するためのシステムです。 これは、予測可能性、スケーラビリティ、および高可用性を提供する方法を使用して、コンテナ化されたアプリケーションとサービスのライフサイクルを完全に管理するように設計されたプラットフォームです。

Kubernetesユーザーは、アプリケーションの実行方法と、他のアプリケーションや外部とのやり取りの方法を定義できます。 サービスをスケールアップまたはスケールダウンし、適切なローリング更新を実行し、アプリケーションの異なるバージョン間でトラフィックを切り替えて、機能をテストしたり、問題のあるデプロイメントをロールバックしたりできます。 Kubernetesは、高度な柔軟性、パワー、信頼性でアプリケーションを定義および管理できるようにするインターフェースとコンポーザブルプラットフォームプリミティブを提供します。

Kubernetesアーキテクチャ

Kubernetesがこれらの機能をどのように提供できるかを理解するには、Kubernetesがどのように設計および編成されているかを高レベルで理解することが役立ちます。 Kubernetesは、レイヤーに組み込まれたシステムとして視覚化できます。各レイヤーは、下位レベルに見られる複雑さを抽象化します。

基本的に、Kubernetesは、共有ネットワークを使用して個々の物理マシンまたは仮想マシンをクラスターにまとめ、各サーバー間で通信します。 このクラスタは、すべてのKubernetesコンポーネント、機能、およびワークロードが設定されている物理プラットフォームです。

クラスタ内のマシンには、それぞれKubernetesエコシステム内での役割が与えられます。 1台のサーバー(または高可用性デプロイメントの小グループ)は、マスターサーバーとして機能します。 このサーバーは、ユーザーとクライアントのAPIを公開し、他のサーバーのヘルスチェックを行い、作業の分割と割り当て(「スケジューリング」と呼ばれる)の最適な方法を決定し、他のコンポーネント間の通信を調整することにより、クラスターのゲートウェイおよび頭脳として機能します。 マスターサーバーは、クラスターとの主要な接続ポイントとして機能し、Kubernetesが提供するほとんどの集中型ロジックを担当します。

クラスター内の他のマシンは、ノードとして指定されます。ローカルおよび外部リソースを使用してワークロードを受け入れて実行するサーバーです。 分離、管理、柔軟性を支援するために、Kubernetesは container でアプリケーションとサービスを実行するため、各ノードにコンテナーランタイム(Dockerやrktなど)を装備する必要があります。 ノードはマスターサーバーから作業指示を受け取り、それに応じてコンテナーを作成または破棄し、ネットワークルールを調整してトラフィックを適切にルーティングおよび転送します。

上記のように、アプリケーションとサービス自体は、コンテナー内のクラスターで実行されます。 基盤となるコンポーネントは、アプリケーションの望ましい状態がクラスターの実際の状態と一致することを確認します。 ユーザーは、メインAPIサーバーと直接、またはクライアントとライブラリと通信することにより、クラスターと対話します。 アプリケーションまたはサービスを起動するために、何を作成し、どのように管理するかを定義する宣言型プランがJSONまたはYAMLで送信されます。 次に、マスターサーバーは計画を取得し、要件とシステムの現在の状態を調べて、インフラストラクチャで計画を実行する方法を理解します。 指定されたプランに従って実行されるユーザー定義アプリケーションのこのグループは、Kubernetesの最終レイヤーを表します。

マスターサーバーコンポーネント

上で説明したように、マスターサーバーはKubernetesクラスターのプライマリコントロールプレーンとして機能します。 これは、管理者とユーザーの主要な連絡先として機能し、比較的洗練されていないワーカーノードにクラスター全体の多くのシステムを提供します。 全体として、マスターサーバー上のコンポーネントは連携して、ユーザーリクエストを受け入れ、ワークロードコンテナーをスケジュールし、クライアントとノードを認証し、クラスター全体のネットワークを調整し、スケーリングとヘルスチェックの責任を管理するための最良の方法を決定します。

これらのコンポーネントは、単一のマシンにインストールすることも、複数のサーバーに分散させることもできます。 このセクションでは、マスターサーバーに関連付けられている個々のコンポーネントをそれぞれ見ていきます。

etcd

Kubernetesが機能するために必要な基本的なコンポーネントの1つは、グローバルに利用可能な構成ストアです。 CoreOSのチームによって開発されたetcdプロジェクトは、複数のノードにまたがるように構成できる軽量の分散型Key-Valueストアです。

Kubernetesは etcd クラスタ内の各ノードからアクセスできる構成データを格納します。 これはサービス検出に使用でき、コンポーネントが最新の情報に従って自身を構成または再構成するのに役立ちます。 また、リーダー選出や分散ロックなどの機能を使用して、クラスターの状態を維持するのにも役立ちます。 単純なHTTP/JSON APIを提供することにより、値を設定または取得するためのインターフェースは非常に簡単です。

コントロールプレーンの他のほとんどのコンポーネントと同様に、 etcd 単一のマスターサーバー上で構成することも、実稼働シナリオでは複数のマシンに分散させることもできます。 唯一の要件は、各Kubernetesマシンがネットワークにアクセスできることです。

kube-apiserver

最も重要なマスターサービスの1つはAPIサーバーです。 これは、ユーザーがKubernetesのワークロードと組織単位を構成できるようにするため、クラスター全体の主要な管理ポイントです。 また、 etcd デプロイされたコンテナのストアとサービスの詳細は一致しています。 これは、クラスターの正常性を維持し、情報とコマンドを広めるためのさまざまなコンポーネント間のブリッジとして機能します。

APIサーバーはRESTfulインターフェースを実装しています。これは、多くの異なるツールやライブラリーがRESTfulインターフェースと容易に通信できることを意味します。 kubectl と呼ばれるクライアントは、ローカルコンピューターからKubernetesクラスターと対話するデフォルトの方法として使用できます。

kube-controller-manager

コントローラマネージャは、多くの責任を持つ一般的なサービスです。 主に、クラスターの状態を調整し、ワークロードのライフサイクルを管理し、日常的なタスクを実行するさまざまなコントローラーを管理します。 たとえば、レプリケーションコントローラーは、ポッドに定義されたレプリカ(同一のコピー)の数が、クラスターに現在デプロイされている数と一致することを確認します。 これらの操作の詳細はに書かれています etcd、コントローラーマネージャーがAPIサーバーを介して変更を監視します。

変更が見られると、コントローラーは新しい情報を読み取り、目的の状態を満たす手順を実行します。 これには、アプリケーションのスケールアップまたはスケールダウン、エンドポイントの調整などが含まれます。

kube-scheduler

クラスター内の特定のノードに実際にワークロードを割り当てるプロセスは、スケジューラーです。 このサービスは、ワークロードの運用要件を読み込み、現在のインフラストラクチャ環境を分析し、受け入れ可能な1つまたは複数のノードに作業を配置します。

スケジューラーは、各ホストで使用可能な容量を追跡して、ワークロードが使用可能なリソースを超えてスケジュールされていないことを確認する責任があります。 スケジューラーは、各サーバー上の既存のワークロードにすでに割り当てられているリソースだけでなく、総容量も知っている必要があります。

cloud-controller-manager

Kubernetesはさまざまな環境にデプロイでき、さまざまなインフラストラクチャプロバイダーとやり取りして、クラスター内のリソースの状態を理解および管理できます。 Kubernetesは、接続可能なストレージやロードバランサーなどのリソースの一般的な表現を処理しますが、これらを不均一なクラウドプロバイダーによって提供される実際のリソースにマッピングする方法が必要です。

クラウドコントローラーマネージャーは、Kubernetesがプロバイダーとさまざまな機能、機能、APIを相互作用させながら、比較的一般的な構造を内部的に維持できるようにする接着剤として機能します。 これにより、Kubernetesは、クラウドプロバイダーから収集した情報に従って状態情報を更新し、システムで必要な変更に応じてクラウドリソースを調整し、クラスターに送信された作業要件を満たすために追加のクラウドサービスを作成して使用できます。

ノードサーバーコンポーネント

Kubernetesでは、コンテナを実行して作業を実行するサーバーはノードと呼ばれます。 ノードサーバーには、マスターコンポーネントとの通信、コンテナーネットワークの構成、およびノードサーバーに割り当てられた実際のワークロードの実行に必要ないくつかの要件があります。

コンテナランタイム

各ノードに必要な最初のコンポーネントは、コンテナーランタイムです。 通常、この要件は Docker をインストールして実行することで満たされますが、rktruncなどの代替手段も利用できます。

コンテナランタイムは、比較的分離されているが軽量のオペレーティング環境にカプセル化されたアプリケーションであるコンテナの起動と管理を担当します。 クラスタの各作業単位は、基本レベルで、展開する必要のある1つ以上のコンテナとして実装されます。 各ノードのコンテナランタイムは、クラスタに送信されたワークロードで定義されたコンテナを最終的に実行するコンポーネントです。

kubelet

クラスタグループとの各ノードの主な連絡先は、kubeletと呼ばれる小さなサービスです。 このサービスは、コントロールプレーンサービスとの間で情報を中継したり、 etcd 構成の詳細を読み取ったり、新しい値を書き込んだりするために保存します。

The kubelet サービスはマスターコンポーネントと通信して、クラスターに対して認証を行い、コマンドを受信して動作します。 作業は、ワークロードと動作パラメータを定義するマニフェストの形式で受信されます。 The kubelet 次に、プロセスはノードサーバー上の作業の状態を維持する責任を負います。 コンテナの実行時間を制御して、必要に応じてコンテナを起動または破棄します。

kube-proxy

個々のホストのサブネット化を管理し、他のコンポーネントでサービスを利用できるようにするために、kube-proxyと呼ばれる小さなプロキシサービスが各ノードサーバーで実行されます。 このプロセスは、リクエストを正しいコンテナに転送し、基本的な負荷分散を実行できます。通常、ネットワーク環境が予測可能でアクセス可能であることを確認しますが、適切な場合は分離されます。

Kubernetesオブジェクトとワークロード

コンテナはアプリケーションのデプロイに使用される基盤となるメカニズムですが、Kubernetesはコンテナインターフェース上で追加の抽象化レイヤーを使用して、スケーリング、復元力、ライフサイクル管理機能を提供します。 コンテナを直接管理する代わりに、ユーザーはKubernetesオブジェクトモデルによって提供されるさまざまなプリミティブで構成されるインスタンスを定義して操作します。 以下では、これらのワークロードを定義するために使用できるさまざまなタイプのオブジェクトについて説明します。

ポッド

ポッドは、Kubernetesが扱う最も基本的なユニットです。 コンテナ自体はホストに割り当てられていません。 代わりに、1つ以上の密結合コンテナがポッドと呼ばれるオブジェクトにカプセル化されます。

ポッドは通常、単一のアプリケーションとして制御する必要がある1つ以上のコンテナーを表します。 ポッドは、緊密に連携し、ライフサイクルを共有するコンテナで構成されており、常に同じノードでスケジュールする必要があります。 それらは完全に1つのユニットとして管理され、環境、ボリューム、およびIPスペースを共有します。 コンテナ化された実装にもかかわらず、一般に、ポッドを単一のモノリシックアプリケーションと見なして、クラスターがポッドのリソースとスケジューリングを管理する方法を最もよく概念化する必要があります。

通常、ポッドは、ワークロードの一般的な目的を満たすメインコンテナーと、オプションで密接に関連するタスクを容易にするいくつかのヘルパーコンテナーで構成されます。 これらは、独自のコンテナで実行および管理することでメリットが得られるプログラムですが、メインアプリケーションと緊密に連携しています。 たとえば、ポッドには、プライマリアプリケーションサーバーを実行する1つのコンテナと、外部リポジトリで変更が検出されたときにファイルを共有ファイルシステムにプルダウンするヘルパーコンテナが含まれる場合があります。 タスクにより適した他のより高いレベルのオブジェクトがあるため、ポッドレベルでは水平スケーリングは一般的に推奨されません。

一般に、ユーザーはポッドを自分で管理するべきではありません。ポッドは、アプリケーションで通常必要とされる機能の一部(高度なライフサイクル管理やスケーリングなど)を提供しないためです。 代わりに、ポッドまたはポッドテンプレートを基本コンポーネントとして使用するが、追加機能を実装する、より高いレベルのオブジェクトを操作することをお勧めします。

レプリケーションコントローラーとレプリケーションセット

多くの場合、Kubernetesを使用する場合、単一のポッドを使用するのではなく、同一の複製されたポッドのグループを管理します。 これらはポッドテンプレートから作成され、レプリケーションコントローラーおよびレプリケーションセットと呼ばれるコントローラーによって水平方向にスケーリングできます。

レプリケーションコントローラーは、ポッドテンプレートを定義し、実行中のコピーの数を増減することでポッドの同一のレプリカを水平方向にスケーリングするパラメーターを制御するオブジェクトです。 これは、Kubernetes内でネイティブに負荷を分散し、可用性を向上させる簡単な方法です。 ポッド定義によく似たテンプレートがレプリケーションコントローラー構成内に埋め込まれているため、レプリケーションコントローラーは必要に応じて新しいポッドを作成する方法を知っています。

レプリケーションコントローラーは、クラスターにデプロイされたポッドの数が、その構成内のポッドの数と一致することを確認する責任があります。 ポッドまたは基盤となるホストに障害が発生した場合、コントローラーはそれを補うために新しいポッドを起動します。 コントローラの構成内のレプリカの数が変更された場合、コントローラは、必要な数に一致するようにコンテナを起動または強制終了します。 レプリケーションコントローラーは、ローリング更新を実行して、ポッドのセットを1つずつ新しいバージョンにロールオーバーし、アプリケーションの可用性への影響を最小限に抑えることもできます。

レプリケーションセットは、レプリケーションコントローラーの設計を反復したものであり、コントローラーが管理対象のポッドを識別する方法に柔軟性があります。 レプリケーションセットは、レプリカ選択機能が優れているため、レプリケーションコントローラーに取って代わり始めていますが、ローリング更新を実行して、レプリケーションコントローラーのようにバックエンドを新しいバージョンに循環させることはできません。 代わりに、レプリケーションセットは、その機能を提供する追加の上位レベルのユニット内で使用することを目的としています。

ポッドと同様に、レプリケーションコントローラーとレプリケーションセットの両方が、直接操作するユニットになることはめったにありません。 ポッドの設計に基づいて水平方向のスケーリングと信頼性の保証を追加しますが、より複雑なオブジェクトに見られるきめ細かいライフサイクル管理機能の一部が欠けています。

展開

Deployments は、直接作成および管理する最も一般的なワークロードの1つです。 展開では、レプリケーションセットを構成要素として使用し、柔軟なライフサイクル管理機能を組み合わせて追加します。

レプリケーションセットを使用して構築されたデプロイメントは、レプリケーションコントローラーによって提供される機能を複製しているように見える場合がありますが、デプロイメントは、ローリング更新の実装に存在していた多くの問題点を解決します。 レプリケーションコントローラーを使用してアプリケーションを更新する場合、ユーザーは、現在のコントローラーを置き換える新しいレプリケーションコントローラーの計画を提出する必要があります。 レプリケーションコントローラーを使用する場合、履歴の追跡、更新中のネットワーク障害からの回復、不適切な変更のロールバックなどのタスクは困難であるか、ユーザーの責任として残されます。

デプロイメントは、複製されたポッドのライフサイクル管理を容易にするように設計された高レベルのオブジェクトです。 デプロイメントは構成を変更することで簡単に変更でき、Kubernetesはレプリカセットを調整し、異なるアプリケーションバージョン間の遷移を管理し、オプションでイベント履歴と元に戻す機能を自動的に維持します。 これらの機能により、デプロイは、最も頻繁に使用するKubernetesオブジェクトのタイプになる可能性があります。

ステートフルセット

ステートフルセットは、順序付けと一意性の保証を提供する特殊なポッドコントローラーです。 主に、これらは、展開の順序、永続データ、または安定したネットワーキングに関連する特別な要件がある場合に、よりきめ細かい制御を行うために使用されます。 たとえば、ステートフルセットは、データベースなどのデータ指向のアプリケーションに関連付けられていることが多く、新しいノードに再スケジュールされた場合でも同じボリュームにアクセスする必要があります。

ステートフルセットは、ポッドを別のノードに移動する必要がある場合でも存続する、ポッドごとに一意の番号ベースの名前を作成することにより、安定したネットワーク識別子を提供します。 同様に、再スケジュールが必要な場合は、永続ストレージボリュームをポッドで転送できます。 偶発的なデータ損失を防ぐために、ポッドが削除された後もボリュームは保持されます。

スケールを展開または調整する場合、ステートフルセットは、名前に含まれる番号付きの識別子に従って操作を実行します。 これにより、実行順序の予測可能性と制御が向上し、場合によっては便利になります。

デーモンセット

デーモンセットは、クラスター内の各ノード(または指定されている場合はサブセット)でポッドのコピーを実行する、もう1つの特殊な形式のポッドコントローラーです。 これは、メンテナンスの実行とノード自体のサービスの提供に役立つポッドを展開する場合に最もよく役立ちます。

たとえば、ログの収集と転送、メトリックの集約、およびノード自体の機能を向上させるサービスの実行は、デーモンセットの一般的な候補です。 デーモンセットは基本的なサービスを提供することが多く、フリート全体で必要になるため、他のコントローラーが特定のホストにポッドを割り当てることを妨げるポッドスケジューリングの制限を回避できます。 例として、その固有の責任のために、マスターサーバーは通常のポッドスケジューリングに使用できないように構成されていることがよくありますが、デーモンセットには、ポッドごとに制限をオーバーライドして、重要なサービスが実行されていることを確認する機能があります。

JobsとCronJobs

これまでに説明したワークロードはすべて、長期にわたるサービスのようなライフサイクルを想定しています。 Kubernetesは、 jobs と呼ばれるワークロードを使用して、実行中のコンテナーが作業を完了した後、しばらくすると正常に終了することが期待される、よりタスクベースのワークフローを提供します。 ジョブは、継続的なサービスを実行する代わりに、1回限りの処理またはバッチ処理を実行する必要がある場合に役立ちます。

ジョブに基づいて構築するのは、cronジョブです。 従来のように cron スケジュールに従ってスクリプトを実行するLinuxおよびUnixライクなシステム上のデーモンであるKubernetesのcronジョブは、スケジューリングコンポーネントを使用してジョブを実行するためのインターフェイスを提供します。 cronジョブを使用して、将来実行するジョブをスケジュールしたり、定期的に繰り返し実行したりすることができます。 Kubernetes cronジョブは、基本的に、単一のオペレーティングシステムではなく、クラスターをプラットフォームとして使用する、従来のcron動作の再実装です。

その他のKubernetesコンポーネント

クラスターで実行できるワークロード以外にも、Kubernetesは、アプリケーションの管理、ネットワーキングの制御、永続性の有効化に役立つ他の多くの抽象化を提供します。 ここでは、より一般的な例のいくつかについて説明します。

サービス

これまで、従来のUnixライクな意味で「サービス」という用語を使用してきました。これは、要求に応答できる、多くの場合ネットワークに接続された、長時間実行されるプロセスを意味します。 ただし、Kubernetesでは、サービスは、ポッドの基本的な内部ロードバランサーおよびアンバサダーとして機能するコンポーネントです。 サービスは、同じ機能を実行するポッドの論理コレクションをグループ化して、それらを単一のエンティティとして提示します。

これにより、特定のタイプのすべてのバックエンドコンテナを追跡してルーティングできるサービスを展開できます。 内部コンシューマーは、サービスによって提供される安定したエンドポイントについて知る必要があるだけです。 一方、サービスの抽象化により、必要に応じてバックエンドワークユニットをスケールアウトまたは交換できます。 サービスのIPアドレスは、ルーティング先のポッドへの変更に関係なく安定しています。 サービスを展開することで、発見しやすくなり、コンテナの設計を簡素化できます。

1つ以上のポッドへのアクセスを別のアプリケーションまたは外部コンシューマーに提供する必要があるときはいつでも、サービスを構成する必要があります。 たとえば、インターネットからアクセスできるWebサーバーを実行しているポッドのセットがある場合、サービスは必要な抽象化を提供します。 同様に、Webサーバーでデータを保存および取得する必要がある場合は、データベースポッドにアクセスできるように内部サービスを構成する必要があります。

デフォルトでは、サービスは内部でルーティング可能なIPアドレスを使用してのみ利用できますが、いくつかの戦略の1つを選択することにより、クラスターの外部で利用できるようにすることができます。 NodePort 構成は、各ノードの外部ネットワークインターフェイスで静的ポートを開くことによって機能します。 外部ポートへのトラフィックは、内部クラスターIPサービスを使用して適切なポッドに自動的にルーティングされます。

または、 LoadBalancer サービスタイプは、クラウドプロバイダーのKubernetesロードバランサー統合を使用してサービスにルーティングする外部ロードバランサーを作成します。 クラウドコントローラーマネージャーは、適切なリソースを作成し、内部サービスサービスアドレスを使用してそれを構成します。

ボリュームと永続ボリューム

多くのコンテナ化された環境では、データを確実に共有し、コンテナの再起動間でその可用性を保証することが課題です。 コンテナランタイムは、多くの場合、コンテナの存続期間を超えて存続するストレージをコンテナに接続するための何らかのメカニズムを提供しますが、実装には通常、柔軟性がありません。

これに対処するために、Kubernetesは独自の volume 抽象化を使用して、ポッド内のすべてのコンテナーでデータを共有し、ポッドが終了するまでデータを利用できるようにします。 これは、密結合のポッドが複雑な外部メカニズムなしでファイルを簡単に共有できることを意味します。 ポッド内のコンテナ障害は、共有ファイルへのアクセスに影響しません。 ポッドが終了すると、共有ボリュームが破棄されるため、真に永続的なデータには適していません。

永続ボリュームは、ポッドのライフサイクルに縛られない、より堅牢なストレージを抽象化するためのメカニズムです。 代わりに、管理者は、ユーザーが実行中のポッドに対して要求および要求できるクラスターのストレージリソースを構成できます。 ポッドが永続ボリュームで実行されると、ボリュームの再利用ポリシーによって、手動で削除するか、データとともにすぐに削除するまでボリュームを保持するかどうかが決定されます。 永続データを使用して、ノードベースの障害を防ぎ、ローカルで使用できるよりも多くのストレージを割り当てることができます。

ラベルと注釈

他の概念に関連しているが、他の概念の外にあるKubernetesの組織の抽象化はラベリングです。 Kubernetesのlabelは、Kubernetesオブジェクトにアタッチして、グループの一部としてマークすることができるセマンティックタグです。 これらは、管理またはルーティングのさまざまなインスタンスを対象とする場合に選択できます。 たとえば、コントローラベースの各オブジェクトは、ラベルを使用して、操作する必要のあるポッドを識別します。 サービスはラベルを使用して、リクエストのルーティング先となるバックエンドポッドを理解します。

ラベルは、単純なキーと値のペアとして与えられます。 各ユニットには複数のラベルを付けることができますが、各ユニットにはキーごとに1つのエントリしか含めることができません。 通常、「名前」キーは汎用識別子として使用されますが、開発段階、パブリックアクセシビリティ、アプリケーションバージョンなど、他の基準でオブジェクトをさらに分類することもできます。

注釈は、任意のキー値情報をオブジェクトに添付できる同様のメカニズムです。 ポッドを選択基準と照合するのに役立つセマンティック情報にはラベルを使用する必要がありますが、注釈はより自由形式であり、構造化されていないデータを含めることができます。 一般に、注釈は、選択の目的には役立たないオブジェクトに豊富なメタデータを追加する方法です。

結論

Kubernetesは、ユーザーが高度に抽象化されたプラットフォームでスケーラブルで可用性の高いコンテナ化されたワークロードを実行できるようにするエキサイティングなプロジェクトです。 Kubernetesのアーキテクチャと内部コンポーネントのセットは、最初は気が遠くなるように思えますが、そのパワー、柔軟性、堅牢な機能セットは、オープンソースの世界では比類のないものです。 基本的な構成要素がどのように組み合わされているかを理解することで、プラットフォームの機能を完全に活用してワークロードを大規模に実行および管理するシステムの設計を開始できます。