コンテナー: Docker、Windows、および動向

最近では、コンテナーについて話すことなしに、クラウド コンピューティングの議論をすることはできません。銀行や金融サービス会社からECサイトまで、すべてのビジネスにわたる組織は、コンテナーとは何か、クラウドにおけるアプリケーションにとってコンテナーは何を意味するか、コンテナー固有の開発/IT運用シナリオでどのようにコンテナーを最大限に利用するかについて、理解したいと考えています。

皆さんがよりシームレスにクラウド アプリケーションを構築、テスト、デプロイ、管理するために、この重要なクラウド コンピューティング開発を最大限に活用する方法を理解するのを助けるため、コンテナーとは何か、コンテナーがどのように動作するかという基本から、現在、コンテナーが最も幅広く使われているシナリオ、「コンテナー化」をサポートする現れつつある動向まで、私の観点を共有しようと思います。

コンテナーの概要

抽象的な言葉では、コンピューティングのすべては、1+1のような単純な数値計算であれ、Exchangeのような複数のマシンにわたる複雑なアプリケーションであれ、タスクを実行するために、プロセッサー、メモリ、ディスク、ネットワークといった一連の「物理」リソース上で、何らかの「機能」を実行することを基にしています。時とともに、物理リソースがますます強力になったので、アプリケーションは、しばしば物理マシンが提供するリソースのわずかですら利用しません。そのため、基になる物理ハードウェアをシミュレーションするために、「仮想」リソースが作り出されました。これによって複数のアプリケーションを同時に実行できるようになり、それぞれのアプリケーションが同じ物理マシンの物理リソースの一部を利用します。

我々は通常、このシミュレーション テクニックを仮想化と呼んでいます。多くの人々は仮想化と聞くと即座に仮想マシンのことを考えますが、これは仮想化の1つの実装にすぎません。すべての汎用OSが実装しているメカニズムである仮想メモリは、アプリケーションに、コンピューターのメモリがそのアプリケーション専用であるという幻想を与え、コンピューターで利用可能なRAMよりずっと多いRAMにアクセスするエクスペリエンスを与えることもできます。

コンテナーは、OS仮想化とも呼ばれる、別の種類の仮想化です。現在のLinux上のコンテナーは、アプリケーションに、完全に分離された独立したOSという認識を与えます。実行中のコンテナーにとって、ローカル ディスクはOSファイルの初期コピーのように見え、メモリは新しくブートしたOSのファイルとデータを保持しているだけのように見え、実行されている唯一のものはOSです。これを実現するために、コンテナーを作成する「ホスト」マシンが何か賢いことを行っています。

最初のテクニックは、名前空間の分離です。名前空間には、ファイル、ネットワーク ポート、実行中のプロセスの一覧といった、アプリケーションが対話できるすべてのリソースが含まれています。名前空間の分離によって、ホストは、各コンテナーに、そのコンテナーが見るべきリソースだけを含んでいる仮想化された名前空間を与えます。この制限表示によって、コンテナーは、その権限に関係なく、単に仮想化された名前空間に含まれていないファイルを見られないので、それらのファイルにアクセスできません。また、コンテナーは、そのコンテナーの一部でないアプリケーションを一覧したり、それらと対話したりするすることもできません。これによって、コンテナーはだまされて、システム上に数十、数百のアプリケーションがあっても、そのコンテナーがシステム上で動作している唯一のアプリケーションであると信じます。

効率性のため、OSファイル、ディレクトリ、実行中のサービスの多くはコンテナー間で共有され、各コンテナーの名前空間に投影されます。たとえば、既存ファイルを修正したりファイルを新規作成したりすることによって、アプリケーションがそのコンテナーを変更した時にだけ、コンテナーは、基になるホストOSとは異なるコピーを取得します。しかし、Dockerの「コピー オン ライト」最適化を使い、コピーを取得するのは変更された部分だけになります。この共有が、単一のホスト上への複数のコンテナーのデプロイを極めて効率の高いものにしています。

