はじめに
開発をしていてDockerのような仮想化技術に触れることはよくありますが、どのようにして仮想化を実現しているのかを理解していなかったので調べてみました。
概要
- 前提
- 仮想化
- 仮想化技術の種類
- ハイパーバイザー型(タイプ1ハイパーバイザー)
- ホスト型(タイプ2ハイパーバイザー)
- コンテナ型
- Windows で Docker Desktop を実行する時の仕組み
前提
これから仮想化について解説する上でいくつか出てくる単語があるため、本項で意味を定義しておきます。
- 物理サーバー
- ホストOSがインストールされている物理的なサーバー
- ホストOS
- 物理サーバーにインストールされているOS(一般的なPCでいうWindows OS や Mac OS等)
- ハイパーバイザー
- 仮想サーバー(VM)を作成/実行するソフトウェア
- 仮想サーバー(VM)
- 物理サーバーの余剰リソースを使用して作成されるサーバーおよび仮想環境
- ゲストOS
- 仮想サーバー上にインストールされているOS
※引用
仮想化
仮想化はソフトウェアの開発で使用される手法であり、一つの物理サーバーの上で「仮想的に」サーバーを構築するという技術を指します。
Windows PC上でのWebアプリケーション開発を例に挙げると、Webアプリとして「Webサーバー」「アプリケーションサーバー」「DBサーバー」が必要になりますが、これらのサーバーを物理的に用意するのではなく一つの物理サーバー(Windows)上で仮想的に(WebサーバーやDBサーバーを)構築するようなイメージです。
専用のサーバーを用意する必要がないため、サーバーの費用や電力、物理的なスペースなどのコストを削減できることがメリットになります。
仮想化技術の種類
仮想化技術には主に
- ハイパーバイザー型(タイプ1ハイパーバイザー)
- ホスト型(タイプ2ハイパーバイザー)
- コンテナ型
の3種類が存在し、次項でそれぞれの違いを見ていきます。
ハイパーバイザー型(タイプ1ハイパーバイザー)
ハイパーバイザー型(タイプ1ハイパーバイザー) は、ハイパーバイザーが物理サーバー上で直接動作し、その上に仮想サーバーを構築します。
- ホストOSを必要とせず、本来役割を担っているホストOSの代わりにハイパーバイザーがハードウェアを直接制御するため、仮想マシンのパフォーマンスが上がる
- 複数の仮想マシンを効率よく稼働させるための仕組みがある
- 例:Microsoft Hyper-V, VMWare ESX-i, Linux KVM
ホスト型(タイプ2ハイパーバイザー)
ホスト型(タイプ2ハイパーバイザー) は、ホストOSのソフトウェアとしてハイパーバイザー(等の仮想化ソフトウェア)が実行され、その上に仮想サーバーを構築します。
- ホストOSの上にソフトウェアとしてインストールして使用するため、設定がシンプル
- ハードウェアへのアクセスはホストOSを経由して行われるため、余計なオーバーヘッドがかかる
- ホストOSは仮想マシンに対してハードウェアリソースの割り当て管理をしているため、仮想マシンが増えるとホストOSの負荷が懸念される
- 仮想マシンごとに、ホストOSとは異なるゲストOSをインストールできる
- 一般的なデスクトップOS上で動作するため、個々の環境でテストや開発がしやすい
- 例:Oracle VM VirtualBox, VMware Palyer, VMWare Fusion
コンテナ型
コンテナ型の場合はゲストOSを必要とせず「仮想マシン/仮想サーバー」を構築しないため、ホスト型・ハイパーバイザー型とは全く異なる概念となります。
OSの機能はホストOSに依存しているため、そのホストOS(Linuxカーネル等)が利用するアプリケーションを実行するための環境をコンテナごとに管理し、コンテナは「コンテナエンジン」というソフトウェアで動作します。
そのためコンテナはあくまでもアプリケーションを実行する役割となり、サーバーの中核機能(OSの機能)はホストOSへ任せることになります。
- ゲストOSが不要であるコンテナではホストOSのカーネルを共有して動作するが、各コンテナには必要なライブラリやバイナリ等(bin/lib)のユーザー空間が含まれ、これがアプリケーションの実行に必要な最低限のOSコンポーネントを提供する
- そのためOSのコア機能(カーネル)はホストOSに依存し、独立したユーザー空間だけがコンテナごとに用意される(Docker Engineを実行する場合、WindowsではWSL2、MacではLinuxKitがホストOSにあたる)
- ホストOSのみで動作するため、リソースの消費量が少なく動作速度も速い
- ホスト型やハイパーバイザー型のように、ホストOSと異なるOSを持つ仮想マシンを稼働させることができない
- 例:Docker, Kubernetes, LXC(Linux Containers)
前回の記事「ディストリビューションってなんじゃ」 に関連することですが、
DebianやUbuntuのようなLinuxのディストリビューションをコンテナにインストールすることで、ホストOS(WSL2)のLinuxカーネルがそのディストリビューションに含まれるソフトウェアを利用するようになるため、これら全体がLinuxサーバーとなります。
Windows で Docker Desktop を実行する時の仕組み
Dockerはコンテナ型仮想化の技術を使用しています。
WindowsやMacでDockerを使用するためのアプリケーション「Docker Desktop」で実行されるDocker Engine(コンテナエンジン)は、元々Linux向け(LXC: Linux Containers)に開発されているため、動作環境(ホストOS)にLinuxカーネルが必要になります。
Windows(やMac)ではホストOSがLinuxではないため、このままでは実行できません。
そのためにWindowsでは WSL2(Windows Subsystem for Linux) というLinux VM(Linuxの仮想化ソフトウェア)が用意されており、Docker Engineの実行はWSL2が行うことになります。
Mac ではHyperKitが用意されています。
一見、ホストOS(Windows)上で仮想化マシンのようなソフトウェア(Docker Desktop)を実行しているように見えたため、「ホスト型仮想化なのでは?」と思ったのですが、
Docker Engineを実行しているのはWindowsではなくWSL2であり(厳密にはDocker Desktopのアプリケーション自体はWindowsが実行し、Docker Desktopの内部で実行されるDocker EngineをWSL2によって動作させる)、その WSL2という仮想化ソフトウェアを実行しているのがMicrosoft Hyper-V(ハイパーバイザー) のため、仕組みとしては ハイパーバイザー型 に分類されるのです。
- Hyper-Vの有効化+再起動後は最初にハイパーバイザーが起動し、親パーティションとしてHyper-V上でWindowsを起動する。ハードウェアリソースの管理をHyper-Vが行うようになる
- DockerDesktopはWindowsによって実行される
- Docker Desktop内部で動作するDocker EngineはWSL2で実行される
- WSL2はHyper-Vで実行される(厳密には親パーティションであるWindowsの子パーティションとして実行)
WindowsでHyper-Vを有効化した後に再起動すると、最初にハイパーバイザーが起動し、Windowsは親パーティションとしてハイパーバイザー上で動作するようになります。
親パーティションであるWindowsはハイパーバイザーを介してハードウェアにアクセスし、仮想マシンの管理を行います。
そしてハイパーバイザー上の親パーティションは、子パーティションとして仮想マシン(今回の例ではWSL2)を管理します。
※WSL2は一般的に子パーティションとして扱われるHyper-V仮想マシンとは異なり、ファイルシステムの共有やネットワーク設定の面でWindows向けに最適化がされている特殊な仮想マシンだそうです。
Hyper-VはWindows10以降にデフォルトで導入されている、ハイパーバイザー型の仮想化プラットフォームです。
最後に
もやもやを解消しようと調べだした途端に色々な点で躓いて、書くのを諦めようかと思いながらもなんとかまとめられました。
同じような境遇の方の手助けになれたら幸いです。