コンテナ技術の基礎知識
コンテナの概要
ITシステムにおいて、開発面や運用面の変化へ迅速に対応する解決策の1つとして、従来では、仮想化ソフトウェアの採用がありました。仮想化ソフトウェアは、複数のOS環境とアプリケーションを1つのファイルとして取り扱い、非常に可搬性の高い基盤を提供します。しかし、Dockerに比べ、複数のOSを集約した場合の性能劣化や、OSとアプリケーションの仲立ちをする仮想化ソフトウェアの介在による障害発生時の問題切り分けの複雑化が問題視されてきました。Dockerは、従来のハイパーバイザー型の仮想化とは異なり、1つのOS環境に、コンテナと呼ばれる分離された空間を作成し、その分離された空間ごとに異なるOS環境を実現することができます。コンテナによってマルチOS環境を実現することができるため、複数のOSバージョンを必要とするITシステムを1つのOS環境に集約できるというメリットがあります。
コンテナは、アプリケーションの分離された空間を提供します。アプリケーションの分離された空間を実現することで、1つのOS環境でありながら、プロセスを分離することができるため、マルチOS環境を実現することができます。例えば、CentOS 7のホストOS上でDockerを稼働させ、CentOS 6.6のDockerコンテナや、Ubuntu Server 14.04 LTSのDockerコンテナを複数同時に稼働させることも可能です。
コンテナ自体は、Dockerが登場する以前から存在し、古くから商用製品にも採用されている技術で、一般的に、Linux OS上での分離された空間を「Linuxコンテナ」と呼びます。Linuxコンテナは、一般的に、LXCとも呼ばれます。古いバージョンのDockerは、Linuxコンテナを使っていたため、DockerとLinuxコンテナが同一のものとして考えても差し支えありませんでしたが、現在のDockerは、libcontainerと呼ばれるドライバーを利用するようになり、Linuxコンテナに依存する部分が無くなったため、LinuxコンテナとDockerは、同じものではありません。しかし、考え方という観点では、LinuxコンテナもDockerコンテナも、同様の分離された空間を提供することには違いがありません。LinuxコンテナやDocker以外では、商用製品として、Parallels社のVirtuozzo(バーチュオッゾ)、オープンソースのコミュニティであるOpenVZ、UNIX系OSでは、HP-UX Container、Solaris Containerなどが存在します。
これらLinuxコンテナや商用製品、UNIX系のコンテナは、いずれも単一OS上で複数の分離された空間を提供するという特徴を持っており、ハイパーバイザー型の仮想化ソフトウェアではありません。
[補足] libcontainerについて
libcontainerは、Dockerのバージョン0.9から実装されています。libcontainerに関する情報は、Dockerの公式ブログの以下のURLに情報が掲載されています。
https://blog.docker.com/2014/03/docker-0-9-introducing-execution-drivers-and-libcontainer/
[参考] LXCとLXD
LXCは、Linuxコンテナにおけるライブラリやツールなどを提供しており、すでに多くの商用環境で利用されており、実績も豊富です。LXCは、Linuxカーネルのコンテナ機能を利用するために設けられたユーザー空間で稼働するツールやAPIを提供します。一方、2014年11月、新しく登場したLXDは、新しいコンテナ管理のための仕組みです。lxdと呼ばれるデーモンが稼働するハイパーバイザーであり、コマンドラインのツール群がlxcとして用意されています。また、LXDでは、REST API通信により、ネットワーク経由でコンテナを管理することが可能です。
さらに、OpenStack Novaプラグイン(nova-compute-lxd)と呼ばれるコンポーネントが存在し、OpenStackクラウド基盤におけるコンテナ利用を想定したアーキテクチャになっています。Ubuntu Server 15.04に搭載されており、注目が集まっています。現在はまだ開発途上であり、安定的な運用には程遠く、商用環境での採用は見送ったほうがよいでしょうが、スナップショット、ライブマイグレーション、セキュリティを意識した設計になっており、Dockerと並んで今後非常に注目すべき技術と言えるでしょう。
LXDに関する情報
https://linuxcontainers.org/lxd/
以上で、コンテナの主要な製品や最新技術をいくつか紹介しました。以下に、商用UNIX系のコンテナを除く主なコンテナを表で簡単にまとめておきます。
ハイパーバイザー型の仮想化基盤とコンテナの違い
一般的なハイパーバイザー型の仮想化ソフトウェアとしては、VMwareやHyperV、KVMなどが有名ですが、これらの仮想化ソフトウェアは、ハイパーバイザーと呼ばれるソフトウェアが、仮想的なハードウェアである「仮想マシン」を提供します。その仮想マシンが提供する仮想的なBIOS、仮想CPU、仮想メモリ、仮想ディスク、仮想NICなどをゲストOSに見せることで、ゲストOSからは、あたかも物理的なマシンで稼働しているかのように見えます。このため、ゲストOSとしては、通常のOSの起動、停止となんら変わらない運用が必要となります。例えば、ゲストOSでは、自身の仮想ディスクのマスターブートレコード領域に対してブートローダをインストールしなければ、当然ゲストOSは、正常に起動しません。また、OSの終了時に正常なシャットダウン手続きを行わなければ、仮想ディスクにインストールされたゲストOSは、物理サーバーで稼働するOSの時と同様、OS自体が損傷する可能性もあります。
一方、コンテナ環境では、ゲストOSに相当する分離された空間において、そもそも「マスターブートレコードに応じたカーネルを起動する」や「ランレベルに応じた起動スクリプトを使ってブートする」といったいわゆる物理マシン上での一般的な「OSのブート手順」を行いません。このため、コンテナ環境は、ハイパーバイザー型の仮想化基盤のゲストOSに比べ、オーバーヘッドが少ないため、コンテナの起動・停止が非常に高速であるという特徴があります。
また、ハイパーバイザー型の仮想化ソフトウェアは、ハードウェアをエミュレーションしているのに対し、コンテナ環境は、Namespaceとcgroupsと呼ばれる資源管理の仕組みを使うことで、単一のOS内で複数のコンテナがプロセスとして稼働するだけであるため、分離された空間に必要とされるOS環境(コンテナ)のコンポーネントや資源も少なくて済むといった特徴があります。したがって、Linuxコンテナは、KVMやXenなどのハイパーバイザー型の仮想化技術に比べて、CPU、メモリ、ストレージ、ネットワーク等のハードウェア資源の消費やオーバーヘッドが小さいため、集約率を劇的に向上させることが可能です。一般的に、コンテナ環境では、アプリケーションのプロセスがコンテナごとに分離されますが、ホストOS環境から直接実行されるため、コンテナ上のCPU利用は、ホストOSと同等の性能を発揮できます。また、ネットワークやディスクI/Oについても、わずかながらのオーバーヘッドは存在するものの、非常に小さくすることが可能です。
Namespace(名前空間)とは何か?
Dockerは、単一のOS環境において、複数の分離された空間を作成することができますが、その分離された空間を実現しているのがNamespace(名前空間)です。この名前空間は、プロセスでの分離を実現することができるため、例えば、ある分離された空間Aのプロセスは、別の分離された空間Bには見えないといった制御を実現します。また、名前空間は、プロセスだけでなく、ファイルシステムへのアクセスの分離も実現します。Dockerがコンテナを作成する際に、名前空間が作成されます。Dockerで利用される名前空間を以下にあげます。
ipc名前空間 | Inter-Process Communication名前空間と呼ばれます。内部的なプロセス間通信を分離します。 |
---|---|
mnt名前空間 | プロセスから見えるファイルシステムのマウント情報を分離し、chrootに近い働きをします。 |
net名前空間 | ネットワークの制御を行う名前空間です。net名前空間ごとにネットワークインタフェースを持つことができるため、複数のコンテナとホスト間でネットワーク通信を行うことができます。 |
pid名前空間 | プロセスの分離に使用します。カーネルが制御しており、親PIDによる子PIDの制御などに利用されます。 |
user名前空間 | ユーザーIDとグループIDを分離します。user名前空間内ごとに個別のユーザーIDとグループIDを保持することができます。 |
uts名前空間 | UTS(Unix Time-Sharing System)名前空間と呼ばれます。ホスト名やNISドメイン名などの分離に使用します。 |
これらの機能を使って、プロセスやファイルシステム、ユーザーIDなどが分離された空間を複数つくることでコンテナを実現しています。この分離された名前空間ごとにハードウェア資源を割り当てるのがcgroups(Control Groups)になります。Linuxに実装されているcgroupsは、主にCPU、メモリ、ディスク、ネットワークなどの各種デバイスを制御します。
[参考] 名前空間について
名前空間の分離については、以下のURLに解説があります。
https://docs.docker.com/introduction/understanding-docker/
http://lwn.net/Articles/531114/#series_index
[参考] chrootとLinuxコンテナ
Linuxでは、特定のディレクトリ配下をルートディレクトリに変更するchrootコマンドがあります。Linuxコンテナ環境において、特定のディレクトリ配下にあるディレクトリツリーは、起動したコンテナのルートディレクトリになりますが、複数のLinuxコンテナごとにプロセスを分離するのに対して、chrootは、プロセスレベルでの分離ではなく、あくまでファイルシステムレベルでの分離を実現します。Linuxコンテナは、プロセスレベルでの分離とファイルシステムレベルの分離を両方行いますが、chrootは、プロセスの制御はできず、ファイルシステムレベルでの分離を実現するため、主にホストOSにおけるレスキューモードを使ったシステム復旧の際に利用されます。
Dockerのポイント
- コンテナの仕組みにより、仮想マシンやゲストOSは存在せず、コンテナに作成されたOS環境の起動、停止は非常に高速であり、性能劣化が非常に小さい
- Dockerコミュニティの成果物を利用する仕組みが整備されており、OS環境やアプリケーションの再利用が容易
- 本番系システムを変えないイミュータブル・インフラストラクチャにおける重要な基礎技術である
- Linuxカーネルの機能である名前空間により、1つのホストOS上で、複数のコンテナによるマルチOS環境を実現する
- 名前空間とcgroupsが協調動作し、分離された環境に対して、CPU、メモリ、ブロックI/O等の資源の割り当てや制御を行う
- 2015年現在、様々なGUI管理ツールが乱立している