Kubernetesの概要

前書き

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

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

Kubernetesとは何ですか?

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

Kubernetesユーザーは、アプリケーションの実行方法と、他のアプリケーションや外部の世界と対話する方法を定義できます。 サービスを拡大または縮小し、適切なローリング更新を実行し、アプリケーションの異なるバージョン間でトラフィックを切り替えて、機能をテストしたり、問題のある展開をロールバックしたりできます。 Kubernetesは、高度な柔軟性、パワー、信頼性を備えたアプリケーションを定義および管理できるインターフェイスと構成可能なプラットフォームプリミティブを提供します。

Kubernetesのアーキテクチャ

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

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

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

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

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

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

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

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

etcd

Kubernetesが機能するために必要な基本コンポーネントの1つは、グローバルに利用可能な構成ストアです。 CoreOSのチームによって開発されたhttps://coreos.com/etcd/docs/latest/[*etcd*プロジェクト]は、複数のノードにまたがるように構成できる軽量の分散キー値ストアです。

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

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

kube-apiserver

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

APIサーバーはRESTfulインターフェースを実装します。つまり、多くの異なるツールやライブラリが簡単に通信できます。 ローカルコンピューターからKubernetesクラスターと対話する既定の方法として、* kubectl *というクライアントを使用できます。

kube-controller-manager

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

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

キューブスケジューラ

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

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

クラウドコントローラーマネージャー

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

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

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

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

コンテナランタイム

各ノードに必要な最初のコンポーネントは、コンテナランタイムです。 通常、この要件はhttps://www.docker.com/[Docker]をインストールして実行することで満たされますが、https://coreos.com/rkt/ [rkt]やhttps://github.com/opencontainersなどの代替手段もあります。 / runc [runc]も使用できます。

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

キュベレット

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

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

kube-proxy

個々のホストのサブネット化を管理し、サービスを他のコンポーネントで利用できるようにするために、* kube-proxy *と呼ばれる小さなプロキシサービスが各ノードサーバーで実行されます。 このプロセスは、リクエストを正しいコンテナに転送し、プリミティブなロードバランシングを実行できます。一般的に、ネットワーク環境が予測可能でアクセス可能であることを確認しますが、必要に応じて隔離します。

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

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

Pods

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

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

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

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

複製コントローラーと複製セット

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

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

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

*レプリケーションセット*は、コントローラーが管理対象のポッドを識別する方法に柔軟性を持たせたレプリケーションコントローラー設計の反復です。 レプリケーションセットは、レプリカ選択機能が優れているため、レプリケーションコントローラーを置き換え始めていますが、ローリングアップデートを実行して、バックエンドをレプリケーションコントローラーのように新しいバージョンに切り替えることはできません。 代わりに、複製セットは、その機能を提供する追加のより高いレベルのユニットの内部で使用されることを意図しています。

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

展開

*展開*は、直接作成および管理する最も一般的なワークロードの1つです。 展開では、複製セットをビルディングブロックとして使用し、柔軟なライフサイクル管理機能をミックスに追加します。

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

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

ステートフルセット

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

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

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

デーモンセット

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

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

ジョブとCronジョブ

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

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

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

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

サービス内容

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

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

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

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

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

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

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

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

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

ラベルと注釈

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

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

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

結論

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