Kubernetesについて学ぶ 3

今日は Viewing Pods and Nodesを学ぶ。

モジュール2でDeploymentを作成すると、KubernetesはアプリケーションインスタンスをホストするPodを作成しました。
ポッドは、1つまたは複数のアプリケーションコンテナ(Dockerまたはrktなど)のグループ、
およびそれらのコンテナの共有リソースを表すKubernetesによる抽象化(Kubernetes Abstraction)です。これらのリソースは下記を含んでいます。

* 共有ストレージ(ボリュームとして)
* 一意のクラスタIPアドレスとしてのネットワーキング
* コンテナのイメージバージョンや使用する特定のポートなど、各コンテナを実行する方法に関する情報

Podは、アプリケーション固有の「論理ホスト」をモデル化し、
比較的緊密に結合された異なるアプリケーションコンテナを含むことができます。
たとえば、PodにはNode.jsアプリケーションのコンテナと、
Node.js Webサーバーによって公開されるデータを提供する別のコンテナが含まれている場合があります。
ポッド内のコンテナはIPアドレスとポートスペースを共有し、常に同じ場所に配置され、
同じスケジュールで共有され、同じノード上の共有コンテキストで実行されます。

ポッドはKubernetesプラットフォームのアトミックな単位です。
Kubernetes上のDeploymentを作成すると、そのコンテナ内にコンテナを持つポッドが作成されます(コンテナを直接作成するのではなく)。
各ポッドは、スケジューリングされているノードに接続され、(再起動ポリシーに従って)終了または削除されるまでそこにとどまります。
ノードに障害が発生した場合、クラスタ内の他の使用可能なノードで同じポッドがスケジュールされます。
  • ポッドの中に複数のコンテナがいる
  • ポッドの中のコンテナはIPアドレスとポート空間を共有する

のがポイント。 また、

  • デプロイはポッドの作成を意味する

とのこと。

ポッドは常にノード上で実行されます。
ノードはKubernetesのワーカーマシンであり、クラスタに応じて仮想マシンまたは物理マシンのいずれかになります。
各ノードはマスターによって管理されます。
ノードは複数のポッドを持つことができ、
Kubernetesマスターはクラスタ内のノード全体でポッドのスケジューリングを自動的に処理します。
マスターの自動スケジューリングでは、各ノードで使用可能なリソースが考慮されます。

すべてのKubernetesノードは、少なくとも以下を実行します。

* Kubernetes MasterとNode間の通信を担当するプロセスであるKubelet、マシン上で動作するポッドとコンテナを管理します。
* レジストリからコンテナイメージを取得し、コンテナを解凍し、アプリケーションを実行するコンテナランタイム(Docker、rktなど)。

コンテナが密接に結合されており、ディスクなどのリソースを共有する必要がある場合にのみ、単一のポッドにまとめてスケジュールする必要があります。
  • ノードとは、仮想マシン/物理マシンのこと
  • ノード内に複数のポッドが存在しうる
  • ノード上でKubelet(エージェント、実体はプロセス)が動く
  • 1ポッド1コンテナがベスト
モジュール2では、Kubectlコマンドラインインターフェイスを使用しました。
デプロイされたアプリケーションとその環境に関する情報を得るために、モジュール3で引き続き使用します。
最も一般的な操作は、次のkubectlコマンドで実行できます。

kubectl get - リソース一覧
kubectl describe  - リソースに関する詳細情報を表示する
kubectl logs  - ポッド内のコンテナからログを出力する
kubectl exec  - ポッド内のコンテナでコマンドを実行する

これらのコマンドを使用して、アプリケーションがいつ展開されたか、
それらの現在のステータス、実行されている場所、およびそれらの設定が何かを確認できます。

クラスタコンポーネントとコマンドラインについてもっと知りましたので、アプリケーションを調べてみましょう。

Using a Service to Expose Your App

Kubernetesポッドは死にます。
ポッドには実際にライフサイクルがあります。
ワーカーノードが消滅すると、Node上で動作するPodも失われます。
ReplicationControllerは、新しいPodを作成してアプリケーションを実行し続けることによって、
クラスタを動的に所望の状態に戻すことができます。
もう1つの例として、3つのレプリカを持つ画像処理バックエンドを考えてみましょう。
それらのレプリカは代替可能です。フロントエンドシステムはバックエンドレプリカを気にしてはいけません。
また、Podが失われて再作成されたとしても。つまり、Kubernetesクラスター内の各ポッドには、
同じノード上のポッドであっても固有のIPアドレスがあるため、アプリケーションが機能し続けるように、ポッド間の変更を自動的に調整する方法が必要です。

Kubernetesのサービスは、論理的なPodセットと、そのPodにアクセスするためのポリシーを定義する抽象です。
サービスによって、依存するポッド間の疎結合が可能になります。
サービスは、すべてのKubernetesオブジェクトと同様に、YAML(推奨)またはJSONを使用して定義されます。
サービスによってターゲットとされるポッドのセットは、
通常、LabelSelectorによって決定されます(なぜ、selecterをスペックに含めることなくサービスを望むべきかは以下を参照)。

各Podには一意のIPアドレスがありますが、
これらのIPはサービスなしでクラスタ外に公開されません。
サービスにより、アプリケーションはトラフィックを受信できます。
サービスは、ServiceSpecで型を指定することによって、さまざまな方法で公開できます。

