kubernetes「Pods」

この文書は、kubernetesの Podsの和訳(参照した原文は 2015.6.17版)で、一部意訳や不正確な部分が含まれているかもしれません。kubernetesは Apache License v2.0で提供されています。

Kubernetesでは、個別のアプリケーションコンテナのかわりに、 pod がデプロイ可能な最小単位であり、作成・スケジュール・管理される。

pod とは何か?

pod は(クジラの小群やエンドウ豆のサヤのように)共通のコンテキスト下で動作する複数アプリケーションからなる一まとまりのグループを指している。そのコンテキストの中で、アプリケーションを個別のcgroupに分離することも可能だ。podはコンテナ環境で、あるアプリケーション専用の「論理ホスト」をモデル化している。1つまたは複数のアプリケーションを内蔵し、比較的、密結合になっている。密結合をコンテナ以前の環境で考えると、同一の物理/論理ホストで実行されていたようなアプリケーション群といえる。

podのコンテキストは、以下のようにいくつかのLinuxのネームスペースの組み合わせとして定義できる。

  • PIDネームスペース (pod内のアプリケーション群からはお互いのプロセスが見える)
  • ネットワーク・ネームスペース (pod内のアプリケーション群は同一のIPとポートの空間にアクセスする)
  • IPCネームスペース (pod内のアプリケーション群は、SystemV IPCまたはPOSIXメッセージキューを使って相互通信できる)
  • UTSネームスペース (pod内のアプリケーション群はホスト名を共有する)

pod内のアプリケーション群は共有ボリュームにもアクセスできる。共有ボリュームはpodレベルで定義され、個別アプリケーションのファイルシステムの中で利用できる。それに加えて、podはトップレベルのcgroup隔離を定義することで、構成要素のまとまりとなるいくつかのアプリケーション単位で切り分けるための外壁のような境界を設定することもできる。

Docker構成の観点でいえば、1つのpodは共有 ボリュームを持つDockerコンテナ群を1つにまとめたグループからなる。PIDネームスペース共有はDockerではまだ実装されていない。

個別のアプリケーションコンテナ群と同じように、podもずっと使われるものというより比較的短期的なものと位置づけられている。 life of a podで議論されているとおり、podはノードに対して事前定義され、停止(リスタートポリシーにもよる)または削除されるまで存在している。ノードが死んだ場合、そのノードでスケジュールされていたpod群は削除される。特定目的のpod群は新たなノードに再割り当てされることは決してない。その代わりに、必ずリプレースされる(詳細は、 replication controller参照)。(将来的には、より高レベルのAPIがpodマイグレーションをサポートするかもしれない)

podを使う理由

リソース共有と通信

podは構成要素間のデータ共有と通信を簡単に行えるようにしている。

pod内のアプリケーション群はすべて同一のネットワークネームスペース/IP・ポート空間を利用し、localhostを活用して相互に見える状態になっていて通信できる。各podはフラットな共有ネットワークネームスペース内でIPアドレスを持ち、そのネットワークネームスペースではネットワーク外の他の物理コンピュータやコンテナと完全に通信できる。pod内では、ホスト名はアプリケーションコンテナ用のpod名がセットされている。 詳細はnetworking参照.

pod内で動作するアプリケーションコンテナの定義にくわえて、podには一群の共有ストレージボリュームも事前に定めておく。ボリュームはデータをコンテナが再起動しても残るようにし、pod内のアプリケーション間で共有できるようにする。

管理

podは、低レベルのコンテナインターフェースの直接操作と比べて、より高レベルの抽象化機能を提供することで、アプリケーションのデプロイと管理を簡素化している。podはデプロイやスケールアウト、レプリケーションを行うための単位として機能する。セット化(同時配備)や、fate sharing(訳注:1要素にエラーが起こると、アトミックに他要素もエラーにする)、レプリケーションの整合性確保、リソース共有、依存性管理などは自動的に制御される。

podの用途

podは垂直統合型のアプリケーションスタックをホストするためにも使えるが、これを使う主な理由は、1セットとして配備・管理したいヘルパープログラムのサポートにあり、たとえば以下のようなものがある。

  • コンテキスト管理システム、ファイル/データローダー、ローカルキャッシュ・マネージャーなど
  • ログとチェックポイントのバックアップ、圧縮、ローテーション、スナップショットなど
  • データ変更の監視、ログ追跡、ロギング・監視アダプター、イベント通知機能など
  • プロキシー、ブリッジ、アダプター
  • 制御ツール、管理ツール、設定ツール、アップデートツール

多くの場合、個別のpod群は単一アプリケーションの複数インスタンスを実行することは意図していない。

代替策の検証

なぜ、単に複数のプログラムを1つの(Docker)コンテナで動作させないのか?

  1. 透明性。コンテナをインフラから見えるpod内に作成することでインフラがそれらのコンテナにプロセス管理やリソース監視といったサービスを提供できるようになる。これによりユーザーはいくつもの利点を簡単に利用できる。
  2. ソフトウェア依存性の解体。各コンテナは別々に再構築しデプロイできる。kubernetesはいずれ個別コンテナのライブアップデートすらサポートするかもしれない。
  3. 使いやすさ。ユーザーは独自のプロセス管理ツールを実行したり、シグナルや終了コードの伝達などを気にする必要がなくなる。
  4. 効率性。インフラが分担する責任範囲が広がることで、コンテナをより軽量化できる。

なぜaffinityにもとづくコンテナのセット配備を行わないのか?

そのアプローチでは(訳注:コンテナを)ひとまとめにはできるものの、リソース共有やIPC、保証されたfate sharing、管理の簡素化といったpodの利点の多くを提供できない。

podの耐久性(やそれが欠けていることについて)

podはずっと使う petsとして取り扱うことを意図していない。スケジューリング障害やノード障害、またそのほかリソースの欠陥やノードのメンテナンスなどで追い出された場合、存続し続ける挙動はとらない。

一般的にユーザーがpod群を直接作成しなくてはならない状況にはならない。たとえ単体で起動する場合であっても、つねにコントローラー(たとえば replication controller)を使うべきだ。コントローラーはクラスタ単位で自己修復機能だけでなくレプリケーションやセットアップの管理を提供する。

クラスタ・スケジューリング・システムでは一連のAPI群をユーザーが触れる主なプリミティブとして使うことは比較的よくある。そのような例としては、 Borg, Marathon, Aurora, Tupperwareがある。

podは、以下のようなものを簡単に利用できるプリミティブとして提供されている。

  • スケジューラーやコントローラーのプラグイン拡張性
  • コントローラーAPI経由の”中継”を省いて、podレベルの操作をサポート
  • ブートストラップ時などを想定して、podのライフタイムをコントローラのライフタイムから切り離す
  • コントローラーとサービスを切り離して、末端のコントローラーがpod群の監視だけを受け持つ
  • kubeletレベルの機能とクラスターレベルの機能のクリーンな構成。kubeletを実質的に”podコントローラー”とする。
  • ハイアベイラビリティ用途のアプリケーション。pod群は、停止またはとくに削除に先立ってリプレースすることが期待されている。たとえば計画的廃棄やイメージ先行取得、podのライブマイグレーション #3949

現状のpetsに関するベストプラクティスは’replicas’を’1’にして適切なサービスに設定するreplication contorollerを作成すること。もし扱いにくいことが分かったら、 issue #260にコメントして頂きたい。

中馬崇尋
Chuma Takahiro