kubernetes「Replication Controller」

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

replication controllerとは?

replication contorollerは、指定された数のpodの”レプリカ”がどの時点でも動作した状態を保証する。もし多くなり過ぎた場合には、いくつかをkillする。少なくなり過ぎた場合には、追加起動する。ユーザーが直接podを作成した場合とは違って、replication controllerは、どのような理由であれ削除されたり終了されたpodをリプレースする。たとえばnodeの障害や、カーネルアップグレードのような中断をともなうnodeのメンテナンスなどの場合が当てはまる。この理由で、アプリケーションがpodを1つしか必要としない場合であってもreplication controllerの使用を推奨する。プロセスのスーパーバイザーのように、1つのnodeの個別のプロセスではなく複数のnodeを横断する複数のpodを監督する。replication controllerはローカルコンテナの再起動をnode上の何らかのエージェント(例:KubeletやDocker)に任せている。

life of a podで議論したとおり、 ReplicationControllerRestartPolicy = Always に設定したpodにのみ適している(注意: RestartPolicy を指定していない場合、デフォルト値は Always )。 ReplicationController は異なる再起動ポリシーのpodについてはインスタンス起動を拒否すべきである。 issue #503で議論したとおり、他のタイプのコントローラーをKubernetesに追加して他の種類のワークロードに将来対応することを期待している。たとえばbuild/testやバッチのようなワークロードなど。

replication controllerはみずから終了することは決してないが、serviceとして永続するものと位置づけられているわけでもない。serviceは複数のreplication controllerに制御されるpod群で構成され、たくさんのreplication controllerがserviceのライフタイムをつうじて作成されたり削除されたりするものと見込まれる(たとえばserviceを実行するpodのアップグレートを実行する場合など)。serviceそのものとクライアントの両方から見て、replication controllerがserviceのpod群を管理していることに気づかない状態のままであるべきだ。

replication controllerはどのように動作するのか?

podテンプレート

replication controllerはテンプレートからpodを新規作成する。今のところReplicationControllerオブジェクト内に記述されているが、固有のリソースに切り出す予定でいる。 #170

すべてのレプリカにいま求められる状態を指定するものではなく、podテンプレートはクッキー型のようなものだ。クッキーを一度切り出してしまえば、クッキーは抜き型とはもはや関係がない。量子もつれのようになっているわけではない。その後のテンプレート編集や新しいテンプレートに切り替えたとしても、すでに作成されているpod群には直接の影響はない。同様に、replication controllerが作成したpod群は直接アップデートされるかもしれない。これは、podに属するすべてのコンテナーにいま求められる状態を指定する方式のpod群とは計画的に対照的なものにしている。このアプローチは、以下で説明するようなユースケースでデモするとおり、システムの状態定義を劇的に単純化し、基本形の柔軟性を増している。

Replication Controllerによって作られたpodは、代替可能で意味的には同一のものという意図がある。設定は時がたつにつれ異なるものになっていくかもしれないが。これは複製されたステートレスなサーバーであれば明らかに当てはまるが、replication controllerは、マスター選出型やシャード、ワーカープール型のアプリケーションを維持する用途にも利用できる。これらのアプリケーションは、 etcdロックモジュールRabbitMQワークキューなどのように動的に処理を割り当てるメカニズムを利用すべきで、個別のpodの設定にワンタイムの静的なカスタム設定を用いることはアンチパターンと考えられていて避けるべきだ。自動でリソース(例:CPUやメモリー)を自動でバーティカルに拡張する場合のように、pod群に何らかのカスタム設定を実行するのであれば、他のオンライン制御プロセスで実行すべきで、repliction controllerそのものに設定すべきではない。

Label

replication controllerが監視するpod群の配備は labelセレクタで定義される。それはコントローラーと制御されるpod群の間に疎結合の関係を生み出すもので、より密結合で定義されるpodとは対照的だ。固定長配列のpod定義を用いて制御されるpod群のセットを表すことは意図的に避けている。なぜなら、そのアプローチではクライアントとシステムの両方にとって管理オペレーションの複雑さを増すことを経験しているからだ。

replication controllerは指定されたテンプレートから作られるpod群が、labelセレクタと一致するlabelを含んでいることを検証すべきだ。現状では検証機能はないのだが、replication controllerのlabelセレクタが重複するようなセットを対象に含まないことを確認することで、1つだけのreplication controllerが任意のpodを制御している状況を確保すべきだ。

replication controllerは自身のlabelを持っていて、一般的に対応するpod群にそのlabelを持ち込む挙動をとるが、こういったlabelはreplication controllerの動作に影響しないことに注意。

podは、labelを変更することでreplication controllerの対象セットから外れる場合がある。このテクニックはデバックやデータ修復の目的でサービスからpod群を除去するために使えるかもしれない。この方法で除去されたpod群は自動的にリプレースされる(同時にレプリカの数は変更していない前提の場合)。

