2017/08/31

仮想マシンとハードウェアクロック

PCの中には時間を刻むハードウェアが内蔵されており、今が何月何日の、何時何分何秒かを把握しております。歴史的な事情からこのハードウェアは単一ではなく、複数のものが存在していたりします。かつては RTC (Real Time Clock)という仕組みだけでしたが、これがあまり精度が良くなかった、使い勝手が悪かったなどの理由で HPET が登場し、CPU には TSC というタイマーが用意されたのでこれを使って時刻を図ることが行われ、また ACPI には ACPI PMT というこれまた時間を計る機能が存在します。

ともあれ、OS は起動時にPCハードウェアのこれらの時計から時間を取得、カウンターを利用して、取得後どれぐらい経過したかを知り、OS自身で時間を管理しております。
例えば Linux の場合は、OSの終了時に hwclock コマンドを使ってPCのハードウェア側にOSが把握している時間をかき込みます。Windows などの場合もおそらくOS終了時に時刻を書き戻しているでしょう。この理由は、PCのハードウェア上の時刻はずれていることがままあるためです。

この PC上のハードウェアの時計は「どの時間帯」の時間を記録しているでしょうか?実はこれは決まっていません。ほとんどの場合、ハードウェアの時計はローカルタイム、現地時間を記録してます。一方、ハードウェアの時計が UTC(世界標準時) であることを前提としているシステムもあります。例えば ESXi がそうです。ESXi は物理ホスト上のハードウェアの時計に UTC での時間をかき込み、起動時も UTC であることを前提に読み込みをします。

一方、Windows や Linux では、OSの内部では UTC をベースに構成されていますが、時刻の表示時には指定されたタイムゾーンを加味して現地の時間を表示しております。ハードウェアの時計に対しても、ローカルタイムがかき込まれているものと考えるのがデフォルトとなってます。先の hwclock コマンドも、OSから読み出した時間を /etc/localtime ファイルの示す時間帯を考慮した現地時間でかき込みます。


● 仮想マシンの時間

VMware の場合、初回起動時には ホストOSの時間がそのまま使われます。VMware Player や Workstation, Fusion では、新しい仮想マシンを作成して起動、BIOS設定画面に入ると現地時間での時刻が表示されます。
かつての ESX でもそうでした。ESX の場合、COS(サービスコンソール) の Linux 上の /etc/localtime を参照して仮想マシンの仮想的なハードウェアの時計に「ローカル時間」をかき込んでました。
ESXi の場合、/etc/localtime のようなタイムゾーンを把握する枠組みがありません。vSphereClient などで時間を見ると現地時間が表示されますが、これらはクライアントソフトウェア側で変換して表示しているもので、ESXi との時間のやりとりは UTC をベースとしています。

このため、ESXi で仮想マシンを作成、初回の起動時にBIOS時間を見ると、UTCで表示されます。日本の場合、9時間前の時刻が表示されていることになります。

新規に作成した仮想マシン
17:42 頃のものだが、8:42となっており、初回起動時は9時間ずれてるのが分かる
二度目以降の起動では少々事情が異なります。ゲストOSが終了時に(仮想の)ハードウェアの時計に時間を設定した時、VMware はそのかき込まれた時間と自身が把握している時間を比較、「差分」を検知します。ESXi の場合、上のOSが「日本時間」をかき込んでくると、9時間早い時間がかき込まれたことを検知します。この差分は nvram ファイルに保存されます。

二度目以降の起動時は、自身の時刻にこの差分を加味した時刻を、仮想マシンのハードウェアの時計としてセットします。先の例の場合、UTCに9時間を加えた時刻をハードウェアの時計とします。これは日本時間になります。ゲストOSはこの時間を読み込みますので、結果として正しい時間になります。
この挙動は VMware のこのドキュメントの「Virtual CMOS RTC」に記載されています。


● 他のハイパーバイザの仮想マシン

Hyper-V の場合は Windows の時刻管理に準じるためあまり深いことを考える必要がありません。

