2016/12/09

VMware 環境で docker を使う

この記事は、vExperts Advent Calendar 2016 に参加しています。



● 非Linux でもコンテナしたい!


Docker はご存じの通り Linux 上で動作するコンテナ技術で、元々は Linux の OSパーティショニング技術を利用して実装されていました。Linux 環境で Linux のサーバソフトウェアを包んだコンテナを構築する場合はさして問題なかったのですが、利用が増えるにつれ、とくに利便性の面で課題が出てきました。

例えば、Linux サーバ上のアプリケーションを開発する場合でも多くの開発者はデスクトップ環境としては Windows や macOS など使い勝手のいいUIをもつ OS を使っているわけですが、これらの環境では、そのままでは Docker コンテナを実行することができません。


・Boot2Docker ~ Docker Toolbox ~ Docker for Windows/Mac


そこで、登場したのが Boot2Docker という一連のツールです。Boot2Docker は3つの要素、すなわち、

  • boot2docker という管理コマンド
  • 同名(boot2docker)の軽量な Linux のディストリビューション
  • Oracle VirtualBox

の組合わせになります。boot2docker コマンドを通じて、VirtualBox 上に仮想マシンを作成し、boot2docker をOSとして稼働させ、Docker によるコンテナを実行するというものです。仮想化が一段絡むぶん複雑化しますが、 Mac や Windows マシンで簡単に Docker を試せることから、コンテナの学習や開発、テストなどの用途で幅広く使われてきておりました。

この Boot2Docker を発展させたものが Docker Toolbox であり、さらに Docker for Windows, Docker for Mac というソフトウェアです。
いずれも Windows, macOS 向けに仮想環境と操作用のコマンドや管理用GUI などをまとめたものです。
Docker Toolbox は仮想化ソフトウェアとして VirtualBox を使用しておりますが、Docker for Windows では Hyper-V を、Docker for Mac では xhyve を使用しております。
なお、仮想マシン上のOSとしては継続して  boot2docker を使用しています。先にリンクした Boot2Docker のページなどでも、boot2docker はこちらの方、Linux ディストリビューションとしての側面の方が強くなっております。
( 注意: Docker Toolbox と、Docker for Windows/Mac は同一環境にインストールすることがサポートされておらず、Docker Toolbox を使うか、Docker for Windows/Mac を使うかどちらかの選択になります。 )

この、 DockerToolbox, Docker for Windows, Docker for Mac で boot2docker コマンドにかわって用意されているのが Docker Machine という Docker 純正のソフトウェアです。

Docker Machine もまた Docker コンテナの実行環境を操作するソフトウェアになります。boot2docker コマンドが VirtualBox を前提としていたのにたいして、Docker Machine はドライバーを通じて様々なクラウドや仮想環境と対話し、Docker を実行するための仮想マシンを準備することができます。

Docker Machine が対応している環境の一覧はこちらです。

Boot2Docker でも使われていた VirtualBox や Hyper-V といった仮想化ソフトウェアだけではなく、Microsoft Azure や OpenStack といったクラウドもあります。こうなると学習、開発用途を越えて、小規模なら運用環境を構築するのにも使えますね。

VMware 関連では、「vCloud Air」「VMware Fusion」「vSphere」がサポートの環境となります。ここでは、Docker Machine を通じて これら VMware の仮想マシン上で Docker を展開してみます。


● Docker Machine 入手方法


先の経緯から、Docker Toolbox や Docker for Windows, Docker for Mac には docker-machine コマンドが含まれております。これらを既にインストールしている場合は、それをそのまま流用することができます。ただ、今回はローカルで既にインストールされている VMware Fusion を使ったり、リモートの vSphere を利用するため、仮想化ソフトウェアが一緒にインストールされてしまうこれらは大仰とも言えます。

Mac の場合、homebrew というパッケージマネージャでは docker コマンドや docker-machine コマンドが用意されており、以下のコマンドで簡単にインストールすることができます。
brew install docker-machine
brew を使った docker-machine のインストール

また、パッケージマネージャを使わずとも、Docker 社の GitHub から直接バイナリをダウンロードして使用することも可能です。
curl -O https://github.com/docker/machine/releases/download/v0.8.2/docker-machine-Darwin-x86_64 sudo cp ./docker-machine-Darwin-x86_64 /usr/local/bin/docker-machinesudo chmod +x /usr/local/bin/docker-machine
(1行目のコマンドで macOS 用 docker-machine コマンドをダウンロード、2行目で管理者権限で /usr/local/bin 以下にコピー、 最後のコマンドで実行券を付けてます。これはこちらのサイトのインストールコマンドと意味的には同じです、1行で書いてないだけで。)

いずれにせよ、Mac の場合は「ターミナル」のウィンドウで、Windows の場合はコマンドプロンプトウィンドウにて docker-machine とだけ入力、実行してヘルプメッセージが出る、パスが通ってて実行可能になっている、事をご確認ください。


● VMware Fusion でコンテナを展開してみる


macOS で既に docker-machine と VMware Fusion がインストール済みの場合は、以下コマンドを実行すると、Docker コンテナの実行環境(仮想マシン)が作成され、自動的に実行されます。
docker-machine create --driver vmwarefusion <仮想マシン名>
コンテナを実行する仮想マシンを、docker-machine で作成、起動

このとき、インターネット上の boot2docker の iso イメージ(40MB弱)をインターネットからダウンロードします。その後、仮想マシンを作成、vmrun コマンドで仮想マシンを実行し、仮想マシンは iso イメージからブート、boot2docker を OS として起動します。

