コンテナー テクノロジ: Docker、Windows とトレンド
このポストは、2015 年 8 月 17 日に投稿された Containers: Docker, Windows and Trends の翻訳です。この記事は、マイクロソフトの Azure CTO、Mark Russinovich によって執筆されました。
今やコンテナーを語らずして、クラウド コンピューティングを語ることはできません。銀行や大手金融サービス企業から EC サイトまで、あらゆるビジネス分野にわたる組織が、コンテナーとは何か、クラウド内のアプリケーションにとってコンテナーはどういう意味があるのか、コンテナー固有の開発や、 IT 運用のシナリオでコンテナーを最大限に利用する方法などについて、理解したいと考えています。
コンテナーの概要やしくみなどの基本から、コンテナーが、現在最も幅広く使用されているシナリオ、「コンテナー化」をサポートする最新のトレンドまで、私の個人的な見解を皆様にお伝えすることで、この重要なクラウド コンピューティング開発を最大限に活用して、クラウド アプリケーションの構築、テスト、展開、管理をよりシームレスに進める方法を、深くご理解いただけたらと思います。
コンテナーの概要
抽象的な言葉で言えば、コンピューティングはすべて、1+1 のような単純な計算であれ、Exchange のように、複数のマシンにまたがる複雑なアプリケーションであれ、あるタスクを遂行するために、プロセッサ、メモリ、ディスク、ネットワークなど、一連の「物理」リソースで何らかの「機能」を実行することに基づきます。時代を経て物理リソースが強力になるにつれ、アプリケーションは物理マシンが、提供するリソースの一部すら利用しないことも多くなりました。このため、基盤となる物理ハードウェアを、シミュレーションするために「仮想」リソースが作り出されました。これにより複数のアプリケーションを同時に実行できるようになり、それぞれのアプリケーションは同じ物理マシン上の物理リソースの一部を有効活用します。
一般に、こうしたシミュレーション技術を仮想化と言います。多くの人は仮想化と聞くと、仮想マシンをすぐに思い出しますが、仮想マシンは仮想化の実装の 1 つにすぎません。すべての汎用 OS (オペレーティング システム) で実装されているメカニズムである仮想メモリは、コンピューターのメモリがアプリケーション専用であると、アプリケーションに錯覚させるもので、アプリケーションがコンピューターで利用可能な RAM をはるかに上回るメモリ容量を、利用することも可能です。
コンテナーは別の種類の仮想化で、OS 仮想化とも呼ばれます。Linux 上の今日のコンテナーは、アプリケーションに対し完全に分離し、独立した OS という認識を作り出すものです。実行中のコンテナーにとって、ローカル ディスクは OS ファイルの初期コピーのように見え、メモリには起動されたばかりの OS のファイルとデータのみが、保持されているように見えます。実行されているのは OS のみです。これを実現するために、コンテナーを作成する「ホスト」マシンは優れた処理を行います。
最初の手法は名前空間の分離です。名前空間には、ファイル、ネットワーク ポート、実行中のプロセスのリストなど、アプリケーションがやり取りできるすべてのリソースが含まれます。名前空間を分離することで、ホストは、認識すべきリソースのみを含む仮想化された名前空間を、各コンテナーに提供することができます。このように、見えるリソースが制限されているため、権限にかかわらず、コンテナーは仮想化された名前空間にないファイルには、アクセスできません。単純にそれらのファイルは見えないからです。また、コンテナー自体にないアプリケーションをリストしたり、やり取りしたりすることもできません。コンテナーは、他に数十、数百というアプリケーションがあっても、自分がシステムで実行されている唯一のアプリケーションであると認識しています。
効率性のため、OS のファイル、ディレクトリ、実行中のサービスの多くは、コンテナー間で共有され、各コンテナーの名前空間に反映されます。たとえば、既存のファイルを変更したり、新しいファイルを作成するなどして、アプリケーションがコンテナーに変更を加えた場合のみ、コンテナーは基盤となるホスト OS から別個のコピーを取得します (ただし、Docker の「コピー オン ライト」最適化を使用して、変更された部分のみコピーします)。この共有は、1 つのホスト上に複数のコンテナーを展開する処理を大幅に効率化することに一役買っています。
2 つ目の手法は、コンテナーが使用できるホストのリソースの容量を、ホストが制御することです。CPU、RAM、ネットワーク帯域幅などのリソースを管理することで、コンテナーは必要なリソースを確実に取得でき、ホストで実行中の他のコンテナーのパフォーマンスに影響を与えることもありません。たとえば、コンテナーの CPU 使用率を 10% 以下に制限することができます。つまり、コンテナー内のアプリケーションが使用しようとしても、残りの 90% にはアクセスできず、ホストは、その分を他のコンテナーやホスト自体の用途に割り当てることができます。Linux では、「cgroup」という技術を使用してこうしたガバナンスを実装します。同じホストのコンテナーが相互に協調動作する場合、リソースのガバナンスは不要です。標準の OS 動的リソース割り当てによって、アプリケーション コードの需要の変化に対応できます。
OS 仮想化による瞬時の起動と、名前空間の分離とリソース ガバナンスによる信頼性の高い実行を兼ね備えることで、コンテナーはアプリケーションの開発とテストに理想的なものになります。開発プロセスの際に、開発者は速やかに反復できます。環境とリソースの利用がシステム全体で一貫しているため、コンテナー化されたアプリケーションが開発者のシステムで動作すれば、別の実稼動システムでも同じように動作します。瞬時に起動し、フットプリントが小さいことは、クラウド シナリオにも役立ちます。アプリケーションを速やかにスケールアウトでき、アプリケーションを 1 つずつ VM に割り当てる場合よりも多くのアプリケーション インスタンスを 1 台のマシンに収めることができるので、リソースを最大限に活用できるためです。
仮想マシンを使用するシナリオと、コンテナーを使用する類似のシナリオを比較すると、共有によって得られる効率性が浮き彫りになります。下記の例のホスト マシンには VM が 3 つあります。VM 内のアプリケーションを完全に分離するために、VM はそれぞれ、OS ファイル、ライブラリ、アプリケーション コードの独自のコピーと、OS の完全なインメモリ インスタンスを持っています。新しい VM を起動するには、ホストまたは既存の VM に同じバージョンの実行中インスタンスが既にある場合でも、OS のインスタンスを別に起動し、アプリケーション ライブラリをメモリに読み込む必要があります。各アプリケーションの VM は、OS の起動と、独自のプライベート コピーのためのインメモリ フットプリントという代償を払うことになり、ホスト上で実行できるアプリケーション インスタンス (VM) の数も限られます。