今回、この記事を書く動機になったのは KVMについてのハードウェアの時計がどうなってるかを調べたことからでした。KVM では、仮想マシンのモニタである qemu-kvm コマンドの引数 -rtc にどう設定するかによって決まります。主に以下2つのオプションが使われます。

  • clock : 時刻を何処で管理するか
    • clock=vm : 仮想マシン側で独自に時刻を管理する
    • clock=host : ホストの時間をそのまま利用する
  • base : 仮想マシンの起動時、(仮想の)ハードウェアの時計を何処に設定するか
    • base=2010-12-03T01:02:00 : 2010/12/03 01:02:00 に設定する
    • base=utc : UTCでの現在時間に設定する
    • base=local : ホストOSのタイムゾーンを加味した現地時間に設定する

OpenSUSE のドキュメントの例をみると
qemu-kvm [...] -rtc clock=vm,base=2010-12-03T01:02:00
となってますが、これは「時刻は仮想マシンで独自に管理」「2010 12/03 1:02:00 をハードウェアの時計の開始時間」として設定することを意味します。

(AHVについては記述が誤っていたため一旦削除しました。あらためて正しい情報を書きます。)

2017/04/06

【余談】Hammerspoon に移行

手元の Mac の OSをアップデートしたら Karabiner が利用できなくなってしまった。
どうも  macOS Sierra に非対応のとのこと。Karabiner はカーネルにモジュール(KEXT)を読み込ませ、カーネル内部のキーイベントを操作することでキーバインドの変更を実現している模様だが、そのためカーネルの変更に弱い面がある。

一方の Apple はセキュリティ面やOSの安定稼働の面から、KEXT による拡張を抑制する方向にある。Microsoft も 64bit 移行やOSのアップグレードの機会を通じて電子署名されていないデバイスドライバはロードできないようにしているし、iOS のようなモバイルデバイスのOSでは、もはやカーネルにモジュールを追加することすら不可能になっている。

幸い、Karabiner では Karabiner Elements という新しいキーリマップソフトウェアを開発、そこから従来の Karabiner の機能を追加していく形で刷新するようで、これは期待が持たれる。とはいえ、一からの作り直しなのでしばらくは Karabiner なしの生活に耐えなければならないようだ。

私が Karabiner を使ってる理由は、実のところ「Microsoft Office で Emacs キーバインド(のサブセット)が使いたい」 につきる。Karabiner Elements では現在のところアプリケーションごとのキーマップというのは実装されてないので、これは対応できないことになる。

いい加減 面倒になってきたので色々探して試した結果、Hammerspoon を利用することに落ち着いた。Hammerspoon はキー入力などのイベントを Lua という言語を使ってカスタマイズするもので、単なるキーリマップ以上の操作もできるようだ。
また、Accessibility API を通じてキーイベントを取得、操作を行う。公式のAPI を通しているため、OSのアップデートによる影響も(KEXTを使うのに比べると)低い訳だ。

Hammerspoon は ~/.hammerspoon/init.lua というスクリプトを読み、これに応じて処理をおこなう。私のスクリプトは以下の通りだ。

詳細は、この gist のコメントを見てほしい。

2017/02/18

【TIPS】外付けSSD

普段は Macbook Air (2012) で VMware Fusion を使っていますが、本体のストレージ容量が256GBしかないのでやりくりには苦労します。仮想マシンもインストール用ISOイメージもGB単位で容量を食うので、こまめに掃除しないとあっという間にあふれてしまいます。

そこで、前職の頃から外付けSSDを接続してこちらに仮想マシンを配置、使用しております。
こんな感じです。

外付けSSDドライブ。下の袋は函館に旅行したときに買ってたものを利用

Transcend の TS512GESD400K という 512GB の外付けSSDで、今だと 25,000円程度で入手できます。前職では会社に買ってもらって利用していたのですが退職時に会社支給の Macbook Air と共に返却、ただ使い勝手が良く気に入ってたので退職後、自分でも買い直した次第です。(なお、Macbook Air はたまたま知己が買い換えで余らせてたものを引き取ったのですが、奇しくも前職で使ってたのと同じ2012年ものとなりました。)

仮想マシンやISOイメージはこちらに格納して、Fusionを利用するときだけドライブを接続して使ってます。小さく軽いため鞄に入れてても気になりませんし、USB3.0のポートに繋いでいる限りは、内蔵SSDで仮想マシンを起動しているとの体感的な速度差は感じません。