第二に、ホストは、コンテナーがそのホストのどれだけのリソースを使えるかを制御します。CPU、RAM、ネットワーク帯域幅といったリソースのガバナンスは、コンテナーが期待するリソースを取得でき、そのコンテナーが同じホスト上で動作している他のコンテナーのパフォーマンスに影響を与えないようにします。たとえば、コンテナーが10%以上のCPUを使えないように、コンテナーを制限できます。これは、たとえコンテナー内のアプリケーションが試みても、そのホストが他のコンテナーに割り当てたり、そのホスト自体が使うために割り当てたりすることができる、他の90%にアクセスできないことを意味しています。Linuxは、「cgroups」と呼ばれるテクノロジを使って、こういったガバナンスを実装しています。
同じホスト上に配置されたコンテナーが協調的な場合には、アプリケーション コードの変化する要求に適応するOS標準の動的リソース割り当てが可能となり、リソース ガバナンスは必要ありません。

OS仮想化による即時起動と、名前空間の分離とリソース ガバナンスによる信頼性の高い実行の組み合わせによって、コンテナーは、アプリケーションの開発/テストに最適なものになります。開発プロセスの間、開発者は迅速に反復できます。コンテナー化されたアプリケーションの環境とリソース使用は、システムにわたって一貫しているので、開発者のシステム上で動作するコンテナー化されたアプリケーションは、異なる運用システム上でも同様に動作するでしょう。また、即時起動と小さいフットプリントは、クラウドのシナリオでも役立ちます。アプリケーションが迅速にスケール アウトでき、各アプリケーションが異なるVMで動作する場合に比べて、さらに多くのアプリケーション インスタンスがマシンに収まることができ、リソース使用率を最大化できるからです。

仮想マシンを使う類似のシナリオをコンテナーを使うシナリオと比べると、共有によって得られる効率性が強調されます。次に示した例では、ホスト マシンは3つのVMを持っています。VM内のアプリケーションに完全な分離を提供するために、VMはそれぞれ、OSの完全なイン メモリ インスタンスとともに、OSファイル、ライブラリ、アプリケーション コードの独自コピーを持っています。新規VMを起動するには、たとえホストや既存のVMがOSの同じバージョンの実行中インスタンスを持っていたとしても、OSの別インスタンスをブートし、アプリケーション ライブラリをメモリにロードする必要があります。各アプリケーションVMは、OSブートと独自のプライベート コピーのためのイン メモリのフットプリントというコストを払っています。また、このフットプリントは、そのホスト上で動作できるアプリケーション インスタンス (VM) の数を制限します。

image

次の図は、コンテナーによる同じシナリオを示しています。ここでは、コンテナーは、単にカーネルやライブラリを含むホストOSを共有しているので、OSをブートし、ライブラリをロードし、それらのファイルのためのプライベート メモリのコストを払う必要はありません。コンテナーが使う唯一の増分領域は、アプリケーションがコンテナー内で動作するために必要となるメモリとディスク領域です。アプリケーションの環境は専用OSのようであり、アプリケーションは専用ホスト上にデプロイされる場合と同様にデプロイされます。コンテナー化されたアプリケーションは数秒で起動し、VMの場合に比べて、さらに多くのアプリケーション インスタンスをマシンに収めることができます。

image

Dockerの魅力

OSに関連する名前空間の分離やリソース ガバナンスの概念は、BSD Jail、Solarisゾーン、基本的なUNIXのchroot (change root) メカニズムなど、長い間存在していました。しかし、Dockerは、共通のツールセット、パッケージング モデル、デプロイのメカニズムを作ることによって、どのLinuxホスト上でも動作できるアプリケーションのコンテナー化と配布を大幅に簡素化しました。この普遍的なテクノロジは、あらゆるホストに対して同じ管理コマンドを提供することで、管理を簡素化するだけでなく、シームレスなDevOpsへのまたとない機会も作ります。

