[Docker] The Microcontainer Manifesto and the Right Tool for the Job

原文はこちら。
https://blogs.oracle.com/developers/the-microcontainer-manifesto

コンテナの人気が、ここ数年で劇的に高まっています。コンテナはパッケージマネージャと構成管理の両方を置き換えるために使用されてきました。コンテナの標準的なビルドプロセスは開発者にとっては理想的ですが、残念ながら、結果として得られるコンテナイメージにより、オペレータの仕事がより困難になっています。

Related Content

Oraccleではクラウドサービスの構築時に、コンテナの恩恵を受ける可能性のあるいくつかのサービスを特定しましたが、コンテナの安定性とセキュリティを確保する必要があります。本番利用でのコンテナ利用に慣れるため、コンテナの構築プロセスの変更が必要でした。構築プロセスの問題を分析した後、環境の安定性とセキュリティを劇的に改善したコンテナの構築および実行方法を開発しました。2年以上前にこのプロセスを開始して以来、コンテナの安定性とセキュリティは劇的に向上しました。

Problems Resulting from Docker Build

問題の多くは、Linux全体をコンテナイメージに入れるという作業から生じます。具体的には以下の通りです。

1. Large Images

長きにわたり、イメージ構築の標準的な方法は、 `FROM debian / jesse`で始まり、その結果、大きなサイズのイメージをダウンロードすることになりました。これは管理性のためだけにレイヤを必要としていました。 これは、alpine linuxへの切り替えによっていくらか改善されましたが、すべてのソフトウェアがalpine linux上に構築するのは簡単ではありません。 今日でも、最も人気のあるイメージの多くは1G以上のサイズです。

2. Privilege Escalation

Linuxのユーザー空間全体をアプリケーションデプロイメントアーティファクトにするという習慣は、アプリケーションのセキュリティ侵害は、特権昇格のための他の潜在的な攻撃手段を与えることを意味します。コンテナ内にアプリケーション以外のものを置かないことでよりセキュアになります。

3. Vulnerability Management

コンテナの最大のセキュリティ問題の1つは期限切れの依存関係です。コンテナはイミュータブル(不変)であって、パッケージマネージャを介して脆弱なソフトウェアを更新するソリューションはありません。つまり、ビルド時に実行する必要があります。標準ビルドプロセスでは、コンテナ内のどのファイルが実際に使用されているかが不明ゆえに、コンテナのアップデートが必要か否かを判断することが難しくなります。つまり、「アプリケーションがコンテナ内の脆弱なバージョンのOpen SSLを使用しているのか、それとも単に標準インストールの一部として含まれていたのか」が不明なのです。
これらのビルドの問題の多くは、コンテナシステムをリードすることによって既に解決済みです。マルチステージビルドや--squashオプションを追加すると、コンテナを操作する他の方法が提供されますが、今回さらに一歩すすめました。その内容についてコミュニティからどのようがあるかを知りたいと思っています。

Other Operational Changes

ビルドの問題に加え、オペレーション上の変更を実施して悩みを最小限にしました。これらはコンテナシステムやその機能の悪い部分というわけではありませんが、以下の点で成功しました。

1. No Layers

コンテナを使って数年後、Layerが運用上問題のある仕様であると判断しました。 開発時にあたっては、Layerは素晴らしい仕様です。ビルドプロセスの最後のいくつかのステップをキャッシュし、毎回イメージ全体をダウンロードしなくても新しいバージョンのコードを実行できるという点で素晴らしいものです。問題は、デプロイメント・イメージの複数のLayerが不必要な複雑さを意味する点です。最近追加されたdocker buildコマンドに--squashオプションが追加されたことで、他の人が同じことを発見したことを示しています。

2. User Namespaces

ユーザー名前空間は素晴らしいセキュリティ機能です。誰かが名前空間の分離を破って出た場合、ホストに対する権限のないユーザーに割り当てられます。一般に、ファイルシステムのユーザーの所有権が適切にマッピングされないため、ユーザーの名前空間を有効にすることは困難です。Dockerはしばらくこの件について取り組んできました。彼らは最近、すべてのコンテナに対して単一のユーザー名前空間を共有する機能を追加しましたが、設定変更が必要で、しかもその設定変更はほとんど利用されることはありません。各コンテナが独自のユーザー名前空間を持つことが理想的ですが、残念なことに、これには読み込み専用のイメージまたはファイルシステムIDのマッピングのためのカーネルサポートが必要です。

3. No Overlayfs

OverlayFS(およびその前身のUnionFS)は、本番環境での数多くの問題の原因となっています。同じイメージから多くのコンテナを起動している場合は、ソースイメージの各コンテナディレクトリへのコピーは膨大な領域を必要とするため、オーバーレイの目的は理にかなっています。私たちは将来的にOverlayFSを使いたいと思っていますが、これまで避けていた運用上の問題にぶつかりました。さらに、ファイルシステムIDをマップできないということは、一意のユーザー名前空間には役立たないことを意味します。

4. No Image Repository

イメージのダウンロードは、多くの問題の原因となっています。 ネットワークの問題、不適切なイメージ、Layerの破損で悩まされてきました。私たちは、帯域外でノードに必要なイメージをデプロイするだけで、より多くの運用上の成功を収めました。これにより、セキュリティ上の脆弱性が存在する場合に、すべてのノードが最新バージョンのイメージを持つようにすることもできます。
これらの機能を有効にするには、デプロイメント・アーティファクトを、手作業でデプロイするのに十分な小さい読み取り専用コンテナに縮小します。ファイルシステムは読み取り専用なので、ユーザーの名前空間を有効にしてレイヤーやオーバーレイを避けることができます。