同様に、replication controllerを取り除くことは作成済みのpod群には影響しない。制御されているpod群を削除するためには、replicasフィールドにまず0を指定しなくてはならない(クライアントツールのkubectlは stopという単一オペレーションを提供していて、repolication controllerと制御下のpod群を同時に削除できることに注意。ただし、現時点でAPIにはそのような操作はない)。

replication controllerの守備範囲

replication controllerは単純に希望のpodの数が、labelセレクタと一致していて機能していることを保証する。現状では、終了されたpod群だけは計算から除外されている。将来的には、readinessや他の情報などシステムから得られるものも考慮されるかもしれない。リプレースポリシーにより多くの制御を追加するかもしれない。イベントを送出することで、外部ツールが望むより洗練されたリプレースやスケールダウンポリシーを実装できるよう計画している。

replication controllerは恒久的にこの狭い守備範囲に限定される。この先も、 readinessや死活監視を実行することはない。自動スケーリングを実行するのではなく、replicasフィールドを変更するような方法で、外部の自動スケールツールから制御されることを意図している( #492の議論のとおり)。replication controllerにスケジュールポリシー(例: spreading)を追加することはない。また、制御下のpod群が現在指定されているテンプレートと一致していることを検証することもない。それは自動サイジングや他の自動化プロセスをさまたげるからである。終了時の完了確認や依存性の指定、構成拡張ほか、他の領域の各種機能も同様である。podのバルク生成のためのメカニズムを切り出すことさえ検討している( #170)。

replication controllerは組み合わせて使えるビルディンブブロックの基礎モジュールであることを意図している。将来的に、より上位のAPIやツールをこの上に築くことや、補完的な基礎モジュールをユーザーの利便性のために用意することを期待している。現在kubectlによってサポートされている”マクロ”操作(run, stop, scale, rolling-update)は、このコンセプト証明の事例になっている。たとえば、 Asgardのような、replication controllerや自動スケールツール、service、スケジュールポリシー、カナリアデプロイメントなどを管理するものを想定できる。

一般的な利用パターン

再スケジューリング

上述のとおり、1つのpodを動作させ続けたい場合、またはそれが1000podであっても、replication controllerは、node障害やpod終了(例:他の制御エージェントの操作による場合)などの際にも指定された数のpodが存在することを保証する。

スケーリング

replication controllerは、手動でも自動スケール制御エージェント経由でも、単にreplicasフィールドを更新するだけでレプリカ数の増減を簡単にスケールさせられる。

ローリングアップデート

replication controllerはpod群を1つひとつリプレースすることでserviceをローリングアップデートできるよう設計されている。

#1353で解説したとおり、1レプリカで新規のreplication controllerを作成してから、新コントローラーを+1、旧コントローラーを-1、それぞれ1つひとつスケールさせ、古いコントローラーが0レプリカに到達したのちに削除するアプローチを推奨している。これにより予期しない障害の影響を受けることなくpod群のセットを見通しよく更新できる。

理想的には、ローリングアップデートコントローラーはアプリケーションが利用可能になっていることを考慮に入れ、どの時点をとっても十分な数のpodが機能提供していることを保証すべきである。

2つのreplication controllerは、pod内のプライマリコンテナのイメージタグなど、少なくとも1つの識別可能なlabelを持っているpodを作成する必要があるだろう。なぜなら、ローリングアップデートの典型的な目的はイメージアップデートだからだ。

ローリングアップデートはクライアントツールの kubectlに実装されている。

複数のリリーストラック

ローリングアップデートの最中にアプリケーションの複数リリースが動作することにくわえて、複数のリリーストラックを持って、特定期間の間、あるいは継続的に、複数のリリースを動作させたることはよくある。トラックはlabelを用いて識別する。

たとえば、あるserviceは tier in (frontend), environment in (prod) によってすべてのpodを対象とするかもしれない。このtierを構成するのに10レプリカのpodを持つとしよう。しかし、このコンポーネントの新バージョンを’canary’(カナリアデプロイメント)したい。1つのreplication controllerを replicas に9個のバルクレプリカとlabelに tier=frontend, environment=prod, track=stable を指定し、もう一方のreplication controllerを replicas にcanary用に1を指定、labelに tier=frontend, environment=prod, track=canary を指定する構成をとれる。これでserviceはcanaryと非canaryのpod群を両方カバーする。しかし、個別に色々テストするreplication controllerを混ぜて、結果を監視するようなこともできる。

APIオブジェクト

replication controllerはkubernetes REST APIのトップレベルリソースである。APIオブジェクトの詳細は ReplicationController API objectで見つかる。

中馬崇尋
Chuma Takahiro