2.3. OpenShift Online 固有のガイドライン
以下は、OpenShift Online で使用するためのコンテナーイメージの作成時に適用されるガイドラインです。
権限およびボリュームビルド
Docker イメージは、DOCKERFILE
の VOLUME
ディレクティブを使用してビルドすることはできません。読み取り/書き込みファイルシステムを使用するイメージは、ローカルストレージの代わりに永続ボリュームまたは emptyDir
ボリュームを使用する必要があります。Dockerfile でボリュームを指定する代わりに、ローカルストレージのディレクトリーを指定し、Pod のデプロイ時に永続ボリュームまたは emptyDir
ボリュームをそのディレクトリーにマウントします。
Source-To-Image (S2I) 向けのイメージの有効化
開発者が提供した Ruby コードを実行するように設計された Ruby イメージなど、サードパーティー提供のアプリケーションコードを実行することが目的のイメージの場合には、イメージを Source-to-Image (S2I) ビルドツールと連携できるようにすることができます。S2I は、インプットとして、アプリケーションのソースコードを受け入れるイメージを簡単に記述でき、アセンブルされたアプリケーションをアウトプットとして実行する新規イメージを簡単に生成することができるフレームワークです。
たとえば、この Python イメージは S2I スクリプトを定義して、Python アプリケーションのさまざまなバージョンをビルドします。
イメージ用に S2I スクリプトを記述する方法については、「S2I 要件」のトピックを参照してください。
任意のユーザー ID のサポート
デフォルトで、OpenShift Online は、任意に割り当てられたユーザー ID を使用してコンテナーを実行します。こうすることで、コンテナーエンジンの脆弱性が原因でコンテナーから出ていくプロセスに対して追加のセキュリティーを設定でき、ホストノードでパーミッションのエスカレーションが可能になります。
イメージが任意ユーザーとしての実行をサポートできるように、イメージ内のプロセスで記述される可能性のあるディレクトリーやファイルは、root グループが所有し、このグループに対して読み取り/書き込みの権限を割り当てる必要があります。実行予定のファイルには、グループの実行権限も必要です。
以下を Dockerfile に追加すると、root グループのユーザーがビルドされたイメージでアクセスできるように、ディレクトリーおよびファイルのパーミッションが設定されます。
RUN chgrp -R 0 /some/directory && \ chmod -R g=u /some/directory
コンテナーユーザーは常に root グループのメンバーであるため、コンテナーユーザーはこれらのファイルに対する読み取り、書き込みが可能です。root グループには、(root ユーザーのように) 特別なパーミッションがないので、この設定ではセキュリティーに関する懸念点はありません。さらに、コンテナーで実行中のプロセスは、特権のあるユーザーとして実行されていないので、特権のあるポート (1024 未満のポート) をリッスンできません。
コンテナーのユーザー ID が動的に生成されるので、/etc/passwd に関連のあるエントリーがありません。これが原因で、ユーザー ID を検索する必要のあるアプリケーションで問題が発生する可能性があります。この問題に対応するには、イメージの起動スクリプトの一部として、コンテナーのユーザー ID を指定した passwd のファイルエントリーを動的に作成します。Dockerfile の内容は、以下のようになります。
RUN chmod g=u /etc/passwd ENTRYPOINT [ "uid_entrypoint" ] USER 1001
uid_entrypoint には、以下を含めてください。
if ! whoami &> /dev/null; then if [ -w /etc/passwd ]; then echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:${HOME}:/sbin/nologin" >> /etc/passwd fi fi
最後に、Dockerfile
の最後の USER 宣言では、ユーザー名ではなく、ユーザー ID (数値) を指定してください。こうすることで、OpenShift Online は、イメージが実行時に使用しようとしている認証を検証でき、root ユーザーでのイメージの実行を防ぐことができます。特権のあるユーザーがコンテナーを実行するとリスクが発生するためです。イメージが USER を指定しない場合、親イメージから USER を継承します。
イメージ内の通信でのサービスの使用
データの保存や取得のためにデータベースイメージにアクセスする必要のある Web フロントエンドイメージなど、別のイメージが提供するサービスとイメージが通信する場合には、イメージは OpenShift Online サービスを使用する必要があります。サービスは、コンテナーが停止、開始、または移動しても変更されない静的アクセスエンドポイントを提供します。さらに、サービスにより、要求が負荷分散されます。
共通ライブラリーの提供
サードパーティーが提供するアプリケーションコードの実行を目的とするイメージの場合は、プラットフォーム用として共通に使用されるライブラリーをイメージに含めるようにしてください。とくに、プラットフォームで使用する共通のデータベース用のデータベースドライバーを設定してください。たとえば、Java フレームワークイメージを作成する場合に、MySQL や PostgreSQL には JDBC ドライバーを設定します。このように設定することで、アプリケーションのアセンブリー時に共通の依存関係をダウンロードする必要がなくなり、アプリケーションイメージのビルドがスピードアップします。また、すべての依存関係の要件を満たすためのアプリケーション開発者の作業が簡素化されます。
設定での環境変数の使用
イメージのユーザーは、ダウンストリームイメージをイメージに基づいて作成しなくても、イメージの設定が行えるようにしてください。つまり、ランタイム設定は環境変数を使用して処理される必要があります。単純な設定の場合、実行中のプロセスは環境変数を直接使用できます。より複雑な設定や、これをサポートしないランタイムの場合、起動時に処理されるテンプレート設定ファイルを定義してランタイムを設定します。このプロセス時に、環境変数を使用して渡される値は設定ファイルで置き換えることも、この値を使用して、設定ファイルに指定するオプションを決定することもできます。
環境変数を使用して、コンテナーに証明書やキーなどのシークレットを渡すこともでき、これは推奨されています。環境変数を使用することで、シークレット値がイメージにコミットされたり、Docker レジストリーに漏洩されることはありません。
環境変数を指定することで、イメージの利用者は、イメージ上に新しいレイヤーを作成することなく、データベースの設定、パスワード、パフォーマンスチューニングなどの動作をカスタマイズできます。Pod の定義時に環境変数の値を定義するだけで、イメージの再ビルドなしに設定を変更できます。
非常に複雑なシナリオの場合、ランタイム時にコンテナーにマウントされるボリュームを使用して設定を指定することも可能です。ただし、この方法を使用する場合には、必要なボリュームや設定が存在しない場合に明確なエラーメッセージが起動時に表示されるように、イメージが設定されている必要があります。
このトピックは、サービスエンドポイントの情報を渡す環境変数としてデータソースなどの設定において、 イメージ間の通信でのサービスの使用についてのトピックと関連しています。これにより、アプリケーションは、アプリケーションイメージを変更せずに、OpenShift Online 環境に定義されているデータソースサービスを動的に使用できます。
さらに、コンテナーの cgroups 設定を確認して、調整を行う必要があります。これにより、イメージは利用可能なメモリー、CPU、他のリソースに合わせてチューニングが可能になります。たとえば、Java ベースのイメージは、制限を超えず、メモリー不足のエラーが表示されないように、cgroup の最大メモリーパラメーターを基にヒープをチューニングする必要があります。
Docker コンテナーの cgroup クォータを管理する方法については、以下の資料を参照してください。
- ブログ記事 - Resource management in Docker
- Docker ドキュメント - Runtime metrics
- ブログ記事 - Memory inside Linux containers
イメージメタデータの設定
イメージのメタデータを定義することで、OpenShift Online によるコンテナーイメージの使用が改善され、開発者が OpenShift Online でイメージを使用しやすくなります。たとえば、メタデータを追加して、イメージに関する役立つ情報を提供したり、必要とされる可能性のある他のイメージを提案したりできます。
サポートされるメタデータや、定義の方法に関する詳細は、「イメージのメタデータ」のトピックを参照してください。
クラスタリング
イメージの複数のインスタンスを実行するとはどういうことかを十分に理解しておく必要があります。最も単純な例では、サービスの負荷分散機能は、イメージのすべてのインスタンスにトラフィックをルーティングします。ただし、セッションの複製などで、リーダーの選択やフェイルオーバーの状態を実行するには、多くのフレームワークが情報を共有する必要があります。
OpenShift Online での実行時に、インスタンスでこのような通信を実現する方法を検討します。Pod 同士は直接通信できますが、Pod が起動、停止、移動するたびに IP アドレスが変更されます。そのため、クラスタリングスキームを動的にしておくことが重要です。
ロギング
すべてのロギングを標準出力に送信することが推奨されます。OpenShift Online はコンテナーから標準出力を収集し、表示が可能な中央ロギングサービスに送信します。ログコンテンツを分離する必要がある場合には、出力のプレフィックスに適切なキーワードを指定して、メッセージをフィルタリングできるようにしてください。
お使いのイメージがファイルにロギングをする場合には、手動で実行中のコンテナーに入り、ログファイルを取得または表示する必要があります。
Liveness および Readiness プローブ
イメージで使用可能な liveness および readiness プローブの例をまとめます。これらのプローブにより、処理の準備ができるまでトラフィックがコンテナーにルーティングされず、プロセスが正常でない状態になる場合にコンテナーが再起動されるので、ユーザーはイメージを安全にデプロイできます。
テンプレート
イメージと共にテンプレートサンプルを提供することを検討してください。テンプレートがあると、ユーザーは、正しく機能する設定を指定してイメージをすばやく簡単にデプロイ できるようになります。完全を期すため、テンプレートには、イメージに関連して記述した liveness および readiness プローブを含めるようにしてください。