The Solution: Microcontainers

本番環境でコンテナを使っている際に目の当たりにしたこうした問題を解決するため、microcotainerと呼ぶ新しいコンセプトを作成しました。注意いただきたいのは、これは新しいコンテナ形式ではなく、単によりよいセキュリティや安定性を可能にする、特定のコンテナ構築方法です。具体的にmicrocontainerとは
  • 単一の実行可能ファイルとその依存関係のみが含まれています(つまりShellとinitプロセスがありません)
  • 読み取り専用のルートファイルシステムで実行されます(書き込みはボリュームマウントによって分離されて処理されます)
  • ユーザーとグループのファイルシステムの所有権はありません(すべてが単一のユーザーによって所有され、読み取り可能です)
  • ファイルシステムのタイムスタンプや機能はありません
  • 再現可能に構築することができ、毎回同じイメージを生成します
これらの原則に加えて、microcontainerを実際に簡単に実践できるようにするいくつかのファイルロケーション規約(file location conventions)を採用しています。ソフトウェアパッケージは、さまざまな場所に構成ファイルをインストールし、他の場所にファイルを書き込みます。すべての一時ファイル(pidファイルのような)を/runディレクトリに入れ、すべての永続的な書き込み(ログファイルとデータファイル)を/writeディレクトリに入れます。コンテナごとに変更する必要のある設定ファイルを/readディレクトリに入れます。なお、設定ファイルはボリュームマウントかkubernetes configmapで変更できます。
これらの原則と規約を実装することで、運用上の頭痛につながる主要なセキュリティと安定性の問題のいくつかを解決することができます。

Building a Microcontainer

静的にリンクされたGoバイナリを構築し、ベースとしてスクラッチ(開発)を使用している場合は、すでにmicrocontainerを構築している可能性があります。他のソフトウェアでは、マイクロコンテナを構築するのが難しい場合があります。そのため、私たちはmicrocontainerを構築するために利用するsmithをオープンソース化しました。このツールを使って、yumリポジトリと(オプションで)rpmファイルからmicrocontainerを構築できます。
さらに、既存のDockerコンテナを「microize(訳注:microsizeのtypoだと思われます)」するために使用できるので、開発中はコンテナ構築にあたって開発者にとって便利なDockerのツールを使用し、実稼働環境に合わせてmicrocontainerに変換できます。smithは標準のoci形式でイメージを構築しますが、Dockerリポジトリからイメージをアップロード/ダウンロードすることもできます。

Practical Considerations

様々な方法でconfigファイルを/readに入れたり、出力ファイルを/writeに入れたりすることができます。コマンドラインパラメータで設定することもできますが、簡単な解決策の1つは、予想される場所を適切なディレクトリにシンボリックリンクを貼ることです。たとえば、/var/log/appnameを/write/logにシンボリックリンクを貼ることができます。
smithは実行可能ファイルのリンクされた依存関係を検出できますが、dlopenで開いたライブラリを自動的に拾い上げませんし、構成ファイルやデータファイルを自動的に取得しません。実際には、他のファイルをどのように含める必要があるかを把握するのは概してかなり簡単です。既存のアプリケーションをmicrocontainerにパッケージ化するのに、通常は1時間以上かかりません。最終的には、イメージがより安全で、他の技法を使って作成されたものよりも10倍も小さくなります。
多くのソフトウェアパッケージは、適切に機能するために基本的なユーティリティに依存しています。他のすべてのユーティリティ(bash、grep、awkなど)をマイクロコンテナに入れないことがベストですが、実行しようとしている実行可能ファイルが、実際には実際のアプリケーションを実行する前に環境設定を行うシェルスクリプトであることがあります。場合によっては、これらの依存関係を取り除くために必要な労力が大きすぎるため、これらのユーティリティのいくつかをコンテナに含めざるを得ないことがあります。一般に、すべてのルールは破られる可能性があります。実用的であることは常に良い考えです。コンテナに含めるすべてのものに正当な理由があることを確認してください。維持する必要があるものになるからです。

Running a Microcontainer

一意のユーザー名前空間でコンテナを実行するには、runcのようなものを使って手動で設定する必要がありますが、Dockerを直接使用して他のメリットも享受できます。Dockerはociイメージをインポートできないので、smithで構築されたmicrocontainerイメージをDocker HubのようなDockerリポジトリにプッシュしてから実行する必要があります。
microcontainerの利点をすべて享受するには、コンテナを読み取り専用モードで実行します。
docker run -ti --read-only --tmpfs /run -v /my/write/directory:/write my-microcontainer

Operations

microcontainerは、システムのセキュリティを向上させる優れた方法です。 smithを使ってビルドしている場合は、アプリケーション自体が変更された場合にのみコンテナのIDが変わります。つまり、自動ビルドを構成してコンテナの再デプロイの必要性を警告することができます。しかし、docker execコマンドを使ってアクセスできるコンテナ内にツールがないため、デバッグが難しいという欠点もあります。このため、デバッグに役立つcrashcartという別のツールもリリースしました。
CrashCart: sideload binaries into a running container
https://github.com/oracle/crashcart
Hardcore Container Debugging
https://blogs.oracle.com/developers/hardcore-container-debugging

0 件のコメント:

コメントを投稿