[Sy] 【解決した】VagrantでCentOS7のVMを作ったらネットワーク設定でコケた(固定IP割り当てに失敗)
現象
Vagrant + VirtualBox 上で CentOS7 のBoxを使ってVM(仮想マシン)をvagrant up
で作ろうとすると、
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'CentOS7.0_x86_64'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: mind_canvas_default_1415699812027_84984
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
default: Adapter 2: hostonly
==> default: Forwarding ports...
default: 22 => 2200 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Configuring and enabling network interfaces...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
ARPCHECK=no /sbin/ifup eth1 2> /dev/null
Stdout from the command:
ERROR : [/etc/sysconfig/network-scripts/ifup-eth] Device eth1 does not seem to be present, delaying initialization.
Stderr from the command:
とエラーが起きてしまう。
この時点でVM自体は作成されてて、vagrant ssh
でSSH接続はできる。ただ、Vagrantfile
にて
config.vm.network "private_network", ip: "192.168.33.10"
のように固定IPを振ろうとしているのに、ssh vagrant@192.168.33.10
では接続できない。
環境
- Mac OS X 10.10(Yosemite) ⇒ ホストOS
- Vagrant 1.6.3
- VirtualBox 4.3.12
- CentOS7.0 ( x86_64 minimal (VirtualBoxGuestAddtions 4.3.14) ) ⇒ ゲストOS
ゲストOS(VM上で動かすOS)のCentOS7.0は Vagrantbox.es から選択したVagrantのBoxを使用。
解決方法
以下の手順で解決しました。
1. Vagrantをアップデートする
まずはVagrantを最新版(2014/11/13現在:1.6.5)にアップデートします。
(念のため起動中のVMは全部vagrant haltで止めてからアップデートした方がいいかも?)
Vagrantのアップデートは 公式サイト から普通に Mac OS X用のインストーラを落としてきてインストールしてしまえばOKです。(以降、Mac OS X 向けの説明になりますが、Windowsの場合もほぼ同じようにいけるはずです)
vagrant_1.6.5.dmg
をダウンロードできたら、dmgファイルをクリックします。するとVagrant.pkg
というファイルが出てくるので、そいつをクリックしてインストーラを起動します。
あとはデフォルトのままインストールを進めていきます。
インストールが終わったら、Vagrantのバージョンを確認しておきましょう。
Vagrantのバージョンを確認するには、ターミナルで
$ vagrant -v
Vagrant 1.6.5
で確認できます。ちゃんと1.6.5にアップデートされました。
2. 改めてvagrant upでVM作成
VagrantがアップデートできたらVMを作りなおします。
おそらく先ほど失敗したVMをそのまま使うとうまくいかない(試してないのでうまくいくかも?)と思ったので、一旦vagrant destroy
で削除してから改めてvagrant up
で作りなおして解決。
このエラーが起こる条件
以下2つ両方に当てはまる場合でした。
- Vagrantのバージョンが1.6.4以下
- CentOS7のBox使用
原因の詳細&調べたこと
もう少し原因を詳しく知りたい人、原因追求までの右往左往を知りたい人は以下も参考になれば。
1. エラーメッセージでググる
とりあえず何が何やらわからなかったので、エラーメッセージでググるとそれっぽい記事発見。
⇒ Vagrant で VirtualBox 上の CentOS 7 へ固定 IP を設定 - なんとなくな Developer のメモふむ。同じ現象っぽい。この記事からわかったのは、
- CentOS7ではデバイス名(記事ではNIC名)の名称が
eth0
、eth1
という形式から、enp0s3
、enp0s8
に変わってるらしい。 - そのため、VagrantのRedhat系OS設定用のプラグインがうまくデバイス名を取れずにエラーなってる。
ということみたい。この時点ではまだなんとなくわかるようなわからないような状態。
で、回避方法が書いてあるので読んでみたけど、プラグインをいじったり設定ファイルをいじったりだったので、この中途半端な理解でやっちゃうと危ない気がすると思い、一旦さらっと読んで他の情報を探す。
2. さらにエラーメッセージでググる
今度はちょっと古めで、かつ現象も違いそうな記事でしたが手がかりがないかなーと軽く読んでみることに。
⇒ Vagrantのネットワークが起動しないときは - Thinking-meganeこの記事で、
ブリッジネットワークまたはホストオンリーネットワークで起動すると、ネットワークインターフェース設定ファイル/etc/sysconfig/network-script/ifcfg-<デバイス名>
がVagrantによって作成される。
という大事なポイントに気づきました。
3. 一旦寄り道してネットワークのお勉強
先ほどのポイントを攻める前に、あまりネットワークまわりは自信がないので以下のサイトでちょっと勉強しました。
ふむふむなるほど。
4. VirtualBoxマネージャーでネットワークの設定を確認
ここでVirtualBoxを起動して、実際に作ったVMの設定を確認。
VMのネットワーク設定は、以下の手順で確認できます。
- ネットワーク設定を確認したいVMを選択。
- 設定ボタンを押して、ダイアログを表示。
- ダイアログの「ネットワーク」をクリック。
ここで、 「アダプター2」のタブを開いてみると、ネットワークアダプタの割り当てがホストオンリーアダプタになっています。(画像の4, 5)
ということは、Vagrantによってネットワークインターフェース設定ファイルが作成されているってこと?
5. ネットワークインターフェース設定ファイルを確認
ゲストOSにvagrant ssh
でログインして、/etc/sysconfig/network-scripts/ifcfg-eth1
を探すと・・・あった!
この時点で、1で見た記事の内容も踏まえて根本的な原因がつかめてきました。
- CentOS7からは、デバイス名が
eth0
、eth1
の形式ではなくなってる。 - それにもかかわらず、Vagrant側で作成されるネットワークインターフェース設定ファイルが相変わらず
eth0
、eth1
といったデバイス名に対応したifcfg-eth1
のような名前で作られてる。
ということなのでは?
6. 1で見た記事に戻り、Vagrantのプラグインを見てみる
だいぶ理解できてきたので、一番参考になりそうな1の記事をもう少ししっかり読むことに。
なるほど。plugins/guests/redhat/cap/configure_networks.rb
というRedHat系のネットワーク設定を行うプラグインがCentOS7対応していないということか。とようやく納得。(CentOSはRedHat系なのでこのプラグインが作動する)
ということで、実際のスクリプトを見てみることに。
ターミナルで/Applications/Vagrant/
に移動して、スクリプトを検索すると、
$ cd /Applications/Vagrant/
$ find ./ -name configure_networks.rb
embedded/gems/gems/vagrant-1.6.3/plugins/guests/
配下に、各OSに対応したconfigure_networks.rb
があることがわかりました。
1の記事によるとfedora/cap/configure_networks.rb
の方法だとうまくデバイス名を取得できるらしいとあるので、そっちを見てみるとConfigureNetworks
クラスのself.configure_networks(machine, networks)
メソッドにて、
/usr/sbin/biosdevname -d | grep Kernel | cut -f2 -d: | sed -e 's/ //;’
というコマンドを実行してデバイス名のリストを取得しているっぽい。
実際にゲストOSにログインしてこのコマンドを一つ一つ分解して実行してみると、
$ sudo /usr/sbin/biosdevname -d
BIOS device: p2p1
Kernel name: enp0s3
Permanent MAC: 08:00:27:EA:9B:B5
Assigned MAC : 08:00:27:EA:9B:B5
ifIndex: 2
Driver: e1000
Driver version: 7.3.21-k8-NAPI
Firmware version:
Bus Info: 0000:00:03.0
PCI name : 0000:00:03.0
PCI Slot : 2
Index in slot: 1
BIOS device: p7p1
Kernel name: enp0s8
Permanent MAC: 08:00:27:57:80:36
Assigned MAC : 08:00:27:57:80:36
ifIndex: 3
Driver: e1000
Driver version: 7.3.21-k8-NAPI
Firmware version:
Bus Info: 0000:00:08.0
PCI name : 0000:00:08.0
PCI Slot : 7
Index in slot: 1
ふむ。Kernel name
のところにenp0s3
とかenp0s8
とかある。次。
$ sudo /usr/sbin/biosdevname -d | grep Kernel
Kernel name: enp0s3
Kernel name: enp0s8
grepかけて、必要な行に絞って、
$ sudo /usr/sbin/biosdevname -d | grep Kernel | cut -f2 -d:
enp0s3
enp0s8
:
より前を捨てて、
$ sudo /usr/sbin/biosdevname -d | grep Kernel | cut -f2 -d: | sed -e 's/ //;’
enp0s3
enp0s8
うん、ちゃんとCentOS7でもデバイス名のリストがとれますね。
ということで、Fedora用のプラグインでうまくデバイス名をとれているのはわかりました。
次にRedHatの方も見てみると、引数で渡されてきたnetworks
をイテレータで回して、その要素(network
)ごとにnetwork[:interface]
でおそらくeth0
、eth1
とデバイス名を取得しているんだろうというコードになってます。
その結果、CentOS7でも相変わらずifcfg-eth1
といった設定ファイルが作成されちゃうんですね。
7. さてどうするか
とりあえず1の記事にあるとおり、このRedHatのスクリプトをFedoraのもので上書きしちゃえばうまくいくかもという気がします。
ただ、これまた記事にあるとおり、それが安全なのかどうかはちゃんとスクリプトを理解しないとわからない。
どうしようかなーと思ってた時に、ふと、
あれ?そういえば、この記事は8月末のだから、もしかしたら最新版のVagrantでは解決済みなのでは?(気づくの遅い
Vagrantのリポジトリ を見てみると、やっぱり。最新の1.6.5では解決してるっぽい。
8. Vagrantをアップデートして終わり
で、上の解決方法の手順でVagrantをアップデートして完了!