Kubernetes のデプロイのしくみ

完了

ドローン追跡アプリには、複数のコンポーネントが含まれており、互いに別々にデプロイされます。 あなたの仕事は、クラスター上でこれらのコンポーネントのデプロイを構成することです。 ここでは、これらのコンポーネントをデプロイするために利用できるデプロイ オプションの一部を見ていきます。

Diagram of the high-level architecture that shows the drone-tracking solution components.

ポッドのデプロイ オプション

kubectl を使用する場合、Kubernetes クラスターへのポッドのデプロイを管理するには、いくつかのオプションがあります。 オプションは次のとおりです。

  • ポッド テンプレート
  • レプリケーション コントローラー
  • レプリカ セット
  • デプロイ

これら 4 つの Kubernetes オブジェクト型定義のいずれかを使用して、1 つまたは複数のポッドをデプロイできます。 これらのファイルは、YAML を使用して、デプロイされるポッドの目的の状態を記述します。

ポッド テンプレートとは

ポッド テンプレートを使用すると、デプロイするポッドの構成を定義できます。 このテンプレートには、コンテナー イメージの名前、イメージのフェッチにどのコンテナー レジストリを使用するかなどの情報が含まれています。 テンプレートには、使用するポートなどのランタイム構成情報も含まれます。 テンプレートは、Docker ファイルを作成する場合と同じ方法で YAML を使用して定義します。

テンプレートを使用してポッドを手動でデプロイできます。 ただし、手動でデプロイしたポッドは、障害が発生したり、削除されたり、または終了したりした後も再起動されません。 ポッドのライフサイクルを管理するには、上位レベルの Kubernetes オブジェクトを作成する必要があります。

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

レプリケーション コントローラーにより、ポッド テンプレートが使用され、実行する必要のあるポッドの指定数が定義されます。 このコントローラーにより、同じポッドの複数のインスタンスを実行でき、ポッドがクラスター内の 1 つ以上のノードで常に実行されることが保証されます。 障害が発生した、削除された、または終了した場合、コントローラーによって、実行中のポッドがこの方法で新しいポッドに置き換えられます。

たとえば、あなたがドローンを追跡するフロントエンドの Web サイトをデプロイし、ユーザーがこの Web サイトへのアクセスを開始するとします。 何らかの理由ですべてのポッドが失敗した場合、あなたが新しいポッドを起動しない限り、ユーザーはこの Web サイトを利用できません。 レプリケーション コントローラーを使用すると、Web サイトを常に利用可能にしておくことができます。

レプリカ セットとは

レプリカ セットは、レプリカをデプロイするための推奨される方法として、レプリケーション コントローラーの代わりに使用されます。 レプリカ セットにはレプリケーション コントローラーと同じ機能が含まれますが、セレクター値を含めるための追加の構成オプションがあります。

セレクターを使用すると、レプリカ セットにより、その下で実行されているすべてのポッドを識別できるようになります。 この機能を使用すると、セレクター値と同じ値のラベルが付けられてはいるが、レプリカ セットでは作成されていないポッドを管理できます。

デプロイとは

デプロイにより、レプリカ セットより 1 レベル上位の管理オブジェクトが作成され、クラスター内のポッドの更新をデプロイおよび管理できます。

ご自分のアプリの 5 つのインスタンスがクラスターにデプロイされているとします。 アプリのバージョン 1.0.0 が実行されているポッドが 5 つあります。

Diagram that shows five pods running on a node with the same pod version.

アプリを手動で更新することにした場合は、すべてのポッドを削除してから、アプリのバージョン 2.0.0 が実行される新しいポッドを起動します。 この戦略では、アプリのダウンタイムが発生します。

代わりに、アプリのバージョンが古いポッドを削除する前に、アプリのバージョンが新しいポッドを起動するローリング アップデートを実行する必要があります。 ローリング アップデートは、すべての古いポッドを一度に停止するのではなく、一度に 1 つのポッドを起動します。 デプロイでは、レプリカ セットについての情報を記述するセクションで構成されているレプリカの数が優先されます。 これは古いポッドを新しいポッドに置き換えるため、レプリカ セットで指定されているポッドの数を維持します。

Diagram that shows five pods, two pods set as version 1 and 3 pods set as version 2.

既定では、デプロイにより、ポッドを更新するためのローリング アップデート戦略が提供されます。 再作成戦略を使用することもできます。 この戦略では、新しいポッドを起動する前に、ポッドを終了させます。

また、デプロイではロールバック戦略も提供されます。これは、kubectl を使用して実行できます。