20GiBの仮想ディスクが作成されている

無事作成されたかは、以下のコマンドで確認できます。

docker-machine ls


なお、仮想マシンは実行されても、 VMware Fusion というアプリケーションそのものは起動されないのでご注意ください。VMware Fusion の仮想マシンの実体は vmware-vmx というプロセスで、VMware Fusion.app は仮想マシンを管理するGUIにすぎません。この VMware Fusion.app 内には、コマンドラインから仮想マシンを起動する vmrun というコマンドが含まれており、docker-machine はこちらを使う次第です。もちろん、VMware Fusion.app を起動すれば、docker-machine が作成した仮想マシンもライブラリに表示され、こちらから起動終了など操作をすることも可能です。

VMware Fusion.app を起動すると、仮想マシンが立ち上がってるのが分かる


デフォルトでは仮想マシンは 1vCPU, 1GB RAM の仮想マシンを作成、仮想ディスクサイズは 20GBとなっています。異なるサイズの仮想マシンを作成したい場合は、以下のドライバ特有のコマンドラインオプション、あるいは環境変数で変更できます。

コマンドラインでのオプション環境変数での設定デフォルト値
--vmwarefusion-boot2docker-urlFUSION_BOOT2DOCKER_URL最新のboot2docker の
URLが自動的に参照される
--vmwarefusion-cpu-countFUSION_CPU_COUNT1
--vmwarefusion-disk-sizeFUSION_DISK_SIZE20000 (単位MiB)
--vmwarefusion-memory-sizeFUSION_MEMORY_SIZE1024 (単位MiB)
--vmwarefusion-no-shareFUSION_NO_SHAREfalse
( https://docs.docker.com/machine/drivers/vm-fusion/ より引用)

さて、docker コマンドを使ってコンテナを実行してみましょう。docker コマンドは環境変数からどこで待機している dockerd と接続するかを決めることができます。そして、docker-machine はこの環境変数を作成してくれます。

docker-machine env

このコマンドだけでは、単に環境変数を表示するだけですが、以下のように実行することでその環境変数を現在のシェルにセットするのが定石です。
eval $( docker-machine env )
個人的には以下の方が好みです。(古い人間なので、bash独自仕様は、どうも...ね。)
eval `docker-machine env`

また、関数を用意して環境変数を設定したサブシェルを作るというのもいいかと思われます。

function dockersh() { ( eval `docker-machine env "$1"` && exec sh -i ) }

関数を定義。実際には .bashrc などに記載しておく
dockersh を使ってサブシェルを実行、環境変数がセットされているのを確認

こうしておくと、suspend コマンドでそのサブシェルを停止し、元のシェルに戻れます。docker-machine では複数のコンテナ実行環境を構築することができますので、それごとに dockersh でサブシェルを起動し、suspend で一旦抜けて、fg で戻るを繰り返すことで簡単にコンテナ実行環境を行き来できます。
(フェイルセーフを考えると、上記 dockersh 関数では、bash のコマンドプロンプトも操作してコンテナ実行環境の名前を入れておいた方がいいかもしれません。)
docker-machine で Fusion 上にもう一つ別のコンテナ実行環境用の仮想マシンを作成
このように、コンテナの実行環境をいくつでも作成できるのが docker-machine の便利なところだ
もちろん、ドライバーを変えることで Fusion 以外での環境も作成できる

ともあれ、コンテナの実行環境ができたら、あとは docker コマンドでコンテナを実行するだけです
docker コマンドで hello-world コンテナを実行してみた

なお、docker-machine で作成した仮想マシンはデフォルトでは ~/.docker/machine/machines フォルダに格納されます。通常の仮想マシンと位置が違うのでご注意ください。

作成した仮想マシンvm は、~/.docker/machine/macchines/vm フォルダに存在する

● vSphere 上でコンテナを実行してみる

Fusion の場合と同じように、docker-machine を使って vSphere 上に コンテナの実行環境となる仮想マシンを作成、制御することができます。

vSphere に対する場合は、ドライバとして「vmwarevsphere」を使用します。
docker-machine create --driver vmwrevsphere --vmwarevsphere-vcenter=<vc/esxi> --vmwarevsphere-username=<username> --vmwarevsphere-password=<passwd> <仮想マシン名>
--vmwarevsphere-vcenter オプションで捜査の対象となる vCenterServer ないしは ESXi のIPアドレスか、ホスト名を指定します。--vmwarevsphere-username と --vmwarevsphere-password でユーザ名、パスワードを指定します。なお、vmwarevsphere ドライバでは -username と -password は必須オプションとなり、オプションか環境変数で必ず指定する必要があります。実質的には -vcenter も必須と言えるでしょう。

docker-machine から vSphere に対して仮想マシンを作成

作成後の、ls での一覧と、env の内容表示
そのほかオプションについては、こちらに記載があります。Fusion でもあった仮想マシンのvCPU数、メモリサイズ、ディスクサイズ、boot2docker (iso イメージ)のURL から、作成した仮想マシンをどのネットワークに接続するか、どのデータストアに格納するか、どのリソースプールに入れるか、どのデータセンターに配置するか、それから起動時にどのホストで起動するか、などが指定できるようになっています。

● vSphere Integrated Containers との違いは?


ここまでで見てきたように、Docker コンテナを仮想化環境やクラウドで実行させるだけなら docker-machine があれば十分です。

一方、VMware 社は vSphere EnterprisePlus 購入者向けの無償製品として「vSphere Integrated Containers」(VIC) をオープンソースで提供しています。

VIC と docker-machine + vSphere ドライバーはどちらも vSphere 上での Docker によるコンテナ化されたアプリケーションの展開をおこないます。その点では同じです。

一方、以下の点で違いがあります。

・Boot2Docker vs. Photon OS with Instant Clone


docker-machine ではコンテナを実行するLinuxとして boot2docker を使用します。これはオープンソースで用意されており、isoメディアを見ても35MB程度と非常に軽量です。

一方、VIC は VMware 社が推進するコンテナ向けの Photon OS というディストリビューションを使用します。PhotonOS は軽量と言いますが、メディアサイズは 1GB程度と、boot2docker よりは大きくなります。
そこで、VICではこの PhotonOS を搭載した Linux VM を InstantClone で展開します。

InstantClone は VMfork と呼ばれる技術を利用したもので、「コピーオンライト」(COW)で仮想マシンを増やします。仮想マシンの作成時はCOWにより最低限の書き換えられたメモリ分だけが新たに消費され、ほとんどのメモリは「共有」された状態で起動します。ディスクについてもリンククローンのように差分ディスクを活用するため、極めて高速に Photon OS の仮想マシンを展開できるわけです。

InstantClone の詳細については、こちらの記事をご参照下さいませ。

注意点としては、InstantClone では透過的ページ共有が有効になります。これはセキュリティ上の理由から vSphere 5.5P04, vSphere 5.1U3 などからデフォルトで無効にされた機能です。InstantClone を使う VIC や Horizon View では、リスクがあることは理解しておくべきでしょう。

ともあれ、VICでは InstantClone によりコンテナを乗っける仮想マシンの展開速度は非常に敏速になります。
ただ、敏速になるのは展開速度だけのため、その恩恵は展開の頻度にもよります。

・管理を容易に


docker-machine ではコンテナを実行する環境(OS)を用意するまでで、その上にいくつコンテナを展開するかは利用者次第です。一方 VIC では1コンテナ1仮想マシンに決め打ちしております。InstantClone により高速に仮想マシンが展開できることもありますが、1コンテナ1仮想マシンにすることでサービスとVMの紐付けが単純化され、仮想化基盤の管理者からも分かりやすくなるという利点があります。vSphereClient(WebClient)で仮想マシンを管理するときや、NSXのマイクロセグメンテーションを適用するときにこれは便利と言えます。

1コンテナ1仮想マシンのため、vReailze Orchestartor での可視化の時もどのコンテナ(=仮想マシン)に負荷がかかっているかが分かりやすくなります。

さらに、Admiral というWebベースのUIも提供されており、より容易にマウスクリックでのコンテナ管理もできます。

こうした、vSphere の各管理製品との連携やUIの拡充も VIC の特徴になります。

・コスト


docker-machine は Docker 標準の管理ツールであり、これまで述べたように Windows/Mac 環境向けにOSSで無償提供されております。

VIC はオープンソースのソフトウェアでそれそのものは公開されていますが、実行するには有償の vSphere が必須となります。ESXi 単体の場合は vSphere Enterprise 以上、vCenter Server を使った集中管理された環境では vSphere EnterprisePlus 以上のライセンスが必要です。これは、こちらのページにも説明がありますが、Network Serial Port や分散スイッチと言った有償エディションでしか使えない機能を前提としているためです。

なお、サポート対象になるのは MyVMwareで公開されている公式リリースのバイナリのみで、オープンソースのコードを自前でビルドしたものはVMware社のサポート対象外になります。



また、個人的には国内でのサポート(認識)について少々不安が持たれます。

たとえば先日の vForum 2016 Tokyo の「VMwareとコンテナ技術の相乗効果とは」のセッションにて VIC の説明がおこなわれるはずでしたが、Docker の概要と 1VM1コンテナで便利、ぐらいの内容しかなく、ここで述べたような docker-machine との差別化はおろか、TPS が有効になるなどの重要情報もありませんでした。
( このセッション、冒頭でテスラの自動運転の話を延々とした割には「時間がないのでここまで」で切り上げており、ちょっとなぁという出來でした。セッション資料が非公開なのも当然かな、といったところです。)

VICのコンセプトや機能は決して悪くないだけに、残念な話です。



ともあれ、今後、コンテナ化されたアプリケーションは当然になってくるにあたり、コンテナをどう展開するか、どこで動かすかは重要になってきます。大規模環境なら DC/OS や Swarm のようなオーケストレーションツールが活躍するのでしょうが、とっかかりや開発環境、小規模な運用環境では docker-machine は十分に役に立つかと思われます。また、予算が潤沢にあるなら、vSphere EnterprisePlus の大規模なクラスタで VIC を使い、負荷分散は DRS に任せ、vRealize Operations で状態を可視化するのも有益でしょう。



2016/12/08

vSphere 上での Nano Server のインストール

この記事は、vExperts Advent Calendar 2016 に参加しています。


Windows Server 2016 では Nano Server と呼ばれる、軽量化されたOSが含まれています。Windows Server 2016 をベースに新しいアプリケーションやインフラストラクチャーを対象に、そのための機能に研ぎ澄ましたもので、稼働させるだけなら数百MB程度のメモリとディスクがあれば動きます。

Windows Server 2016 そのものも 512MB が最低必要量になってますが、インストール時には 800MB 程度、デスクトップエクスペリエンスを備えるならやはり 2GBが必要となります。ストレージ容量なら32GBが最低容量となります。

一方、Nano Server は「研ぎ澄まされ」ているため、用途としては不適となります。たとえばローカルコンソールで操作できることは本当に最低限のため、リモート管理が必須となります。役割や機能もフルインストールの Winodows Server がサポートするものが全てサポートされるわけではありません。ライセンスから見ても、アップデートがCBBモデルなのもありSAが必須となります。

こうしたことから、インストーラーでぽんとインストールできるわけではありません。

Windows Server 2016 のインストーラーでは、デフォルトのの Server Core か、
デスクトップエクスペリエンス付きかの選択肢しかない

むしろ、インストールしてから用途に向けてセットアップしていくのではなく、コマンドラインで
「必要な機能を組み込んでいく」必要があります。

インストール手順自体はこちらにありますが、少々敷居の高いものとなっています。
では、VMware の仮想マシン上にインストールするにはどうすればいいでしょうか? ちょっと試してみました。

● EFI か、BIOSか?

まず最初に決めるべき事は、ファームウェアを従来のPC-BIOSか、UEFIにするかです。PC-BIOS
はこれまで使われてきたファームウェアで、リアルモードで動作するものになります。UEFI はより新しいファームウェアで、ブート前の状態でより多くの機能を提供できるものです。

Nano Server をインストールするにはどちらでも構いません。多くの VMware 製品は普通に仮想マシンを作ると PC-BIOS を設定します。VMware Fusion については macOS をゲストOSにしない限り、EFI は選択されません。(ユーザーインターフェイスから設定できない。ただし vmx ファイルを直接書き換えることで設定可能)

ここでは、最初に BIOS でのインストールを、次に EFI でのインストールを試してみます。

● Nano Server のインストール (BIOS編)

まず、仮想マシンを作成する。特に普通に作れば良い。今回はメモリは 1GB程度にしました。
仮想ディスクのサイズも1GB以上ならば問題ありません。

ESXi の仮想マシンのプロパティ
「リソース」の「起動オプション」にてファームウェアの指定が可能


注意点としては、ゲストOSとしては「Windows Server 2016(64bit)」を選択すると言うことぐらいです。

仮想マシンの作成画面より
OSは Windows Server 2016 (64bit) にする

できあがった仮想マシンに Windows Server 2016 のインストールメディアを認識させ、こちらから起動します。
Windows Server 2016 のインストールメディアから起動
通常はここでキーボードや言語の選択を行いウィザードを進めるが
Nano Server の場合はここで一旦停止

この画面が表示されたところで「SHIFT+F10」をおす。すると、コマンドプロンプトウィンドウが開きます。

Windows Server のインストールメディアでは、SHIFT-F10 でコマンドプロンプトウィンドウが開く
ここでは、D: ドライブの内容を dir で確認している

デフォルトの状態では、X:ドライブに一時的な起動ドライブが作成されております。インストールメディア自体はD:ドライブにマウントされており、初期状態では仮想ディスクはフォーマットもされていないため、どこにもマウントされていません。
D:\NanoServer フォルダ以下に、Nano Server の素の状態のイメージ(NanoServer.wim) と、デバイスドライバや役割、機能を備えたパッケージ(*.pkg)があります。


さて、ここからインストールを行います。インストールで行わなければならないことは、以下の4つです。

  1. ディスクのパーティション作成と、フォーマット
  2. Nano Server イメージの展開
  3. その他必要なパッケージのインストール
  4. 起動パーティションとして指定

・パーティションの作成

パーティションの作成とフォーマットは diskpart コマンドで実施します。まず、「diskpart」と入力し実行して、diskpart コマンドを起動します。このとき、「DISKPART>」のプロンプトが出ずハングする場合があります。その時は Ctrl-C をおして diskpart コマンドを終了し、しばらく待ってから再度実行するとプロンプトが出てきます。

diskpart コマンドを実行

DISKPART> のプロンプトが出たら、以下のコマンドを実行します。
  • select disk 0
  • create partition primary
  • format quick fs=ntfs label="nano server"
  • assign letter=c
  • active
select disk 0 で接続されている最初のドライブを選択します。
次の create partition で選択されたドライブに新しいパーティションを作ります。このとき、 primary を指定することでMBR のプライマリパーティションとしてパーティションが作成されます。
(MBRでは、そのままだと最大4つのパーティションしか作成できない。これらを「プライマリパーティション」と呼ぶ。4つ以上パーティションが必要な場合は、そのうちどれかを入れ子にして、別途パーティションテーブルを作成、分割する。この入れ子で作成されるパーティションを「論理パーティション」と呼ぶ )


上記コマンドに従い、パーティションを作成、フォーマットを実行
最近?の diskpart では、作成したパーティションが選択された状態になっているので、そのまま fomat コマンドを実行することで作成したばかりのパーティションをフォーマットします。fs=ntfs でntfsを選択、ボリュームラベルは nano server を指定、quick を付けることでクイックフォーマットを行ってます。
assign letter=c で、このパーティションを「C」ドライブと名付けます。名付けた時点で C: でアクセスが可能になります。

最後が重要です、active を実行することで、MBRに「このパーティションから起動する」という指名をします。この操作をしていないと、起動パーティションが分からずブートに失敗しますので注意してください。

起動パーティションを指定
list partition で先頭に*があるのがそれだ


終わったら、DISKPART> のプロンプトで exit を入力する、もしくは Ctrl-C で終了できます。

・Nano Server イメージの展開

空のC:ができたところで、ここにOSのイメージを流し込みます。
まず、カレントディレクトリを d:\NanoServer に移動しておきます。

ここで、以下コマンドを実行します。少々長いので打ち間違いに気をつけてください。

  • dism /apply-image /imagefile:.\NanoServer.wim /index:1 /applydir:c:\

dism コマンドでWIMイメージを展開

dism.exe は WindowsVista から用意された、Windows の展開イメージの管理コマンドです。インストーラーが使用する WIM形式のイメージや仮想ディスクイメージである VHD/VHDX形式、それからディスクに展開された Windows のシステムを管理することができます。

ここでは、imagefile で指定した WIM形式のイメージを applydir で指定したパスに書き出しています。/index:1 は、WIMイメージの2つめのボリュームを対象にしていることを指します。このWIMイメージの中にはEFIシステムパーティションがあるので、C: に相当するのは二つ目の(0オリジンで1の)ボリュームだからです。

dir c: とかすると、Program Files や WINDOWS など、おなじみのフォルダが展開されているのが分かります。

・その他必要なパッケージのインストール

このままでは Nano Server そのものしかインストールされておらず、起動する以上の意味を持ちません。追加のデバイスドライバや役割、機能をここでインストールします。

CABパッケージの追加インストールには、dism /add-package を使用します。
パッケージは d:\NanoServer\Packages フォルダの下に格納されております。

ここでは、d:\NanoServer\Packages フォルダにカレントディレクトリを移動させた後、Microsoft-NanoServer-OEM-Drivers-Package.cab を追加しています。

  • dism /add-package /packagepath:.\Microsoft-NanoServer-OEM-Drivers-Package.cab /image:c:\

add-package ではインストール先の「システムイメージ」を指定しますが、ここでは c:\ 以下に展開されたイメージが対象のため、c:\ としています。

パッケージを追加
警告が気になる場合は、2GB以上のディスクを用意する事

ここではディスク容量が小さく作業領域(ScratchDir)が小さいせいで警告が出ています。確かに、今回ディスクサイズを1GBにしたので、イメージを展開した分容量が取られており、空き領域が 1GBを切っています。仮想マシンのディスクサイズをそもそも2GB程度にすればこの警告は生じませんし、今回のように強行しても、1個ぐらいのパッケージなら問題なく展開できたりもします。

VMware 上の仮想マシンの場合、この Microsoft-NanoServer-OEM-Drivers-Package.cab は必ず入れてください。この中に LSI Logic の SCSIドライバなども含まれているため、このパッケージを追加しないと、OS起動後に C:ドライブをマウントできず、BSODになります。

その他の役割については、こちらのページを参照してほしい。「Creating a custom Nano Server image」の項目にある表が、概ね機能と対応するパッケージになります。厳密にはこの表は、事前にパッケージを組み込んだ NanoServer.wim を作るために使用する New-NanoServerImage コマンドレットの引数になってますが、たとえば Hyper-V の役割をインストールするための「-Compute」なら、「Microsoft-nanoServer-Compute-Package.cab」とか類推がつくかと思います。

また、c:\NanoServer\Packages フォルダの直下だけではなく、言語ごとのフォルダもあります。日本語の場合、c:\NanoServer\Packages\ja-jp というフォルダがあり、同名のパッケージがあるのでこちらもインストールしておいてください。
(ただし、NanoServer のコンソール画面は英語しか表示できないため、ローカルコンソールでの日本語関係は化けてしまいます。)

・起動パーティションとして指定

さて、最後に起動パーティションとして指定します。これは、bcdboot コマンドを使用します。

  • bcdboot c:\Windows /s c:

bcdboot でブートローダーの設定を作成


bcdboot.exe もまた WindowsVista から導入されたコマンドで、winload によるOS起動を制御します。ここでは、c:\Windows から Windows  を起動することを指定しています。その設定は c: に、つまり同じドライブに書き込まれます。

実のところ、これはちょっとした手抜きです。Windows をGUIからインストールした場合は PC-BIOS の場合も先頭に100MB程度のシステムパーティションが作成され、こちらに OS起動の設定が書き込まれます。UEFIの場合、EFIシステムパーティションが必須であり、こちらで認識する必要があるから別パーティションを用意する必要はあります。

一方、PC-BIOS の場合はその必要性はさしてないですし、仮想マシンの場合固定したOSを固定したパーティションから起動する、せいぜい起動オプションを変えたモードを用意するぐらいですので、これでも問題ない、という判断からです。
なお、Microsoft のページでも、「不要なら削除して構わない」となってます。

気になる方はシステムパーティションを作成し、/s の指定先をそちらにした方が良いでしょう。

bcdboot で設定が正しく書き込まれたかは、bcdedit コマンドで確認できます。
  • bcdedit /store c:\Boot\BCD
bcdedit コマンドでブートローダーの設定を確認
bcdedit 単体で実行すると、現在起動したOS(この場合はX:)の設定を表示するため、
ここでは /store でどこにある設定を読み込むかを指定している

Windows ブートマネージャー の項目が、ブートマネージャーそのものの設定、たとえば表示言語(ここではen-us)などが表示されます。ブートマネージャーの default に表示されている Identifier の項目が起動時に使われます。また、次の displayorder に複数の Identifier が表示されている場合、この順でメニュー表示され、どの設定から起動するかを選択することができます。メニューを表示して何秒待ったら起動するかは、timeout に設定されます。

ここでは {default} という Identifier の設定が一つだけ、 Windowsブートローダーの項目に表示されています。

詳細な内容については、こちらのページもあわせてご参照ください。


さて、これで準備は終わりました。コマンドプロンプトウィンドウを閉じて、下のインストーラーのパネルを閉じる事で再起動されます。または、コマンドプロンプトウィンドウから「wpeutil reboot」コマンドを実行する事でも再起動が行われます。

再起動後、HDDから起動が行われ、Nano Server が起動してきます。

Nano Server 起動中
ブートローダーはフルインストールと同じためここだけはグラフィカルだ


Nano Server 起動。
本当に何のUIもなく真っ黒だった 以前のTPと異なり、
TP5やリリース版では最低限のUIはついた。本当に最低限だが

初期状態では Administrator にパスワードが入っていませんので、ユーザ名に Administrator を指定してリターンをたたくと、初期パスワードを入力を要求されます。

ここで Administratror のパスワードを設定

DHCPから採取された IPアドレスなどは画面に表示されるので、あとはRSATを使って管理する、または SMTを使って管理するなどで、Nano Server を扱うことができます。
( Azure 管理コンソールで Windows Server もまとめて管理できる SMT は、マイブームだったり(笑) )

Networking を選択、リターンを押すとIPアドレスの設定が確認できる

● EFI の場合は?

PC-BIOS と EFI で異なるのは、ブートの手順になります。
BIOSの場合は、MBR に記載されたシンプルな一次ブートローダーがアクティブに指定されたパーティションの二次ブートローダー、つまりは winload を呼び出し、winload が bcdboot で記入した設定を読み込み、ブートします。MBR に入れることができるブートローダーはリアルモードかつ容量も限られているので、winload そのものを入れるのではなく、二段構えになっています。

EFI の場合は、 EFI システムパーティションに組み込まれたブートローダーがOSを起動します。Windows の場合は EFI に winload が存在し、これが Windows を起動します。EFIシステムパーティションは100MBないしそれ以上あり、EFIがブートローダーに提供する機能も BIOS に比べ張るかに高機能なことから、winload が直接利用できるわけです。

このことから、二つの部分がかわってきます。
一つはパーティションの作成。GPTパーティション形式にした上で、EFIシステムパーティションを用意する必要が出てきます。
二つ目は、bcdboot での指定。BIOSの場合は winload も bcdboot の設定も c: にごっちゃに入れてましたが、EFI の場合は /s で指定する格納先は EFIシステムパーティションになります。

では、手順を見てみましょう。

最初に重要なのは、仮想マシンを作成したら「ファームウェアをEFIにしておく」事です。ゲストOSの設定にもよりますが、Windows Server 2016(64bit)を選択してもデフォルトはBIOSになってます。

仮想マシンのプロパティの「オプション」「起動オプション」で
ファームウェアをEFI にして、OKを押す
そこからインストールメディアで起動し、diskpart を起動するところまではBIOSとわりません。

Windows Server 2016 のインストールメディアから起動
ここからコマンドプロンプトウィンドウを出すところは同じ

実行する DISKPART のコマンドが少し変わって、以下になります。
  • select disk 0
  • convert gpt
  • create partitoin efi size=100
  • format quick fs=fat32 label="System"
  • assign letter=s
  • create partition msr size=128
  • create partition primary
  • format quick fs=ntfs label="nano server"
  • assign letter=c

select disk0 で1本しか繋いでいない仮想ディスクを選択するところまでは一緒です。
次の convert gpt でパーティションの記録形式をデフォルトのMBR形式から EFI で使用する GPT パーティション形式にしておきます。

次に、create partiton efi で、EFIシステムパーティションを作成しておきます。GPTパーティション形式では、内部的には UUID でそのパーティションがどういうものかを記録しております。が、一々 長い UUID を入力するのは人間業では辛いので、「efi」というシンボルで EFIシステムパーティションであるというUUIDを入れてもらっている訳です。なお、size=100 は 100MiB のサイズで確保する事をさします。create partition でサイズ無指定だと開いてる所全部、となります。

その後、FAT32形式でフォーマットします。EFIシステムパーティションの実体はFAT32のため、FAT32でフォーマットする次第です。ボリュームラベルは Windows のデフォルトインストーラにあわせて「System」にしています。

また、ここでドライブレター「S」を割り当てております。EFIシステムパーティションはOS起動後はマウントされない、不可視のものですが、ここではBCDの起動設定を入れなければならないので、邪魔にならないところにマウントしている訳です。

EFIシステムパーティションの作成。
なお、EFIシステムパーティションを略してESPと呼ぶこともあります。
続けて、「create partition msr size=128」で MSR を128MiBで確保してます。MSRは、Microsoft 予約パーティションの略で、他のシステムパーティションに関する情報が格納される、とあります(どうも、Reserved の R ではなく Recovery の R ではないのか?って気はするけど、さておき。)

ともあれ、EFIシステムパーティションの次、C: ドライブとなる Windows パーティションの前に配置することになってます。これはパーティションが存在すれば良く、フォーマットしたり一時的にドライブレターを割り当てて中に何かかき込む必要はありません。

さて、三つ目がプライマリパーティションで、要は Windows をインストールするパーティションです。パーティション作成後、NTFSでフォーマットして、C:をアサインしてます。

なお、BIOSでの起動(MBRパーティション形式)の時と異なり、active でアクティブパーティションを決める必要はありません。EFIは必ず、EFIシステムパーティションを見に行き、そこのブートローダを利用する、どのパーティションから起動するというのはブートローダ側の仕事となっているからです。
続き、MSRとC:ドライブを作成

WIMイメージからの展開と、ドライバーなどのパッケージの導入はBIOSの時と同じです。

さて、ブートローダの設定がBIOSの時とはまた変わってきます。

今回、実行するコマンドは以下になります。

  • bcdboot c:\Windows /s s:

WIMイメージの展開、パッケージの導入の後、bcdboot で起動ドライブを設定

起動するOSとして c:\Windows を指定するところまでは同じです。が、その後、ブートローダの設定をかき込むのは EFIシステムパーティションである s: ドライブになります。
その後の bcdedit での確認も、以下になります。

  • bcdedit /store s:\EFI\Microsoft\Boot\

EFIシステムパーティションでのブートローダなどは、ルートのEFIフォルダに格納されます。Windows のブートローダーwinload の設定は EFI\Microsoft\Boot 以下に記載される訳です。これはBIOSの時の\Boot\BCD とパスが違うので注意です。

さて、あとはシャットダウンして再起動するだけで、BIOSの時と同じように起動してきます。
一応、EFIから起動した Nano Server...別にBIOSの時と変わらないのですが。
BitLocker などを使わない限りは別にEFIでもBIOSでもOS起動後の動作は変わらないですし、そもそも vSphere では TPMが使えない(仮想TPMが存在しない...これも何とかしてほしいのですが)ので、ことさら EFI にする必要はない、といえます。

.

2016/12/01

Pico process

とある事情で少々調べたので、ここにメモしておく。

だいたいの元ネタは、以下のページになります。
https://blogs.msdn.microsoft.com/wsl/2016/05/23/pico-process-overview/


● PE と ELF

Windows は Portable Executable (PE)という実行ファイル形式をサポートしている。逆に言えば、PE形式のバイナリしか起動させることができない。NT系の Windows では、環境サブシステム(Environment Subsystem) という名前のパーソナリティを、NT Executive というマイクロカーネル上に複数実装できるようになっており、実際に OS/2, POSIX, Interix などのサブシステムが存在した。

しかし、実はこれらの、Win32とは異なるサブシステム上のバイナリも、実質的に PE形式のバイナリ(OS/2については変種だが)を実行するものであった。Service for UNIX の UNIXコマンドも PE形式だったわけだ。

一方、Linux は ELF形式のバイナリを実行するようになっている。

Windows Service for Linux (WSL) が Ubuntu のバイナリを無変更で実行していると言うことは、とりもなおさず ELF形式の、本来実行できないバイナリを実行していることになる。

これはどうやって実現しているのだろうか?

● pico process

WSL のキモが、この pico process を使った ELF バイナリの実行だ。
pico process というものは Microsoft Research で開発された Drawbridge より持ち込まれた、より軽量なプロセスを指す。下図の右側が通常の Windows でのアプリケーションプロセスだ。

NT Process, Minimal Process, Pico Proess
https://blogs.msdn.microsoft.com/wsl/2016/05/23/pico-process-overview/  より抜粋

Windows のカーネルは、アプリケーションの起動時、アプリケーションが必要とするメモリを確保した後、アプリケーションの実行に必要なモジュールをそのメモリ内にロードする。全てのプロセスで共通の NTDLL.DLL や、アプリケーション間で共有されるユーザの情報、スレッドが実行するのに必要な情報(TEB)等々だ。もちろん、アプリケーションのバイナリやDLLもこのプロセス内に展開される。アプリケーションが実行をはじめた時には、アプリケーションが必要な情報はメモリに全部用意された状態になっている。

これは便利だが、言い換えれば、Windows のお仕着せの方式でメモリが利用されてしまっている。何らかの理由でメモリ上の位置を最初から変えておきたい場合、これは不都合が多い。

Windows10 では、Minimal Process と Pico process というこれまでとは違うメモリの使い方をしたプロセスを用意した。


Minimal Process はメモリ内のお仕着せの準備を一切やめた。プロセスが用意されたときはメモリはすっからかんで用意される。スレッドも用意されないので、このプロセスはほっとくとメモリを食ってるだけでCPUがスケジュールされず、つまり実行されない。それ以前に実行すべきプログラムもメモリ上に展開されていないのでCPUが割り当てられても実行することができない。
ただ、環境サブシステムなど特権的なプロセスはこのメモリ内に色々書き込むことができる。適切なコードを割り当て、スレッドを作れば実行もできるようになる。通常の Windows のアプリケーションとは別種のものを実行しつつ、最低限の管理は NT カーネル 側で実施されるわけだ。
Windows10 では、メモリ圧縮や「Device Guard」「Credential Guard」といった仮想化を利用したセキュリティ機能で、この Minimal Process が利用されている。


Minimal Process はメモリはすっからかんでも、特定の手順(システムコール)でOSを呼び出させば、他のアプリケーションと同じく Windows のOSの機能を呼び出すことができた。
Windows も Linux も、最近の x86-64 (x64) の OS では、CPU のもつ sysenter もしくは syscall という命令を使用する。呼び出したいシステムコールの番号をCPUのレジスタに記録、指定したあと sysenter 命令を実行する。sysenter を実行した瞬間にアプリケーションは停止、各OSのカーネル側に処理がうつり、CPUのレジスタの中を見てアプリケーションがどのシステムコールを呼ぼうとしたか、どういうデータをわたそうとしたかを確認、処理を行う。ただ、どのシステムコール番号がどの処理に対応しているかとか、そもそも処理の有無や機能がOSごとに異なっているわけだ。


通常のプロセスでも Minimal Process でも、sysenter 命令が実行された場合の処理は同じ NTカーネルが担う。

一方、Pico Process では、Pico Provider と呼ばれるカーネルのモジュールが sysenter 命令の処理を行う。Windows に代わってお仕置き...ではなく対応を行うわけだ。WSL の場合、カーネルに組み込まれる LxCore.DLL, LXSS.DLL のどちらか(多分 LxCore)が Pico Provider になっている。ここには Linux のシステムコールが「そのまんま」実装されている。つまり Windows のシステムコールではなく、Linux のシステムコールの番号として判断され、適切な処理が呼び出される。


● bash 起動から、Linux コマンドの実行まで

bash.exe をアイコンから実行すると、これはただのコンソールアプリケーションのため、コマンドプロンプトウィンドウが開き、その中でコマンドが実行される。LxCore, LXSS が必要に応じてNTカーネルに読み込まれ、LxssManager が起動される。

(多分)LxCore が pico process を生成し、(多分)LXSS とサービスとして起動される LxssManager が協力してファイルシステムにある ELF形式の init や bash のバイナリを読み込み、すっからかんのプロセスメモリ内に「さもLinux のように」展開を行い、スレッドを作ってCPUを割り当てる。通常の命令はCPUによりそのまま実行される。


ファイルを読み込んだりテキストを出力を試みると、これはOSの力を借りることになるのでシステムコールが呼ばれる。このとき、sysenter の結果は NTカーネルではなく(多分)LxCore が引き取り、Linux のシステムコールとして処理がなされる。簡単なものなら (多分)LxCore に記述された Linux と同じ処理が行われて、結果が pico process に返される。コンソールへの出力の場合は、LXSS 経由で LxssManager が呼び出され、bash.exe にわたされ、コマンドプロンプトウィンドウに出力がなされる。


Linuxのバイナリは何一つ書き換えられることなく、Linux カーネルの上で実行されていたのと同じように、Windows10 のNTカーネル+LxCore+LXSS の上で実行、できてしまうわけだ。


2016/05/15

Fusion 上の仮想マシンのネットワークとパケットキャプチャ


Fusion 上の仮想マシンは、通常、以下3種類のいずれかで外部ネットワークと接続している

NAT :  仮想的なスイッチに接続、外部とはアドレス変換(NAT)を通して接続
ブリッジ: 指定のNICをホストOS(Mac)と共有、NICを通じて直接接続
ホストオンリー: ホストOS(Mac)とだけ接続

デフォルトでは、NATのネットワークは VNET8, ホストオンリーは VNET1 と定義されており、OS X 側の vmnet8 というインターフェイスが VNET8 に接続、vmnet1 が VNET1 に接続されている。

VNET8 については、さらに vmnet-dhcpd と vmnet-natd が起動しており、それぞれ DHCPによるIPアドレスの割り当てと、NATの制御を行っている。

VNET1 は vmnet-dhcpd のみが起動しており NATが行われない。このためホストOS(Mac)としかつながらない。

Fusion の仮想ネットワーク構成
なお、Fusion Professional ではVNET1.8以外のネットワークをカスタム構成できる
さて、仮想マシンがどういったパケットを送出しているかを確認したいときがある。
OS X にはデフォルトで tcpdump が用意されているので、ターミナルから以下のように実行することでパケットのキャプチャを行うことができる
sudo tcpdump -i vmnet8 port 80
なお、Fusion 8.0.1 まででは上記のコマンドではパケットキャプチャができず、以下のように pktap デバイスを併用する必要があった。(こちらのブログに詳しい説明あり)
sudo tcpdump -k pktap,vmnet8 port 80
これは VMware の提供する vmnet デバイスが tcpdump などパケットキャプチャツールが使用する Berkley Packet Filter (BPF) をサポートしていなかったためだ。

この問題は Fusion 8.0.2 にて解消されている









2016/02/06

vExpert 2016 受賞しました

転職したのもあって今回ばっかりは無理かなぁと思ってましたが、なんとか今年も vExpert 2016 を受賞できました。ありがとうございます。

http://blogs.vmware.com/vmtn/2016/02/vexpert-2016-award-announcement.html

2016/01/31

Fusion でリカバリモードで起動する

VMware Fusion 上の OS X でリカバリモードでの再起動をおこなう場合だが、KBによると実機のOS Xと同じく、起動画面で Command-R を押すといいとある。

しかし、実際に試すとこれがなかなかうまくいかない。VMware の提供する EFIの BootManager が表示されてしまう。もっと確実に起動できる手順はないか、ということで行ったのが次の方法だ。

まず、EFI の BootManager を表示させる。これは、Command-R を押しながら起動して失敗した場合でもいいし、「ファームウェアをパワーオン」を使ってもいい。


ここで、「Enter Setup」を選択する


次の画面で「Configure Boot Option」を選択する


さらに、「Add Boot Option」を選択する

3番目に「Recovery HD」があるはずなので、これを選択する。
なお、OS X をインストールすると三つのパーティションが作られる。一つが EFI システム領域、一つが OS X そのもののインストール領域、そして最後が Recovery HD だ。

選択したパーティション内のファイル一覧が表示される。


ここでは、<com.apple.recovery.boot> フォルダを選択


し、その中の「boot.efi」を選択する。

boot.efi を使った起動の設定画面が表示されるので、「Input the description」を選択、この設定の名前を入力する。ここでは、「Recovery HD」とした。


その後、下の Commit changes and exit を選択し、元のメニューに戻る。


さらに、Exit the Boot Maintenance Manager を選択、元の起動メニューに戻る。


すると、先ほど作った「Recovery HD」がメニューに増えているのでこれを選択する。

後は起動を待つだけだ。
起動に時間がかかるので待つべし

起動してしまえば、実機のリカバリモードと同じように使用できる。


なお、二度目からはメニューに登録されているので、単に「ファームウェアをパワーオン」を選択、Recovery HD を選ぶだけになる。