開発者のデスクトップからテスト マシン、一連の運用マシンまで、数秒であらゆる環境に同様にデプロイされるDockerイメージを作成できます。これは、Dockerコンテナーにパッケージされたアプリケーションの、成長する巨大なエコシステムを作り出しました。Dokcerが運用しているパブリックなコンテナー化アプリケーション レジストリであるDockerHubでは、現在、パブリック コミュニティ リポジトリに18万以上のアプリケーションを公開しています。加えて、パッケージング フォーマットを普遍的なものにするために、Dockerは、最近、コンテナー パッケージングを財団が主導するオープンなフォーマットにすることを目指して、Open Container Initiative (OCI) を組織しました。Microsoftは、OCIの創設メンバーの1社です。

Windows Serverとコンテナー

コンテナーの力をすべての開発者にもたらすために、昨年10月、我々は、Windows Serverでコンテナー テクノロジを実装する計画を発表しました。また、Linux Dockerコンテナーを使っている開発者に、Windows Server上でまったく同じエクスペリエンスを提供するために、我々は、Windows ServerコンテナーをサポートするようにDockerのAPIとツールセットを拡張するための、Dockerとの提携も発表しました。我々にとって、これは、LinuxとWindowsを同等に扱うすべてのお客様の利益になる機会でした。最近私がDockerConでデモしたように、我々は、開発者やシステム管理者がWindows Server、Linuxの両方で構成されるコンテナー化されたアプリケーションをデプロイするための、統一されたオープンなエクスペリエンスを作り出せて、興奮しています。我々は、オープンなDocker GitHubリポジトリ (英語 / 日本語) でこれを開発中です。

Widnows Server 2016では、どちらもDocker APIとDockerクライアントを使ってデプロイ可能な、2種類のコンテナー (Windows Serverコンテナー、Hyper-Vコンテナー) をリリースする予定です。Linuxコンテナーはホスト カーネルのLinux APIを必要とし、Widnows ServerコンテナーはホストのWindowsカーネルのWindows APIを必要とします。そのため、Windows Serverホスト上でLinuxコンテナーを実行できず、Linuxホスト上でWindows Serverコンテナーを実行できません。しかし、同じDockerクライアントがこれらのコンテナーのすべてを管理できます。パッケージされたWindowsコンテナーをLinux上で実行することはできませんが、Windows Serverコンテナー、Hyper-Vコンテナーは両方ともWindowsカーネルを利用しているので、Windowsコンテナー パッケージは、Windows Serverコンテナー、Hyper-Vコンテナーで動作します。

Windows Serverコンテナー、Hyper-Vコンテナーをいつ使いたいのか、という質問があります。カーネルの共有によって高速な起動と効率的な集約が可能になりますが、Windows Serverコンテナーは、ホストや他のコンテナーとOSを共有しています。共有されているAPIやAPIの量は、仕様としてにせよ、名前空間の分離やリソース ガバナンスの実装の欠陥のためにせよ アプリケーションがそのコンテナーから脱出したり、ホストや他のコンテナーへのサービスを拒否したりする方法があるかもしれないことを意味しています。OSベンダーがパッチを適用するローカルでの特権の昇格の脆弱性は、アプリケーションが活用できる欠陥の一例です。

そのため、Windows Serverコンテナーは、OSがその中にホストするアプリケーションを信頼し、すべてのアプリケーションが互いに信頼しているシナリオに最適です。言い換えれば、ホストOSとアプリケーションが、同じ信頼境界の中にあります。これは、多くの複数コンテナー アプリケーション、より大きなアプリケーションの共有サービスを構成するアプリケーション、時には同じ組織のアプリケーションにも当てはまります。

しかし、同じホスト上で異なる信頼境界のアプリケーションを実行したい場合があります。その一例は、サービスの機能を拡張するために、お客様が独自のコードを提供できるようにした、
マルチ テナントのPaaS/SaaS機能を実装する場合です。あるお客様のコードがサービスに干渉したり、他のお客様のデータにアクセスしたりしないようにしたいでしょう。しかし、VMより機敏で、Dockerのエコシステムを活用するコンテナーを必要としています。Azure AutomationやAzure Machine Learningなど、Azureでこのようなサービスの例がいくつかあります。故意に分離を覆そうとしているお客様がいると想定しなければならないので、我々は、このようなサービスが動作している環境を「敵対的マルチ テナント」と呼んでいます。この種の環境では、Windows Serverコンテナーの分離が十分な保証を提供しない可能性があり、これがHyper-Vコンテナーを開発する動機を与えました。