唯一の注意点は、付属のUSB3.0ケーブルを使うこと、って事ですか。高速通信をがんがんかけるので、品質の良くないケーブルを使うとたちまち不安定になります。
付属品は太くて取り回しが少々不便なのですが、そのぶん安定しております。

検証ごとにリンククローンで仮想マシンを作ってるせいもあるのですが、この中に常時20ないしそれ以上の仮想マシンが入ってます。

Macbook Air の場合(というか最近の Mac のノート全般で) 本体のストレージ交換は酷く面倒な上、交換用のドライブも高価です。

若干はかさばりますが、リーズナブルな価格での増量ができる、外付けSSDは悪くない選択肢かと思われます。





Windows Server 2016 仮想化ベースのセキュリティ

Windows Server 2016 では様々なレイヤーでのセキュリティの強化が実装されていますが、その中の一つに「仮想化ベースのセキュリティ」と呼ばれる一連の機能があります。

機能名としては「Device Guard」や「Credential Guard」など呼ばれるものです。その詳細についてはマイクロソフトのこちらのページをご参照頂ければと思います。

ポイントとしては上記ページの以下の図が分かりやすいかと思います。

https://technet.microsoft.com/ja-jp/library/mt483740(v=vs.85).aspx より引用


これは Credential Guard の例ですが、ドメイン環境でのサインイン時に、ActiveDirectory から得られた認証情報(Credentials)は、通常ですと OS のメモリ空間のどこかに存在します。このため、カーネル内を含めメモリを読むことができる特権を得られれば、それをメモリから読み取り、奪い取ることができてしまいます。そのアカウントのパスワードを知らずとも、得られた認証情報をつかうことでそのユーザーとしてドメイン内のリソースへアクセスできてしまいます。

Credential Guard を有効にすると、Hyper-V による仮想化を利用して認証情報が切り離されます。 (厳密には異なりますが)ざっくりとしたイメージとしては本来の Windows Server を実行する仮想マシンと、認証情報だけを抱えた小さな仮想マシンの2つが Hyper-V にのっかっているという感じです。

仮想マシン同士のメモリ空間はハイパーバイザーによって分断されており、ある仮想マシンのメモリ空間の端から端までアクセスしても、他の仮想マシンのメモリ空間にはアクセスできません。これらは Intel-VT や SLAT といったハードウェアの機構により実現されており、ハイパーバイザー上のゲストOSやアプリケーションでは越えることができません。
つまり、別空間に切り離された認証情報を従来と同じ方法では盗めない、切り離された秘匿情報は正当なAPIを通じてのみアクセスが許可されます。

これが、Credential Guard です。また、仮想化ベースのセキュリティの一例となります。


要件は冒頭のページを見て頂ければと思いますが、ざっくりとは以下の感じです。
  • OS: Windows 10 Enterprise ないしは Windows Server 2016
  • CPU: 64bit CPU, Intel VT (AMD-V)および SLAT対応
  • TPM: 1.2 ないし 2.0 対応 (1.2の場合は Windows10 1511以降)
あと、セキュアブートも必要となってきます。

物理PC上での利用が前提(Windows 10 の場合仮想マシン上はサポート外)ですが、Windows Server 2016 と Windows 10 で可能となった、nested Hyper-V を使えば仮想マシン上でも試すことはできます。

そこで、実際に仮想マシンで Credential Guard を有効にしてみました。


● 事前準備

まず、Hyper-V 上で G2 仮想マシンを作成します。
従来型の G1仮想マシンは BIOSベースのファームウェアで、ブートドライブとしてIDEのエミュレーションが、デフォルトのNICもエミュレーションベースのものになります。物理PCとの互換性は高いのですが、性能的に制約がある次第です。

G2 仮想マシンは UEFIベースのファームウェアで稼働し、IDEやNICのエミュレーションをしません。高性能の代わりに Hyper-V に対応していないOSはインストールできません。もっとも、Windows ならば Vista 以降、Linux でも最近のものなら標準で Hyper-V 向けのデバイスドライバーを持っており後から統合サービス(IC)をインストールしなくても良くなってます。