下記の図は同じシナリオでコンテナーを使用したケースです。ここでは、コンテナーは、カーネル、ライブラリを含め、ホスト オペレーティング システムを共有しているだけなので、OS を起動する必要も、ライブラリを読み込む必要も、そうしたファイルのためのプライベート メモリという代償を払う必要もありません。追加で使われる容量は、コンテナー内で実行するアプリケーションに必要なメモリとディスク容量のみです。アプリケーションの環境は専用 OS のようですが、アプリケーションの展開方法は、専用ホストの場合とまったく同じです。コンテナー化されたアプリケーションは数秒で起動し、VM のケースよりも多くのアプリケーション インスタンスをマシンに収容することができます。

Docker の魅力
OS に関連する名前空間の分離とリソース ガバナンスの概念は昔からあり、BSD jail、Solaris ゾーン、基本的な UNIX chroot (change root) メカニズムまでさかのぼります。しかし Docker は、共通のツールセット、パッケージング モデル、および展開のメカニズムを作成することで、アプリケーションのコンテナー化と配布を大幅に簡素化し、Linux ホスト上の任意の場所からアプリケーションを実行できるようにしました。このユビキタス技術は、どのホストに対しても同じ管理コマンドを提供することで管理を簡素化しただけでなく、シームレスな開発運用のすばらしいチャンスも生み出しました。
開発者のデスクトップからテスト マシン、一連の実稼動マシンまで、どのような環境にも数秒で同じように展開される Docker イメージを作成できます。こうした話とともに、Docker コンテナーにパッケージ化されるアプリケーションの巨大で成長を続けるエコシステムを作ったのが、DockerHub です。これは、Docker が保持するパブリックのコンテナー型アプリケーション レジストリで、現在 180,000 を超えるアプリケーションがパブリック コミュニティのリポジトリに公開されています。また、パッケージ形式を汎用的にするため、Docker は OCI (Open Container Initiative) を最近立ち上げ、創設メンバーの 1 社であるマイクロソフトと共に、コンテナーのパッケージをオープンで OCI 主導の形式にすることを目指しています。
Windows Server とコンテナー
コンテナーの力をすべての開発者に届けるため、昨年 10 月、マイクロソフトは Windows Server にコンテナー技術を実装する計画を発表しました。Linux Docker コンテナーを使用する開発者に Windows Server でもまったく同じエクスペリエンスを実現するよう、マイクロソフトは Docker と共同で、Windows Server Container をサポートする Docker API とツールセットの拡張に取り組むことも発表しました。マイクロソフトにとって、これは、Linux、Windows を問わず、すべてのお客様にメリットをもたらす機会となりました。最近 DockerCon でデモを行いましたが、マイクロソフトでは、開発者とシステム管理者が Windows Server と Linux の両方から成り立つコンテナー型アプリケーションを展開するための統一されたオープンの操作環境を、作成したいと考えています。この開発はオープンの Docker GitHubリポジトリで続いています。
Windows Server 2016 では、Docker API と Docker クライアントを使用して展開できる 2 種類のコンテナー、Windows Server Container と Hyper-V Container をリリースする予定です。
Linux コンテナーにはホスト カーネルの Linux API が必要であり、Windows Server Container にはホストの Windows カーネルの Windows API が必要なので、Windows Server ホストで Linux コンテナーを実行したり、Linux ホストで Windows Server Container を実行したりすることはできません。ただし、同じ Docker クライアントでこれらのコンテナーをすべて管理できるので、パッケージ化された Windows コンテナーを Linux で実行することはできませんが、Windows Server Container と Hyper-V Container はどちらも Windows カーネルを利用しているため、Windows コンテナーのパッケージで使用できます。
そこで、Windows Server Container と Hyper-V Container のどちらを使用するか、という問題があります。カーネルを共有すると起動が高速になり、パッケージ化の効率が高まりますが、Windows Server Container はホストおよびコンテナー相互で OS を共有します。共有されるデータと API があることは、仕様上の問題か、名前空間の分離やリソース ガバナンスでの実装の欠陥のためかにかかわらず、アプリケーションがそのコンテナーから逸脱したり、ホストや他のコンテナーへのサービスを拒否したりする方法が存在する可能性を意味しています。権限のローカル エレベーションの脆弱性は、オペレーティング システム ベンダーが修正プログラムを適用しますが、これはアプリケーションに影響する可能性がある欠陥の一例です。
つまり、Windows Server Container は、OS が OS 上でホストされるアプリケーションを信頼し、アプリケーションもすべて相互に信頼するシナリオに適しています。言い換えれば、ホストの OS とアプリケーションは同じ信頼の境界内にあります。これは、多くのマルチコンテナー アプリケーションや、大規模なアプリケーションの共有サービスを構成するアプリケーションに当てはまります。また、同じ組織のアプリケーションに当てはまることもあります。
とはいえ、同一ホスト上でも異なる信頼の境界からアプリケーションを実行したいケースもあります。その一例が、マルチテナント PaaS または SaaS 製品を実装する際に、お客様が独自のコードを利用してサービスの機能を拡張することを認める場合です。あるお客様のコードがサービスを妨げたり、他のお客様のデータにアクセスしたりすることがあってはなりませんが、VM よりも即応性に優れ、Docker エコシステムを利用するコンテナーが必要です。Azure には、Azure Automation や Machine Learning など、こうしたサービスの例がいくつもあります。分離を意図的に破壊しようとするお客様がいるのを前提とする必要があるため、マイクロソフトでは、この実行環境のことを「悪意のあるマルチテナント」と呼んでいます。こうした種類の環境では、Windows Server Container の分離では、十分な保証を確保できないことが Hyper-V Container を開発するきっかけとなりました。
Hyper-V Container はコンテナー化とは若干異なるアプローチを取ります。より進んだ分離を作成するため、Hyper-V Container は、それぞれ Windows カーネルの独自のコピーを持ち、メモリはコンテナーに直接割り当てられています。これが強力な分離の重要な要件です。マイクロソフトでは、CPU、メモリ、IO の分離に (ネットワークやストレージのように) Hyper-V を使用して、VM と同じレベルの分離を提供しています。VM の場合のように、ホストは制約のある小さいインターフェイスのみをコンテナーに公開し、通信やホスト リソースの共有に利用します。このように共有が非常に限定されているため、Hyper-V Container は起動時間と密度の点で Windows Server Container より効率性が若干劣りますが、信頼できない「悪意のあるマルチテナント」アプリケーションを同じホスト上で実行することを認めるために必要な分離は確保されます。
では、Hyper-V Container は VM とは同じではないのでしょうか。OS が物理マシンではなくコンテナーにあることを OS が完全に認識するという OS 最適化のほかに、Hyper-V Container は Docker のマジックを使って展開され、Windows Server Container で実行されるパッケージとまったく同じパッケージを使用できます。このように、分離のレベルと効率性/即応性の得失は、開発時の判断ではなく、展開時の判断です。どちらを取るかはホストの所有者に任されます。
オーケストレーション
コンテナーの採用が進むにつれ、お客様にはある課題が生じました。アプリケーションを構成する、数十、数百、数千という数のコンテナーを展開すると、その展開を追跡、管理する際に、管理とオーケストレーションの両面で高度な機能が必要になるのです。コンテナーのオーケストレーションは、複数のオプションやソリューションを、伴う新しい魅力的なイノベーション分野になりました。コンテナーのオーケストレーション機能には、一般に「クラスター」と呼ばれるサーバー (VM またはベア メタル サーバー) のプールが割り当てられ、このオーケストレーション機能がこれらのサーバーへのコンテナーの展開を「スケジュール」します。オーケストレーション機能の中には、さらに進化して、異なるサーバー上のコンテナー間のネットワーキングを構成するものもあれば、負荷分散、コンテナーの名前解決、ローリング アップデートなどが含まれるものもあります。また、拡張可能で、アプリケーション フレームワークを、利用してこうした追加機能を実現できるものもあります。
オーケストレーション ソリューションを詳しく説明するには、別のブログが必要になりますので、ここでは、すべて Azure でサポートされるテクノロジをいくつか簡単に紹介します。
- Docker Compose では、単純なマルチコンテナー アプリケーションの定義が可能です。 Docker Swarm は、1 つの Docker ホストで使用される同じ API を使用して複数のホスト間で、 Docker コンテナーを管理、整理します。Swarm と Compose が一体となって、Docker で構築された完全なオーケストレーション テクノロジを提供します。
- Mesos は、実は Docker より前のオーケストレーション/管理ソリューションですが、最近、組み込みのアプリケーション フレームワーク Marathon に Docker のサポートが追加されました。Mesosphere によって構築された、オープンでコミュニティ主導のソリューションです。マイクロソフトでは、最近、 Azure における Mesos と DCOS の統合のデモを行いました。
- Kubernetes は、Google が構築したオープン ソース ソリューションで、コンテナーを「ポッド」というグループに分類して、複数のホスト間の管理を可能にするものです。これも Azure でサポートされています。
- Deis は、Docker と統合されたアプリケーションを展開、管理するためのオープン ソースの PaaS プラットフォームです。 Deis クラスターを Azure に簡単に展開する方法があります。
マイクロソフトでは、人気の高いオーケストレーション ソリューションのほとんどを Azure でサポートできるようにしたいと考えています。時間をかけて関心の高まりと使用の拡大を見守りながら、こうしたコミュニティとのかかわりを強化したいと思います。
マイクロ サービス
コンテナーの使用はすぐに効果が現れるので、クラウドやオンプレミスに展開するサービスを、開発者が生産フローに対してテストするための開発運用を簡素化する上で、重視されてきました。しかし、コンテナーが非常に魅力的になる成長シナリオがもう 1 つあります。マイクロサービスは、アプリケーションの各部分を、個別に拡大/縮小したり更新したりできる、完全な自己完結型コンポーネント (マイクロサービス) として、展開するアプリケーション開発のアプローチです。たとえば、パブリック インターネットからリクエストを受け取るアプリケーションのサブシステムは、そのリクエストをバックエンド サブシステムのキューに入れてから読み取って、データベースに落とすサブシステムとは分離されます。マイクロサービスを使用してアプリケーションを作成した場合は、各サブシステムがマイクロサービスです。1 台のマシンの開発/テスト環境では、各マイクロサービスのインスタンスが 1 つであったとしても、運用時には、お客様のリクエスト レベルの増減に伴うリソースの需要に応じて、サーバーのクラスター全体で各インスタンスの数を増減することができます。別のチームが作成したマイクロサービスは、個別に更新することもできます。
マイクロサービスは、プログラミングの新しいアプローチというわけでも、コンテナーに明確に結び付けられているわけでもありませんが、Docker コンテナーのメリットは、複雑なマイクロサービス ベースのアプリケーションに適用すると増大します。即応性により、負荷の増加に合わせてマイクロサービスを速やかにスケールアウトできるだけでなく、コンテナーの名前空間とリソースの分離によってマイクロサービス インスタンス同士が競合し合うことが防止され、また、Docker のパッケージ形式と API を使用することで、 Docker のエコシステムをマイクロサービスの開発者やアプリケーション運用者が活用できます。優れたマイクロサービス アーキテクチャにより、お客様は、コンテナー ベースのサービスの管理、展開、オーケストレーション、修正プログラム適用のニーズを解決でき、高い即応性を維持しながら、可用性が低下するリスクを軽減できます。
今日では、マイクロサービスを使用してアプリケーション モデルを構築するソリューションがいくつかあり、マイクロソフトは Azure でそれらの多くと連携しています。Docker Compose と Mesosphere Marathon は 2 つの例です。//build の少し前に、マイクロソフトでは、Service Fabric という独自のマイクロサービス アプリケーション プラットフォームの開発者向けプレビューを発表し、リリースしました。このプラットフォームには、ロールバックが可能なローリング アップデート、パーティション作成、プレースメント制約など、マイクロサービスのライフサイクル管理機能が、豊富に取り込まれています。特に、Service Fabric は、ステートレス マイクロサービスに加えて、マイクロサービスは、同じサーバー上に共存するデータを管理するという事実に反して、ステートフル マイクロサービスもサポートしています。実際、Service Fabric は、ステートフル マイクロサービスを提供する唯一の PaaS プラットフォームで、状態の管理とレ、プリケーションのフレームワークは、クラスター管理に直接組み込まれています。マイクロソフトがこのアプリケーション モデルを開発した目的は、内部サービスをステートフル レプリケーションでハイパースケールまで拡張できるようにすることにあり、Cortana、Azure SQL Database、Skype for Business といったサービスがこのモデルをベースとしています。Service Fabric のパブリック プレビューは今年後半にリリースする予定です。それまで Service Fabric について詳しくはこちらをご覧ください。
マイクロソフトのコンテナー像、よくあるコンテナーの事例、そしてコンテナーを巡る業界の新たなトレンドを理解するために、このブログをお役立ていただければと思います。詳しく知りたい分野などございましたら、ご意見をお寄せください。お待ちしております。