Hyper-Vコンテナーは、コンテナー化に対して少し異なるアプローチを取っています。さらなる分離を提供するために、各Hyper-VコンテナーはWindowsカーネルの独自コピーを持っており、各コンテナーに直接割り当てられたメモリを持っています。これは、強力な分離の主な要件です。我々は、CPU、メモリ、(ネットワークやストレージといった) IOの分離のためにHyper-Vを使っており、VMと同じレベルの分離を提供します。VMと同様に、ホストは、ホスト リソースの通信と共有のために、小さな制約されたインターフェイスをコンテナーに公開しているだけです。この非常に制限された共有は、Hyper-Vコンテナーが、Windows Serverコンテナーに比べて起動時間と密度に関して少し効率が悪いが、信頼されていない「敵対的マルチ テナント」アプリケーションを同じホスト上で実行できるようにするために必要となる分離を提供していることを意味しています。

それでは、Hyper-VコンテナーはVMと同じではないのでしょうか? Hyper-Vコンテナーが物理マシン内ではなくコンテナー内にあると完全に認識していることに起因する、OSへの最適化に加えて、Hyper-VコンテナーはDockerの魔法を使ってデプロイされ、Windows Serverコンテナー内で動作するものとまったく同じパッケージを使えます。そのため、分離レベルと効率性/機敏性との間のトレードオフは、開発時の決断ではなく、ホストの所有者が行うデプロイ時の決断になります。

オーケストレーション

お客様がコンテナーを採用したので、課題を発見しました。アプリケーションを構成する数十、数百、数千のコンテナーをデプロイする際、デプロイの追跡と管理は、管理とオーケストレーションの両方における進歩を必要とします。コンテナー オーケストレーションは、複数の選択肢と解決策がある、心躍る革新の新領域になりました。コンテナー オーケストレーターは、通常「クラスター」と呼ばれるサーバー (VM、またはベア メタル サーバー) のプールを割り当てられ、これらのサーバー上でコンテナーのデプロイを「スケジュール」します。さらに進み、コンテナーと異なるサーバーとの間のネットワーキングを構成するオーケストレーターもあれば、負荷分散、コンテナー名前解決、ローリング アップデートなどを提供するオーケストレーターもあります。拡張可能で、アプリケーション フレームワークが追加機能を持ち込めるようにしているオーケストレーターもあります。

オーケストレーション ソリューションのより深い議論には別のブログ ポストが必要です。ここでは、Azure上でサポートされているいくつかのテクノロジの簡単な概要を示します:

  1. Docker Compose (英語 / 日本語) は、単純な複数コンテナー アプリケーションの定義を可能にします。Docker Swarm (英語 / 日本語) は、単一のDockerホストが使うのと同じAPIを介して、複数のホストにわたってDockerコンテナーを管理、組織します。SwarmとComposeは一緒になって、Dockerが構築した完全なオーケストレーション テクノロジを提供します (英語 / 日本語)
  2. Mesos (英語 / 日本語) は、実際にはDockerより前から存在していた、オーケストレーションと管理のソリューションですが、最近、その組み込みアプリケーション フレームワークであるMarathonに、Dockerのサポートを追加しました。これは、Mesosphere (英語 / 日本語) が構築したオープンでコミュニティ駆動のソリューションです。我々は最近、Azure上でのMesos、DCOS (英語 / 日本語) との統合をデモしました。
  3. Kubernetes (英語 / 日本語) は、複数ホストにわたる管理のために、コンテナーの「ポッド」へのグループ化を提供する、Googleが構築したオープン ソースのソリューションです。これもまた、Azure上でサポートされています (英語 / 日本語)
  4. Deis (英語 / 日本語) は、Dockerと統合されたアプリケーションのデプロイ、管理を行うための、オープン ソースのPaaSプラットフォームです。Azure上にDeisクラスターをデプロイする、簡単な方法があります (英語 / 日本語)

