2.3. OpenShift Container Platform 固有のガイドライン
以下は、OpenShift Container Platform で使用するためのコンテナーイメージを作成時に適用されるガイドラインです。
Source-To-Image (S2I) 向けのイメージの有効化
開発者が提供した Ruby コードを実行するように設計された Ruby イメージなど、サードパーティー提供のアプリケーションコードを実行することが目的のイメージの場合には、イメージを Source-to-Image (S2I) ビルドツールと連携できるようにすることができます。S2I は、インプットとして、アプリケーションのソースコードを受け入れるイメージを簡単に記述でき、アセンブルされたアプリケーションをアウトプットとして実行する新規イメージを簡単に生成することができるフレームワークです。
たとえば、この Python イメージ は S2I スクリプトを定義して、Python アプリケーションのさまざまなバージョンをビルドします。
イメージ用に S2I スクリプトを記述する方法については、S2I 要件 のトピックを参照してください。
任意のユーザー ID のサポート
デフォルトでは OpenShift Container Platform は、任意に割り当てられたユーザー ID を使用してコンテナーを実行します。こうすることで、コンテナーエンジンの脆弱性が原因でコンテナーから出ていくプロセスに対して追加のセキュリティーを設定でき、ホストノードでパーミッションのエスカレーションが可能になります。
イメージが任意ユーザーとしての実行をサポートできるように、イメージ内のプロセスで記述される可能性のあるディレクトリーやファイルは、root グループが所有し、このグループに対して読み取り/書き込みの権限を割り当てる必要があります。実行予定のファイルには、グループの実行権限も必要です。
以下を Dockerfile に追加すると、root グループのユーザーがビルドされたイメージでアクセスできるように、ディレクトリーおよびファイルのパーミッションが設定されます。
RUN chgrp -R 0 /some/directory && \ chmod -R g+rwX /some/directory
コンテナーユーザーは常に root グループのメンバーであるため、コンテナーユーザーはこれらのファイルに対する読み取り、書き込みが可能です。
コンテナーの慎重に扱うべき分野のディレクトリーおよびファイルパーミッションを変更する場合には注意が必要です (通常のシステムの扱い方と同様です)。
/etc/passwd などの慎重に扱うべき分野に適用されると、意図しないユーザーによるこのようなファイルの変更が可能となり、コンテナーやホストにセキュリティー上のリスクが生じる可能性があります。CRI-O は、ランダムユーザー ID のコンテナーの /etc/passwd への挿入をサポートするため、そのパーミッションを変更する必要はありません。
さらに、コンテナーで実行中のプロセスは、特権のあるユーザーとして実行されていないので、特権のあるポート (1024 未満のポート) をリッスンできません。
コンテナーのユーザー ID が動的に生成されるので、/etc/passwd に関連のあるエントリーがありません。これが原因で、ユーザー ID を検索する必要のあるアプリケーションで問題が発生する可能性があります。この問題に対処する 1 つの方法として、nss wrapper を使用し、イメージの起動スクリプトの一部として、コンテナーのユーザー ID で passwd ファイルを動的に作成する方法があります。
export USER_ID=$(id -u) export GROUP_ID=$(id -g) envsubst < ${HOME}/passwd.template > /tmp/passwd export LD_PRELOAD=/usr/lib64/libnss_wrapper.so export NSS_WRAPPER_PASSWD=/tmp/passwd export NSS_WRAPPER_GROUP=/etc/group
passwd.template には以下が含まれます。
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin postgres:x:${USER_ID}:${GROUP_ID}:PostgreSQL Server:${HOME}:/bin/bash
さらに、これを機能させるには、nss_wrapper パッケージおよび gettext パッケージをイメージにインストールする必要があります。後者には envsubst
コマンドが含まれます。たとえば、yum ベースのイメージに対して、以下の行を Dockerfile に追加できます。
RUN yum -y install nss_wrapper gettext
最後に、Dockerfile
の最後の USER 宣言では、ユーザー名ではなく、ユーザー ID (数値) を指定してください。こうすることで、OpenShift Container Platform が、イメージが実行時に使用しようとしている認証を検証して、root でのイメージの実行を防ぐことができます。特権のあるユーザーがコンテナーを実行すると、セキュリティー上の欠陥が発生する 可能性があるためです。特権のあるユーザーがコンテナーを実行すると、セキュリティー上の欠陥が発生する可能性があるためです。 イメージで USER が指定されていない場合は、親イメージの USER が継承されます。
S2I イメージに、ユーザーを数値で指定した USER 宣言が含まれない場合には、デフォルトで、ビルドが失敗するようになっています。名前が指定されたユーザーや root (0) ユーザーを使用するイメージを OpenShift Container Platform でビルドできるようにするには、プロジェクトのビルダーサービスアカウント (system:serviceaccount:<your-project>:builder) を 特権付き SCC (security context constraint) に追加できます。または、すべてのイメージをどのユーザーでも実行できるようにできます。
イメージ内の通信でのサービスの使用
データの保存や取得のためにデータベースイメージにアクセスする必要のある Web フロントエンドイメージなど、別のイメージが提供するサービスとイメージが通信する場合には、イメージは OpenShift Container Platform サービス を使用する必要があります。サービスは、コンテナーが停止、開始、または移動しても変更されない静的アクセスエンドポイントを提供します。さらに、サービスにより、要求が負荷分散されます。
共通ライブラリーの提供
サードパーティーが提供するアプリケーションコードの実行を目的とするイメージの場合は、プラットフォーム用として共通に使用されるライブラリーをイメージに含めるようにしてください。とくに、プラットフォームで使用する共通のデータベース用のデータベースドライバーを設定してください。たとえば、Java フレームワークイメージを作成する場合に、MySQL や PostgreSQL には JDBC ドライバーを設定します。このように設定することで、アプリケーションのアセンブリー時に共通の依存関係をダウンロードする必要がなくなり、アプリケーションイメージのビルドがスピードアップします。また、すべての依存関係の要件を満たすためのアプリケーション開発者の作業が簡素化されます。
設定での環境変数の使用
イメージのユーザーは、ダウンストリームイメージをイメージに基づいて作成しなくても、イメージの設定が行えるようにしてください。つまり、ランタイム設定は環境変数を使用して処理される必要があります。単純な設定の場合、実行中のプロセスは環境変数を直接使用できます。より複雑な設定や、これをサポートしないランタイムの場合、起動時に処理されるテンプレート設定ファイルを定義してランタイムを設定します。このプロセス時に、環境変数を使用して渡される値は設定ファイルで置き換えることも、この値を使用して、設定ファイルに指定するオプションを決定することもできます。
環境変数を使用して、コンテナーに証明書やキーなどのシークレットを渡すこともでき、これは推奨されています。環境変数を使用することで、シークレット値がイメージにコミットされたり、コンテナーイメージレジストリーに漏洩されることはありません。
環境変数を指定することで、イメージの利用者は、イメージ上に新しいレイヤーを作成することなく、データベースの設定、パスワード、パフォーマンスチューニングなどの動作をカスタマイズできます。Pod の定義時に環境変数の値を定義するだけで、イメージの再ビルドなしに設定を変更できます。
非常に複雑なシナリオの場合、ランタイム時にコンテナーにマウントされるボリュームを使用して設定を指定することも可能です。ただし、この方法を使用する場合には、必要なボリュームや設定が存在しない場合に明確なエラーメッセージが起動時に表示されるように、イメージが設定されている必要があります。
このトピックは、サービスエンドポイントの情報を渡す環境変数としてデータソースなどの設定において、 イメージ間の通信でのサービスの使用 についてのトピックと関連しています。これにより、アプリケーションは、アプリケーションイメージを変更せずに、OpenShift Container Platform 環境に定義されているデータソースサービスを動的に使用できます。
さらに、コンテナーの cgroups 設定を確認して、調整を行う必要があります。これにより、イメージは利用可能なメモリー、CPU、他のリソースに合わせてチューニングが可能になります。たとえば、Java ベースのイメージは、制限を超えず、メモリー不足のエラーが表示されないように、cgroup の最大メモリーパラメーターを基にヒープをチューニングする必要があります。
コンテナーの cgroup クォータを管理する方法については、以下の資料を参照してください。
- ブログ記事 - Resource management in Docker
- Docker ドキュメント - Runtime metrics
- ブログ記事 - Memory inside Linux containers
イメージメタデータの設定
イメージのメタデータを定義することで、OpenShift Container Platform によるコンテナーイメージの使用が改善され、開発者が OpenShift Container Platform でイメージを使用しやすくなります。たとえば、メタデータを追加して、イメージに関する役立つ情報を提供したり、必要とされる可能性のある他のイメージを提案したりできます。
サポートされるメタデータや、定義の方法に関する詳細は、イメージのメタデータ のトピックを参照してください。
クラスターリング
イメージの複数のインスタンスを実行するとはどういうことかを十分に理解しておく必要があります。最も単純な例では、サービスの負荷分散機能は、イメージのすべてのインスタンスにトラフィックをルーティングします。ただし、セッションの複製などで、リーダーの選択やフェイルオーバーの状態を実行するには、多くのフレームワークが情報を共有する必要があります。
OpenShift Container Platform での実行時に、インスタンスでこのような通信を実現する方法を検討します。Pod 同士は直接通信できますが、Pod が起動、停止、移動するたびに IP アドレスが変更されます。そのため、クラスターリングスキームを動的にしておくことが重要です。
ロギング
すべてのロギングを標準出力に送信することが推奨されます。OpenShift Container Platform はコンテナーから標準出力を収集し、表示が可能な中央ロギングサービスに送信します。ログコンテンツを分離する必要がある場合には、出力の接頭辞に適切なキーワードを指定して、メッセージをフィルターリングできるようにしてください。
お使いのイメージがファイルにロギングをする場合には、手動で実行中のコンテナーに入り、ログファイルを取得または表示する必要があります。
Liveness および Readiness プローブ
イメージで使用可能な liveness および readiness プローブ の例をまとめます。これらのプローブにより、処理の準備ができるまでトラフィックがコンテナーにルーティングされず、プロセスが正常でない状態になる場合にコンテナーが再起動されるので、ユーザーはイメージを安全にデプロイできます。
テンプレート
イメージと共に テンプレート サンプルを提供することも検討してください。テンプレートがあると、ユーザーは、正しく機能する設定を指定してイメージをすばやく簡単にデプロイ できるようになります。完全を期すため、テンプレートには、イメージに関連して記述した liveness および readiness プローブ を含めるようにしてください。