* ClusterIP(デフォルト) - クラスタ内の内部IPにサービスを公開します。このタイプでは、サービスはクラスタ内からのみ到達可能になります。
* NodePort  -  NATを使用して、クラスタ内の選択された各ノードの同じポートにサービスを公開します。 <NodeIP>:<NodePort>を使用して、クラスタの外部からサービスにアクセスできるようにします。 ClusterIPのスーパーセット。
* LoadBalancer  - 現在のクラウドに外部ロードバランサを作成し(サポートされている場合)、固定された外部IPをサービスに割り当てます。 NodePortのスーパーセット。
* ExternalName  - 名前付きのCNAMEレコードを返すことで、任意の名前(仕様ではexternalNameで指定)を使用してサービスを公開します。プロキシは使用されません。このタイプにはv1.7以上のkube-dnが必要です。

さまざまなタイプのサービスの詳細については、「ソースIPの使用」チュートリアルを参照してください。 「アプリケーションをサービスと接続する」も参照してください。

さらに、仕様にセレクタを定義しないサービスに関するユースケースがいくつかあることに注意してください。
セレクタなしで作成されたサービスは、対応するエンドポイントオブジェクトも作成しません。
これにより、ユーザーはサービスを特定のエンドポイントに手動でマップできます。
セレクタが存在しない別の可能性は、厳密にtype:ExternalNameを使用していることです。

サービスという概念が出てきた。Windowsっぽい。

サービスは、一連のポッドにトラフィックをルーティングします。
サービスは、アプリケーションに影響を与えることなく、ポッドを死にさせ、Kubernetesで複製する抽象化です。
依存するポッド(アプリケーション内のフロントエンドおよびバックエンドコンポーネントなど)間の検出とルーティングは、Kubernetes Servicesによって処理されます。

サービスは、Kubernetesのオブジェクトに対する論理操作を可能にするグループ化プリミティブであるラベルとセレクタを使用して、一連のPodと一致します。
ラベルは、オブジェクトに関連付けられたキー/値のペアであり、任意の数の方法で使用できます。

* 開発、テスト、生産のためのオブジェクトの指定
* バージョンタグを埋め込む
* タグを使用してオブジェクトを分類する

いよいよ複雑になってきた。 たぶん、サービスはエンドポイント的な役割を果たしている。外部との接点みたいな。

Running Multiple Instances of Your App


以前のモジュールでは、デプロイメントを作成し、サービスを通じて公開しました。
デプロイメントは、アプリケーションを実行するために1つのポッドのみを作成しました。
トラフィックが増加すると、ユーザーの需要に対応するためにアプリケーションを拡張する必要があります。
デプロイメントをスケールアウトすると、新しいポッドが作成され、
使用可能なリソースを持つノードにスケジュールされます。
拡大縮小すると、ポッドの数が新しい希望の状態に減少します。
Kubernetesはまた、Podのオートスケーリングをサポートしますが、このチュートリアルの範囲外です。
ゼロへのスケーリングも可能で、指定されたDeploymentのすべてのポッドを終了します。

アプリケーションの複数のインスタンスを実行するには、
すべてのインスタンスにトラフィックを分散する方法が必要です。
サービスには、公開された展開のすべてのポッドにネットワークトラフィックを分散する統合ロードバランサがあります。
サービスは、エンドポイントを使用して実行中のポッドを継続的に監視し、トラフィックが使用可能なポッドにのみ送信されるようにします。

スケーリングは、Deployment内のレプリカの数を変更することによって実行されます。

Pod単位でスケールアウトし、ロードバランシングもしてくれるらしい。 ヘルスチェックもサポートしてくれる。 ホストマシン(仮想マシンも)自体を冗長化したときはどうするのかな。マスターがいい感じに見てくれるのだろうか。

Performing a Rolling Update

ユーザーはいつでもアプリケーションを利用できると期待しており、
開発者は新しいバージョンを1日に数回展開することが予想されます。
Kubernetesでは、これはローリングアップデートで行われます。
更新をローリングすると、Podsインスタンスを新しいインスタンスで段階的に更新することにより、
ダウンタイムゼロでデプロイメントのアップデートを実行できます。
新しいポッドは、利用可能なリソースを持つノードでスケジュールされます。

前のモジュールでは、複数のインスタンスを実行するようにアプリケーションを拡張しました。
これは、アプリケーションの可用性に影響を与えずに更新を実行するための要件です。
デフォルトでは、更新中に使用できないポッドの最大数と、作成できる新しいポッドの最大数は1です。
両方のオプションは、(ポッドの)数値またはパーセンテージのいずれかに設定できます。
Kubernetesでは、更新プログラムがバージョン管理され、展開更新プログラムは以前の(安定版)バージョンに戻すことができます。
アプリケーションのスケーリングと同様に、デプロイメントが公開されている場合、
サービスは更新中に利用可能なポッドにのみトラフィックをロードバランシングします。
使用可能なポッドは、アプリケーションのユーザーが使用できるインスタンスです。

ローリングアップデートでは、次の操作が可能です。

* ある環境から別の環境にアプリケーションをプロモートする(コンテナイメージの更新を介して)
* 以前のバージョンにロールバックする
* 停止時間ゼロのアプリケーションの継続的な統合と継続的な配信

デプロイメントが公開されている場合、サービスは更新中に利用可能なポッドにのみトラフィックをロードバランシングします。

kubernetesマジ頭いい。