我々は、人気の高いオーケストレーション ソリューションのほとんどをAzureでサポートしていることに興奮しており、時とともに興味と使用が増えるにつれて、これらのコミュニティとさらに関与することを期待しています。

マイクロサービス

即座に効果の出るコンテナーの使用方法は、開発者がクラウドやオンプレミスにデプロイされるサービスのための運用フローをテストする、DevOpsの簡素化に焦点を合わせてきました。しかし、コンテナーが非常に説得力を持つようになる、高まりつつあるもう1つのシナリオがあります。マイクロサービスは、アプリケーションの各部分が、マイクロサービスと呼ばれる、個別にスケール、更新可能な完全に自己完結型のコンポーネントとしてデプロイされる、アプリケーション開発のアプローチです。たとえば、パブリック インターネットからリクエストを受信するアプリケーションのサブシステムは、バックエンド サブシステムが読み取ってデータベースに格納するように、リクエストをキューに配置するサブシステムから分離しているかもしれません。マイクロサービスを使ってアプリケーションが構築されている場合、各サブシステムがマイクロサービスです。単一マシン上の開発/テスト環境では、各マイクロサービスは1インスタンスかもしれませんが、運用環境で動作する際は、各マイクロサービスは、ユーザーリクエストの増減に従い、リソース需要に応じて、サーバーのクラスターにわたって異なるインスタンス数までスケール アウトできます。また、別々のチームがそれぞれマイクロサービスを開発している場合、チームは独立してマイクロサービスを更新できます。

マイクロサービスはプログラミングの新しいアプローチではなく、コンテナーと明示的に結びついているわけでもありませんが、複雑なマイクロサービス ベースのアプリケーションに適用されると、Dockerコンテナーの利点は強まります。機敏性は、増大した負荷に対応するためにマイクロサービスが迅速にスケール アウトできることを意味しており、コンテナーによる名前空間とリソースの分離が、1つのマイクロサービスが他のマイクロサービスと干渉するのを防ぎ、Dockerのパッケージング フォーマットとAPIの使用が、マイクロサービス開発者とアプリケーション運用者にDockerエコシステムを解き放ちます。優れたマイクロサービス アーキテクチャによって、お客様は、高い機敏性を維持しつつ、可用性喪失の危険性を減らして、コンテナー ベースのサービスの管理、デプロイ、オーケストレーション、パッチ適用のニーズを解決できます。

現在、マイクロサービスを使ったアプリケーション モデル構築にはいくつかのソリューションがあり、我々はAzureでそれらの多くと提携しています。Docker ComposeとMesosphere Marathonは、その2つの例です。//buildの少し前に、我々は、独自のマイクロサービス アプリケーション プラットフォームであるAzure Service Fabricを発表 (英語 / 日本語)
、リリースしました。Service Fabricには、ロールバックを備えたローリング アップデート、パーティション分割、配置制約といった、一連の高度なマイクロサービス ライフサイクル管理機能が含まれています。特に、Service Fabricは、ステートレス マイクロサービスに加えて、ステートフル マイクロサービスもサポートしています。ステートフル マイクロサービスは、マイクロサービスがデータを管理し、データがマイクロサービスと同じサーバーに存在することで差別化されます。実際、Service Fabricは、クラスター管理に直接組み込まれた状態管理とレプリケーション フレームワークを備えた、ステートフル マイクロサービスを提供する唯一のPaaSプラットフォームです。我々は、内部サービスがステートフル レプリケーションでハイパースケールまでスケールできるように、このアプリケーション モデルを開発しました。Cortana、Azure SQL Database、Skype for Businessといったサービスが、Service Fabric上に構築されています。今年中にService Fabricのパブリック プレビューをリリースする予定ですが、それまでの間、こちらで (英語 / 日本語) Service Fabricについてさらに確認できます。

このポストが、Microsoftのコンテナーのビジョン、最も一般的なコンテナーの使用事例、コンテナー周辺の現れつつあるいくつかの業界の動向を描き出すのに役立つことを期待しています。いつものように、皆さんがさらに学びたい領域がある場合は特に、みなさんからのフィードバックをお待ちしています。

関連情報