Vagrant で VirtualBox 上の CentOS 7 へ固定 IP を設定
はじめに
Vagrant を使って VirtualBox 上で CentOS 7 を起動する際に、固定 IP を設定しようとするとエラーが発生しました。
- Vagrant 1.6.3
- VirtualBox 4.3.12 for Windows hosts
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) では無くなっている - Vagrant の RedHat 系 OS 設定用のプラグインでは今のところ
eth<番号>
以外の NIC 名を処理できない
要するに、VirtualBox 上で CentOS 7 を実行すると NIC 名が下記のようになりますが、Vagrant で RedHat 系 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
でプロビジョニングを強制適用して起動する必要があります。