Vagrant で VirtualBox 上の CentOS 7 へ固定 IP を設定

はじめに

Vagrant を使って VirtualBox 上で CentOS 7 を起動する際に、固定 IP を設定しようとするとエラーが発生しました。

Vagrantfile
・・・
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    config.vm.box = "centos7"
    # ゲスト OS 間の通信用に固定 IP アドレスを設定
    config.vm.network "private_network", ip: "192.168.100.11", virtualbox__intnet: "intnet"
end

CentOS 7 の Box を centos7 という名称で Vagrant へ登録済みです。

なお、virtualbox__intnet の設定が無いとホスト OS と通信するための IP アドレス設定 (ホストオンリーアダプター) になるようです。 (この場合、その IP でゲスト OS 間通信はできない模様)

vagrant up 時のエラー内容
> vagrant up

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos7'...
・・・
==> 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:

CentOS 7 自体の起動は成功しており (SSH でログイン可能)、固定 IP アドレスの設定に失敗しています。

エラーの原因

原因は下記の通りです。

  • CentOS 7 では NIC の名称がデフォルトで eth<番号> (例 eth0) では無くなっている
  • VagrantRedHat 系 OS 設定用のプラグインでは今のところ eth<番号> 以外の NIC 名を処理できない

要するに、VirtualBox 上で CentOS 7 を実行すると NIC 名が下記のようになりますが、VagrantRedHat 系 OS のネットワーク設定を担うスクリプトplugins/guests/redhat/cap/configure_networks.rb) では、今のところ下記 NIC 名に対応していません。

  • enp0s3 (アダプター1)
  • enp0s8 (アダプター2)

実は、Fedora のネットワーク設定を担うスクリプトplugins/guests/fedora/cap/configure_networks.rb) では biosdevname -d コマンドを使って NIC 名を取得しており、上記 NIC 名に対応できているようです。

回避方法

本件のエラーを回避するには下記のような方法が考えられます。 (プラグインを用いる等、他の方法も色々あると思います)

  • (a) CentOS の設定を変更して古い NIC 名 (eth<番号>) を使うようにする
  • (b) RedHat 用の configure_networks.rb へ Fedora 用の configure_networks.rb の処理内容を適用する
  • (c) プロビジョニングで固定 IP を設定する

個人的に、本件は Vagrant 側で対応すべき問題だと思うので、今回は (b) と (c) の対応方法をご紹介します。

(b) RedHat 用の configure_networks.rb へ Fedora 用の configure_networks.rb の処理内容を適用する

Fedora の configure_networks.rb の実装内容を RedHat の configure_networks.rb へ適用する方法です。

configure_networks.rb の内容を書き換えてしまうので、あまり望ましい方法では無いかもしれませんが、対応手順は下記のようになります。

  • (1) plugins/guests/redhat/cap/configure_networks.rb のバックアップをとる
  • (2) Fedora 用の configure_networks.rb (plugins/guests/fedora/cap/configure_networks.rb) を RedHat 用の configure_networks.rb (plugins/guests/redhat/cap/configure_networks.rb) へ上書きコピー
  • (3) (2) で更新した RedHat 用の configure_networks.rb ファイルを編集し、モジュール名を GuestFedora から GuestRedHat へ変更
plugins/guests/redhat/cap/configure_networks.rb の内容
・・・
module VagrantPlugins
  module GuestRedHat
  ・・・

なお、Windows 用の Vagrant の場合は embedded\gems\gems\vagrant-1.6.3 に plugins ディレクトリがあります。

Fedora 用の configure_networks.rb を適用して問題ないかを十分検証したわけではありませんが、一応 vagrant up でエラーが発生せず固定 IP アドレスを設定できました。

実行例
> vagrant up

・・・
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
・・・

enp0s8 へ IP アドレスが設定されている事を確認。

> vagrant ssh
Last login: Mon Aug 25 06:50:04 2014 from 10.0.2.2
[vagrant@localhost ~]$ ip addr
・・・
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
qlen 1000
    ・・・
    inet 192.168.100.11/24 brd 192.168.100.255 scope global enp0s8
    ・・・

(c) プロビジョニングで固定 IP を設定する方法

Vagrant のプロビジョニング機能を使い ip addr add コマンド等で IP アドレスを設定するだけなので、(b) に比べると安全な方法だと思います。

まずは、Vagrantfile へ下記のように provision の定義を追加し、:inline に対して固定 IP アドレスを enp0s8 へ設定し有効化するコマンドを記載します。

Vagrantfile
・・・
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
    config.vm.box = "centos7"

    config.vm.network "private_network", ip: "192.168.100.11", virtualbox__intnet: "intnet"
    # プロビジョニングによる固定 IP の設定
    config.vm.provision :shell, :inline => "sudo ip addr add 192.168.100.11/24 dev enp0s8; sudo ip link set enp0s8 up"
end

vagrant up のネットワーク設定でエラーが発生し途中終了するので、その後に vagrant provision を実行すると固定 IP アドレスを設定します。

実行例1
> vagrant up

・・・
==> 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.
・・・

vagrant provision でプロビジョニング機能を実行します。

> vagrant provision
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: RTNETLINK answers: File exists

enp0s8 へ IP アドレスが設定されている事を確認。

> vagrant ssh
・・・
[vagrant@localhost ~]$ ip addr
・・・
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    ・・・
    inet 192.168.100.11/24 brd 192.168.100.255 scope global enp0s8
    ・・・

vagrant up でエラーを発生させないようにする

vagrant up の後に vagrant provision を別途実行するのが面倒な場合。

plugins/guests/redhat/cap/configure_networks.rb を下記のように編集し、ifup が失敗してもエラーを発生させないようにすれば vagrant up 時にプロビジョニングも適用できるようになります。 (ただし、マウントエラーのような他のエラーを発生させない事が前提)

plugins/guests/redhat/cap/configure_networks.rb 編集例 - ifup の実行処理へ error_check: false を追加 (61 行目)
machine.communicate.sudo("ARPCHECK=no /sbin/ifup eth#{interface} 2> /dev/null", error_check: false)
実行例2 - configure_networks.rb を編集した場合
> vagrant up --provision

Bringing machine 'default' up with 'virtualbox' provider...
・・・
==> default: Configuring and enabling network interfaces...
・・・
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: RTNETLINK answers: File exists

なお、vagrant up でプロビジョニングが適用されるのは初回起動時のみのようですので、2回目以降は vagrant up --provision でプロビジョニングを強制適用して起動する必要があります。