デプロイでは YAML ベースの定義ファイルが使用されており、デプロイの管理が容易になります。 デプロイではクラスターに任意の変更を適用できることに注意してください。 たとえば、新しいバージョンのアプリをデプロイしたり、ラベルを更新したり、ポッドの他のレプリカを実行したりできます。

kubectl には、kubectl run コマンドを使用してポッドをデプロイするときに、デプロイを自動的に作成するための便利な構文があります。 このコマンドにより、必要なレプリカ セットとポッドを使用してデプロイが作成されます。 ただし、そのコマンドでは定義ファイルは作成されません。 ベスト プラクティスは、デプロイ定義ファイルを使用してすべてのデプロイを管理し、バージョン コントロール システムを使用して変更を追跡することです。

デプロイに関する考慮事項

Kubernetes には、クラスターのネットワークとストレージの構成方法に関する特定の要件があります。 これらの 2 つの側面の構成方法は、クラスター ネットワークでのアプリの公開方法と、データの格納方法に関する決定に影響します。

たとえば、ドローン追跡アプリの各サービスには、ユーザー アクセス、プロセス間ネットワーク アクセス、データ ストレージに関する特定の要件があります。 ここで、Kubernetes クラスターのこれらの側面と、それらがアプリのデプロイにどのように影響するかを見てみることにしましょう。

Kubernetes ネットワーク

1 つのコントロール プレーンと 2 つのノードを含むクラスターがあるとします。 Kubernetes にノードを追加すると、内部プライベート ネットワーク範囲から、IP アドレスが各ノードに自動的に割り当てられます。 たとえば、ローカル ネットワーク範囲が 192.168.1.0/24 であるとします。

Diagram of nodes with assigned IP addresses in a cluster.

デプロイした各ポッドには、IP アドレスのプールから IP アドレスが割り当てられます。 たとえば、次の画像に示すように、構成で 10.32.0.0/12 のネットワーク範囲が使用されているとします。

Diagram of nodes and pods with assigned IP addresses in a cluster.

既定では、異なる IP アドレス範囲を使用してポッドとノードの相互通信を行うことはできません。

さらに複雑な問題については、ポッドが一時的なものであることを思い出してください。 ポッドの IP アドレスは一時的なものであり、新しく作成されたポッドに再接続するために使用することはできません。 この構成は、アプリがどのように内部コンポーネントとコミュニケーションを行うか、およびあなたとサービスがどのようにアプリと外部でやり取りするかに影響を与えます。

通信を簡単にするため、Kubernetes ではネットワークを次のような方法で構成することが想定されています。

  • ノード間でネットワーク アドレス変換 (NAT) を使用せずにポッドが相互に通信できる。
  • NAT を使用せずにノードからすべてのポッドと通信でき、また、ポッドからすべてのノードと通信できる。
  • ノード上のエージェントからすべてのノードおよびポッドと通信できる。

Kubernetes には、ネットワークを構成するためにインストールできる複数のネットワーク オプションが用意されています。 例として、Antrea、Cisco Application Centric Infrastructure (ACI)、Cilium、Flannel、Kubenet、VMware NSX-T、Weave Net があります。

クラウド プロバイダーによって独自のネットワーク ソリューションも提供されます。 たとえば、Azure Kubernetes Service (AKS) では、Azure Virtual Network Container Networking Interface (CNI)、Kubenet、Flannel、Cilium、Antrea がサポートされています。

Kubernetes サービス

Kubernetes サービスは、ポッド用に安定したネットワークを提供する Kubernetes オブジェクトです。 Kubernetes サービスを使用することにより、クラスターの内部と外部の両方で、アプリのノード、ポッド、ユーザーの間で通信できるようになります。

Kubernetes では、(ノードやポッドと同様に) サービスに対して作成時に IP アドレスが割り当てられます。 これらのアドレスは、サービス クラスターの IP 範囲 (例: 10.96.0.0/12) から割り当てられます。 サービスには、サービス名に基づく DNS 名と、IP ポートも割り当てられます。

ドローン追跡アプリの場合、ネットワーク通信は次のようになります。

  • クラスターの外部のユーザーは、Web サイトと RESTful API にアクセスできます。

  • メモリ内キャッシュ サービスとメッセージ キュー サービスは、それぞれフロントエンドと RESTful API からアクセスできますが、外部ユーザーによるアクセスはできません。

  • メッセージ キューに対して、データ処理サービスからのアクセスは必要ですが、外部ユーザーからのアクセスは必要ありません。

  • NoSQL データベースは、メモリ内キャッシュ サービスとデータ処理サービスからはアクセスできますが、外部ユーザーによるアクセスはできません。