あと、重要なポイントとして、G2仮想マシンは UEFI上でのセキュアブートを実現しているという点です。今回はセキュアブート環境を用意したいために、G2を選択しています。


Windows Server 2016 をインストールして、Windows Update の実行など一般的な処理をおこなっておきます。別に ServerCore でも構わないのですが、後での動作確認を楽にするためにデスクトップエクスペリエンスありを利用しております。

一旦シャットダウン後、Enable-NestedVM.pl を利用して仮想マシン上での Hyper-V の実行を許可します。方法がよく分からない場合は、こちらの動画を参照してください。

その後、仮想マシンを再び起動し、Hyper-V の役割を有効化します。
以前の Windows10 ではこのときに「分離ユーザーモード」 の機能も有効化する必要がありました。
が、Windows Server 2016 および最近の Windows10 では分離ユーザーモードの選択肢が存在しません。OSに標準組み込みになったので特に選択する必要眼漠なったようです。

Hyper-V の役割のインストールに伴い再起動が発生するので、一回再起動しておきます。

これで、Credential Guard を有効化するための準備は完了です。


● Credential Guard の構成

Credential Guardの設定はグループポリシーを通じて行います。今回はドメインに参加していない1台だけのため、mmc.exe を起動、スナップインの追加でグループポリシーの編集を追加、ローカルコンピューターポリシーを編集しますが、ドメイン環境下の場合、GPOを配布することでドメイン下のメンバーサーバなどにまとめて一気に設定をすることもできます。

ともあれ、設定するポリシーは以下になります。



「コンピューターの構成」->「管理テンプレート」->「システム」->「DeviceGuard」の下に、「仮想化ベースのセキュリティを有効にする」があります。これをダブルクリックしてます。



まずは上のラジオボタンを未構成から「有効」にします。

次に、「プラットフォームのセキュリティレベルを選択する」を今回は「セキュアブートと DMA保護」から、「セキュアブート」だけにします。前者のDMA保護は VT-d (ないしは IOMMU) で実現されていますが、Hyper-V上の仮想マシンではVT-d/IOMMUのエミュレーションは行われていないためです。

OKをおして保存後、ポリシーを確実に読み込ませるために、OSを再起動しておきます。
ドメイン環境でGPOをドメインコントローラから配信している場合は、再起動前に gpupdate /force を実行しておくといいかもしれません。
(GPOは更新されて即時に展開されるわけではなく、ある程度時間をかけて浸透していきます。クライアント側から gpupdate を実行することで、強制的に最新のポリシーをドメインコントローラに取りに行かせるわけです。もちろん、検証や数台のサーバからの実施ならばいいのですが、大量のサーバから gpupdate で即時取得を繰り返すのはドメインコントローラに負荷がかかるのでご注意ください。)
 
これで構成は完了です。


● Credential Guard の確認

では実際にメモリをダンプして Credentail を読み取れなくなったか確認してみましょう...、ではさすがに洒落にならないので、UIから動作確認します。

コマンドラインなどから msinfo32.exe を実行すると、システム情報というウィンドウが立ち上がります。左側のツリーでは標準選択されてている「システムの要約」をそのまま、右側の一覧をスクロールダウンしてくと、最後の方に Device Guard から始まる情報がいくつか記載されています。



まず、「Device Guard 仮想化ベースのセキュリティ」 が「実行中」になっているかがポイントだ。構成されていない場合はこれが「無効」になっており、構成されていても条件が整わなくて起動していない場合は「有効(停止中)」などになります。

次の、「Device Guard の必要セキュリティプロパティ」 が、仮想化ベースのセキュリティを実行させるにあたり必要となる機能で、その次の「Device Guard の利用可能なセキュリティプロパティ」が、実行している環境が提供できる機能の一覧になります。

つまり、必要側に書かれてる機能が利用可能側に記載がない場合、仮想化ベースのセキュリティは機能不足で稼働しないものになります。

構成済みの Device Guard セキュリティサービス が、GPOなどで構成したサービスです。ここでは Credential Guard が記載されていることが分かります。一方、その下の「実行中の Device Guard セキュリティサービス」が実際に稼働しているサービスを指します。こちらも Credential Guard の記載がある、つまりは Credential Guard が有効である事が分かります。

