Syntax Error.

[Sy] 【解決した】VagrantでCentOS7のVMを作ったらネットワーク設定でコケた(固定IP割り当てに失敗)

2014/11/14

現象

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では接続できない。

環境

ゲスト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インストーラのダウンロード

vagrant_1.6.5.dmgをダウンロードできたら、dmgファイルをクリックします。するとVagrant.pkgというファイルが出てくるので、そいつをクリックしてインストーラを起動します。

Vagrantインストーラ起動

あとはデフォルトのままインストールを進めていきます。

インストールが終わったら、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名)の名称が eth0eth1 という形式から、enp0s3enp0s8に変わってるらしい。
  • そのため、VagrantのRedhat系OS設定用のプラグインがうまくデバイス名を取れずにエラーなってる。

ということみたい。この時点ではまだなんとなくわかるようなわからないような状態。

で、回避方法が書いてあるので読んでみたけど、プラグインをいじったり設定ファイルをいじったりだったので、この中途半端な理解でやっちゃうと危ない気がすると思い、一旦さらっと読んで他の情報を探す。

2. さらにエラーメッセージでググる

今度はちょっと古めで、かつ現象も違いそうな記事でしたが手がかりがないかなーと軽く読んでみることに。

⇒ Vagrantのネットワークが起動しないときは - Thinking-megane

この記事で、

ブリッジネットワークまたはホストオンリーネットワークで起動すると、ネットワークインターフェース設定ファイル/etc/sysconfig/network-script/ifcfg-<デバイス名>がVagrantによって作成される。

という大事なポイントに気づきました。

3. 一旦寄り道してネットワークのお勉強

先ほどのポイントを攻める前に、あまりネットワークまわりは自信がないので以下のサイトでちょっと勉強しました。

ふむふむなるほど。

4. VirtualBoxマネージャーでネットワークの設定を確認

ここでVirtualBoxを起動して、実際に作ったVMの設定を確認。

VMのネットワーク設定は、以下の手順で確認できます。

VirtualBoxのネットワーク設定確認
  1. ネットワーク設定を確認したいVMを選択。
  2. 設定ボタンを押して、ダイアログを表示。
  3. ダイアログの「ネットワーク」をクリック。

ここで、 「アダプター2」のタブを開いてみると、ネットワークアダプタの割り当てがホストオンリーアダプタになっています。(画像の4, 5)

ということは、Vagrantによってネットワークインターフェース設定ファイルが作成されているってこと?

5. ネットワークインターフェース設定ファイルを確認

ゲストOSにvagrant sshでログインして、/etc/sysconfig/network-scripts/ifcfg-eth1を探すと・・・あった!

この時点で、1で見た記事の内容も踏まえて根本的な原因がつかめてきました。

  • CentOS7からは、デバイス名がeth0eth1の形式ではなくなってる。
  • それにもかかわらず、Vagrant側で作成されるネットワークインターフェース設定ファイルが相変わらずeth0eth1といったデバイス名に対応した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]でおそらくeth0eth1とデバイス名を取得しているんだろうというコードになってます。

その結果、CentOS7でも相変わらずifcfg-eth1といった設定ファイルが作成されちゃうんですね。

7. さてどうするか

とりあえず1の記事にあるとおり、このRedHatのスクリプトをFedoraのもので上書きしちゃえばうまくいくかもという気がします。

ただ、これまた記事にあるとおり、それが安全なのかどうかはちゃんとスクリプトを理解しないとわからない。

どうしようかなーと思ってた時に、ふと、

あれ?そういえば、この記事は8月末のだから、もしかしたら最新版のVagrantでは解決済みなのでは?(気づくの遅い

Vagrantのリポジトリ を見てみると、やっぱり。最新の1.6.5では解決してるっぽい。

8. Vagrantをアップデートして終わり

で、上の解決方法の手順でVagrantをアップデートして完了!

関連記事