これらのシナリオをサポートするには、3 種類のサービスを構成してアプリのコンポーネントを公開できます。

サービス 説明
ClusterIP サービスに割り当てられたアドレスです。これによって、そのサービスはクラスター内のサービスの集まりから利用できるようになります。 たとえば、アプリのフロントエンド コンポーネントとバックエンド コンポーネントの間の通信などです。
NodePort Kubernetes のコントロール プレーンによってサービスに割り当てられる、30000 から 32767 までのノード ポート。たとえば、clusters01 上の 192.169.1.11。 その後、公開するポッドのターゲット ポートを指定してサービスを構成します。 たとえば、フロントエンドの 1 つが実行されているポッドにポート 80 を構成します。 これで、ノード IP とポート アドレスを使用してフロントエンドにアクセスできるようになります。
LoadBalancer アプリを実行しているノード間、およびパブリック ネットワーク アクセスにポッドを公開しているノード間で、負荷を分散できるようにするロード バランサーです。 通常は、クラウド プロバイダーを使用するときにロード バランサーを構成します。 この場合、外部ロード バランサーからのトラフィックは、アプリを実行しているポッドに送られます。

ドローン追跡アプリで、LoadBalancer を使用することで追跡 Web サイトと RESTful API を公開し、ClusterIP を使用することでデータ処理サービスを公開することを決定できます。

ポッドをグループ化する方法

IP アドレスでポッドを管理することは現実的ではありません。 ポッドの IP アドレスは、ポッドがコントローラーで再作成されると変更されます。また、ポッドの実行数もさまざまです。

Diagram of a service with selector labels.

サービス オブジェクトでは、セレクター ラベルを使用することにより、クラスター内の特定のポッドをターゲットにして管理することができます。 セレクター ラベルは、ポッドの定義ファイルで定義されているポッド ラベルと一致するように、サービス定義で設定します。

たとえば、多数のポッドを実行しているとします。 これらのポッドの一部だけがフロントエンドにあり、フロントエンド ポッドだけを対象とする LoadBalancer サービスを設定する必要があります。 サービスの定義ファイルでセレクター値としてポッド ラベルを参照することにより、サービスを適用してこれらのポッドを公開できます。 サービスは、ラベルに一致するポッドだけをグループ化します。 ポッドが削除されて再作成された場合、新しいポッドは、一致するラベルを介してサービス グループに自動的に追加されます。

Kubernetes のストレージ

Kubernetes では、Docker を使用するときと同じストレージ ボリュームの概念が用いられます。 Docker ボリュームの有効期間は管理されないため、Docker ボリュームは Kubernetes ボリューム程は管理されていません。 Kubernetes ボリュームの有効期間は、ポッドの有効期間と一致する明示的な有効期間です。 この有効期間の一致は、ポッドで実行されるコンテナーよりボリュームの方が長く存在することを意味します。 ただし、ポッドが削除された場合は、ボリュームも削除されます。

Diagram of a service with selector labels again.

Kubernetes には、PersistentVolumes を使用して永続ストレージをプロビジョニングするためのオプションがあります。 また、PersistentVolumeClaims を使用することで、ポッドに対して特定のストレージを要求することもできます。

メッセージ キューやデータベースなどの永続ストレージを必要とするアプリ コンポーネントをデプロイする場合は、これら両方のオプションを考慮します。

クラウド統合に関する考慮事項

Kubernetes は、クラウドネイティブ アプリで使用するテクノロジ スタックを規定するものではありません。 Azure などのクラウド環境では、Kubernetes クラスターの外部にある複数のサービスを使用できます。

前に説明したとおり、Kubernetes では次のサービスが提供されていません。

  • ミドルウェア
  • データ処理フレームワーク
  • データベース
  • キャッシュ
  • クラスター ストレージ システム

このドローン追跡ソリューションでは、NoSQL データベース、メモリ内キャッシュ サービス、メッセージ キューというミドルウェア機能を提供する 3 つのサービスがあります。 NoSQL ソリューションとして MongoDB Atlas を選択し、メモリ内キャッシュを管理するために Redis を選択し、メッセージ キューのニーズに応じて RabbitMQ または Kafka を選択できます。

Azure などのクラウド環境を使用する場合、Kubernetes クラスターの外部のサービスを使用することをお勧めします。 この決定により、クラスターの構成と管理が簡素化されます。 たとえば、メモリ内キャッシュ サービスには Azure Cache for Redis、メッセージ キューには Azure Service Bus メッセージング、NoSQL データベースには Azure Cosmos DB を使用できます。