2014年5月12日月曜日

ESXi上でVirtualBoxがうまく動かなくてハマった件

VMware ESXi上の仮想マシンでさらにVirtualBox(Vagrantが使いたかった)を動かしたかったのだけど、すんなり動かなくてハマったのでメモ。

現象

vSphere側でハードウェアの仮想化とかVT-xとかの設定は全て有効にした状態でVirtualBoxでゲストOS(64bit)を起動すると、

IO-APIC(apic pin)1-9,1-11,2-0,2-1,.....2-15
 ..MP-BIOS bug: 8254 timer not connected IO-APIC
 ..trying to set up timer as ExtINT..failed.
 ..tyring to set up timer as BP..IRQ..failed.
 kernel panic: IO-APIC + timer dose'nt work!

のようなエラーがでて起動しない。

VirtualBoxのマニュアルによると、Linux kernel 2.6.18にレースコンディションがあってうんたらと書いてあって一見それっぽいんだけど、カーネルのバージョンは2.6.32だったので問題はなさそうだった。

解決方法

VirtualBoxのゲストOSのIO-APICの無効にすると動いた。

VBoxManage modifyvm 仮想マシン名 --ioapic off

VBoxManageコマンドだとこんな感じ。

config.vm.provider :virtualbox do |vb|
  # Don't boot with headless mode
  vb.gui = true

  vb.customize ["modifyvm", :id, "--ioapic", "off"]
end

Vagrantfileだとこんな感じ。

あと試してないけどLinux kernelオプションでnoapicを指定するのでも良さそうな気がする。

ただIO-APICはマルチコアCPUでは必須の機能らしいので、コア数を複数割り当てたい場合は諦めるしかないかもしれない。

とりあえずは動かせるようになったけど、なんだかしっくりこないのと新しい仮想マシンを作るたびにいじらなきゃいけないのでテンポ悪いのがなんとも……。

余談

仮想マシンをネストさせることをnested virtualizationとかnested vmとか言うらしい。ググる時の参考に。
nested virtualizationは色々難儀なのでできるなら避けたほうが良いと書いている人もいた。

親側の仮想マシンに対して仮想化関係の設定を有効にしてあげないと、そもそも入れ子で動かせなかったり、なんか32bitになったりする。
/proc/cpuinfo見てflagsにvmxがあるかどうかがひとつの判断材料になるとかなんとか。
vSphereでいうとCPUの設定のところの「ハードウェアアシストによる仮想化をゲストOSに公開」とか「CPU/MMX仮想化」のところの「Intel VT-x/AMD-Vを命令セット仮想化に使用し、Intel EPT・AMD RVIをMMU仮想化に使用」あたり。

さくらのVPSとかConoHaとかでVirtualBoxを使ってる記事はわりとよく見るので、親がKVMだとわりとうまくいくのかもしれない。

2014年5月1日木曜日

systemd-networkdでのネットワーク設定

systemd v210からsystemdはudevとnetworkdによるネットワーク設定がサポートされるようになった。
これを利用するとNetworkManagerやnetctlといったものを利用せずにsystemd自身でネットワークの設定が行えるようになる(既存のネットワークマネージャの類を使い続けることもできる)。

以下はArch Linuxでの例を挙げるけど、CoreOSやDebianなどでもだいたい同じだと思う。

networkdの設定ファイル

systemd-networkdでの設定は/etc/systemd/networkディレクトリに.network.netdev.linkファイルを配置していくことになる。

.networkファイル …… マッチするデバイスにネットワークを設定するファイル。
.netdevファイル …… マッチする環境に仮想ネットワークデバイスを作成するファイル。
.linkファイル …… マッチするデバイスのリンクを設定するファイル。

仮想デバイスとかブリッジとか込み入ったことをしない場合は、.networkファイルだけで事足りる。

resolv.conf

あと、systemd-resolvedは/etc/resolv.confを更新してくれない。代わりに/run/systemd/resolve/resolv.confを生成するので、これに対してリンクを張る必要がある。

# オリジナルをバックアップ
sudo mv /etc/resolv.conf{,.orig}

# リンクを張る
# systemd 214からファイルパスが変わった模様
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

# systemd 213以前はこちらのパス
sudo ln -s /run/systemd/network/resolv.conf /etc/resolv.conf

DHCP

DHCPを設定する場合は素直にdhcpcdでも起動しておくのが一番手っ取り早いけど、それだと話が終わってしまうのでsystemd-networkdで設定してみる。

/etc/systemd/networkdhcp.networkみたいなファイルを作成する。ファイル名は任意。

[Match]
Name=en*

[Network]
DHCP=yes

こんな感じのファイルを作成して、systemd-networkdを再起動してあげると有効になる。
dhcpcdやnetctlを使用している場合は止めておくこと。

sudo systemctl restart systemd-networkd.service

ユニットじゃないのでdaemon-reloadは必要なさそうな気がするけど、もしも設定ファイルを認識しない場合はdaemon-reloadしてみるといいかもしれない。

sudo systemctl daemon-reload

セクション名やキーは大文字小文字を区別するっぽいので注意(nameとか書いてハマった)。

ちなみにMatchのNameのところはワイルドカードで指定できるので、インターフェイスが複数ないのであればざっくり指定してもいいかも。
おそらくsystemdとか使ってるケースではインターフェイス名もeth0とかじゃなくてenp2s0みたいなやつだと思うので(この命名規則については参考に挙げているリンクを参照)。
ざっくり言うとOSが認識した順にeth0, eth1とかするんじゃなくて、NICの刺さってるスロットとかの物理的な位置を名前に使おうよ、というお話。
どんな名前かはip linkifconfigで確認可能。

固定IPアドレス

固定IPアドレスの場合も設定方法はだいたい同じで、.networkに書く内容が違ってくるだけ。

例えばstatic.networkみたいなファイルを作成する。ファイル名は任意。

[Match]
Name=en*

[Network]
Address=192.168.1.22/24
Gateway=192.168.1.254
DNS=192.168.1.254

他にどんな設定が書けるのかはman systemd.network(とかman systemd.link)とかを参照。

ブリッジとか

ブリッジとかVLANとかはCoreOSのIntroduction to networkd, network managment from systemdに具体例があるので参考に。

Docker関係

Dockerを使うとdocker0みたいなブリッジが必要になるけど、この辺はdockerがbridge-utils(brctl)とかでうまくやってくれるみたいで、特に何も設定しなくても動いた。

参考

networkdの設定について

networkdができた背景

インターフェイス名の命名規則