また、上から9行目ほどに「セキュアブート」がありますが、これが「有効」なものは、UEFIからはじまりブートローダー、OS、デバイスドライバと起動時から順に読み込まれていったモジュールがすべて有効な電子署名が施されている、改ざんされていないことを示します。


●うまく構成できていない例

たとえば Hyper-V は有効にしたものの、GPOをまだ設定していない場合には、以下のように「仮想化ベースのセキュリティ」 が単に「無効」と表示されます。




プラットフォームのセキュリティレベルを「セキュアブートとDMA保護」にしたにも関わらず、VT-d, IOMMU などがない場合は、以下のようになります。


必要なセキュリティプロパティに「DMA保護」 が入っていますが、その下の利用可能なセキュリティプロパティに「DMA保護」はありません。条件を満たさなかったためセキュリティサービスとして Credential Guard が表示されていないのが分かります。


また、VMware Fusion で構成を試してみた例がこちらです。Fusion でも nested VM を有効にして、Hyper-V をインストールしたのですが、Credential Guard が有効になってません。よくよく見るとDMA保護だけではなく、仮想化の基本サポート以降の機能がまったくありません。従って、Credential Guard は元より、仮想化ベースのセキュリティも実行されていません。


そもそも、VMware の仮想マシンではセキュアブートが使えません。
例の上から9行目のセキュアブートの項目を見ても「サポートされていません」になっているのが分かります。

セキュアブートが有効でない都言うことは、OS起動時のブートローダを改ざんしたり、間にプロセスを介入させることで仮想化ベースのセキュリティを有効化する前に悪意あるコードを混ぜ込むことが可能となってしまいます。いくらハイパーバイザーでセキュリティを保とうとしても、あく怒るコードの方が先にハイパーバーザーとして起動されてしまう恐れがある訳です。

そのためか、これまでみてきたように仮想化ベースのセキュリティでは、セキュアブートが「必要なプロパティ」として要求されています。

2017/02/09

vExpert 2017 受賞しました

vExpert 2017 受賞しました。どうもありがとうございます。

https://blogs.vmware.com/vmtn/2017/02/vexpert-2017-award-announcement.html

昨年1年を振り返るとやはりあまり活発な活動をしてたとは言えないので、今年はもう少し活動できれば、とか思っております。

2017/01/18

[TIPS] VMware Fusion で無差別モード時の認証を行わないようにする

VMware Fusion Professional の場合、環境設定にあるネットワークの設定にて、「無差別モードに入るには認証が必要です」のチェックを外すことで、仮想マシンが Promiscous Mode に入ろうとしたときに表示される認証を省くことができる。

ネットワークの設定
このパネルは Professional でのみ表示される

チェックを外すと、警告が出るので「続ける」を押す
この警告にもあるとおり、無差別モードを仮想マシンに許すと、その仮想ネットワーク内の通信や、ブリッジの場合はそのネットワークを流れる通信を確認することが可能になり、さらには偽装したパケットの送信もできるようになる。非常に危険なので通常は無差別モードを設定しようとした瞬間に認証がかかって、Fusion の利用者にあらかじめ確認を取るようになっている。

しかし、たとえば ESXi をFusion 上の仮想マシンとして実行する場合、「そのネットワークからくる ESXi 上の仮想マシンのMACアドレスのパケットを受け取る」「そのネットワークに ESXi 上の仮想マシンのパケットを送り出す」という操作、つまりは仮想マシン自身以外のMACアドレスのパケットの読み書きが必要になり、無差別モードが必須となる。

毎回確認されるのも面倒な場合は、このチェックを外すのもいいだろう。


なお、チェックを「外す」事で、/Library/Preferences/VMware Fusion 以下に、 promiscAuthorized という空のファイルが作成される。

promiscAuthorized ファイルが存在する
言い換えれば、この空のファイルを作れば無差別モード時の認証は行われなくなる。

このため、ネットワークの設定パネルのない、通常の VMware Fusion でも以下のコマンドで無差別モード時の認証をなくすことができる。

sudo touch "/Library/Preferences/VMware Fusion/promiscAuthorized"

パスが空白を含むので、ダブルクォートでくくるのを忘れないこと。









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 で状態を可視化するのも有益でしょう。