※本稿は以下の一連の記事のうちの一つです。
【Windows】Docker Desktop for WindowsとVagrantの便利な環境を共存させる #1/3【Hyper-V】
【Windows】Docker Desktop for WindowsとVagrantの便利な環境を共存させる #2/3【Hyper-V】
【Windows】Docker Desktop for WindowsとVagrantの便利な環境を共存させる #3/3【Hyper-V】 ←いまココ
Hyper-V通常VM用のネットワーク設定を自動化する
ここまでの作業で、Hyper-Vの仮想ネットワークの設定・WinNATの設定・VagrantでVMインスタンスを立ち上げる、ということができました。
今回設定した仮想ネットワークにはDHCP機能がないため、VMインスタンスのIPアドレスは自動では設定されません。
これを自動化するためには、大きく以下の2通りの方法があります。
- VagrantによるVMインスタンス構築時、IPv4設定を併せて行う
- ホストOS側でDHCPサーバを稼働させ、「Hyper-V Internal with WinNAT」ネットワークに所属するゲストOSがDHCPでIPv4設定できるようにする
VagrantによるVMインスタンス構築時、IPv4設定を併せて行う
まずはこちらの方が簡単です。
Vagrantの「Shell Provisioner」の機能を使います。
Shell Scripts - Provisioning - Vagrant by HashiCorp
https://www.vagrantup.com/docs/provisioning/shell.html
Vagrantfileに下記のように「config.vm.provision」から始まる2行を追加します。Optionとして「inline」を指定し、実行コマンドを直接書きます。
Optionとして「path」を指定し、シェルスクリプトファイルを指定することが可能ですが、今回は使えません。「path」を指定する場合、実行前にファイルをVM内にSSH経由でコピーするという動作になるようで、ネットワークの設定ができていない状態ではファイルのコピーに失敗するからです。
# 下記2行を追加
config.vm.provision "shell",
inline: "ip address add 192.168.254.13/23 dev eth0; route add default gw 192.168.254.1"
先ほど作ったVagrantfileに追加すると、下記のようになるでしょう。
Vagrant.configure("2") do |config|
config.vm.box = "Yojimbo108/AmazonLinux2"
config.vm.provider "hyperv" do |v|
v.memory = 1024
v.cpus = 1
end
config.vm.define :"stdsv3" do |c1|
c1.vm.hostname = "stdsv3"
end
# 下記2行を追加
config.vm.provision "shell",
inline: "ip address add 192.168.254.13/23 dev eth0; route add default gw 192.168.254.1"
end
いったん、vagrant destroyしたのち、再度vagrant upを実行します。初回は失敗し、先ほどと同じ状況になります。
詳細な理由は未調査ですが、「config.vm.provision "shell"」による設定が行われる前にSMBによるフォルダ共有をしようとしたため、エラーになっているように見えます。
またその後、VM内でnetworkサービスがリスタートされています。eth0はDHCPで設定されるようになっているので、networkサービスの実行に失敗します。
$ vagrant up
Bringing machine 'stdsv3' up with 'hyperv' provider...
==> stdsv3: Verifying Hyper-V is enabled...
==> stdsv3: Verifying Hyper-V is accessible...
==> stdsv3: Importing a Hyper-V instance
stdsv3: Creating and registering the VM...
stdsv3: Successfully imported VM
stdsv3: Please choose a switch to attach to your Hyper-V instance.
stdsv3: If none of these are appropriate, please open the Hyper-V manager
stdsv3: to create a new virtual switch.
stdsv3:
stdsv3: 1) DockerNAT
stdsv3: 2) Hyper-V Internal with WinNAT
stdsv3:
stdsv3: What switch would you like to use? 2
stdsv3: Configuring the VM...
==> stdsv3: Starting the machine...
==> stdsv3: Waiting for the machine to report its IP address...
stdsv3: Timeout: 120 seconds
stdsv3: IP: fe80::215:5dff:fe14:2512
==> stdsv3: Waiting for machine to boot. This may take a few minutes...
stdsv3: SSH address: fe80::215:5dff:fe14:2512:22
stdsv3: SSH username: vagrant
stdsv3: SSH auth method: private key
stdsv3:
stdsv3: Vagrant insecure key detected. Vagrant will automatically replace
stdsv3: this with a newly generated keypair for better security.
stdsv3:
stdsv3: Inserting generated public key within guest...
stdsv3: Removing insecure key from the guest if it's present...
stdsv3: Key inserted! Disconnecting and reconnecting using new SSH key...
==> stdsv3: Machine booted and ready!
==> stdsv3: Preparing SMB shared folders...
stdsv3: You will be asked for the username and password to use for the SMB
stdsv3: folders shortly. Please use the proper username/password of your
stdsv3: account.
stdsv3:
stdsv3: Username: ****
stdsv3: Password (will be hidden):
Error! Your console doesn't support hiding input. We'll ask for
input again below, but we WILL NOT be able to hide input. If this
is a problem for you, ctrl-C to exit and fix your stdin.
stdsv3: Password (will be hidden): ********
Vagrant requires administrator access to create SMB shares and
may request access to complete setup of configured shares.
==> stdsv3: Setting hostname...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
service network restart
Stdout from the command:
Restarting network (via systemctl): [FAILED]
Stderr from the command:
Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details.
次にvagrant provisionを実行します。Shell Provisionerが実行され、指定したIPアドレスが設定されます。
$ vagrant provision
==> stdsv3: Running provisioner: shell...
stdsv3: Running: inline script
vagrant sshを実行してログインしてみます。ifconfigコマンドを実行すると、指定したIPアドレスが付与されていることを確認できます。
netstatコマンドを実行すると、IPv4アドレスでSSH接続していることを確認できます。
$ vagrant ssh
Last login: Fri Mar 1 15:21:31 2019
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
[vagrant@stdsv3 ~]$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.254.13 netmask 255.255.254.0 broadcast 0.0.0.0
inet6 fe80::215:5dff:fe14:2512 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:14:25:12 txqueuelen 1000 (Ethernet)
RX packets 7649 bytes 1955138 (1.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 682 bytes 114005 (111.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[vagrant@stdsv3 ~]$ netstat -an|grep ESTABLISHED
tcp 0 0 192.168.254.13:22 192.168.254.1:64372 ESTABLISHE
この状態では、OS再起動時などにIPアドレスが消えてしまいます。
/etc/sysconfig/network-scripts/ifcfg-eth0に必要な設定を書き込みます。その他、必要な設定を実施します。
まとめると以下のような変更が必要になります。
- /etc/sysconfig/network-scripts/ifcfg-eth0に、IPv4設定を書き込む
- /etc/resolv.confに、自分のISPから提供されているDNSサーバを設定する
- /etc/ssh/sshd_configを変更し、SSH経由でユーザ名・パスワードでログインできるように設定する
Vagrantfileを以下のように変更します。実行コマンドの行数が多くなるので、Inline Scriptsの機能を利用します。
Shell Scripts - Provisioning - Vagrant by HashiCorp -> Inline Scripts
https://www.vagrantup.com/docs/provisioning/shell.html#inline-scripts
$provisioner_script = <<-SCRIPT
ip address add 192.168.254.13/23 dev eth0;
route add default gw 192.168.254.1;
echo '# This file has been overwritten by Vagrant Shell Provisioner' > /etc/sysconfig/network-scripts/ifcfg-eth0;
echo BOOTPROTO=none >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo DEVICE=eth0 >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo NM_CONTROLLED=no >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo ONBOOT=yes >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo IPADDR=192.168.254.13 >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo NETMASK=255.255.254.0 >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo GATEWAY=192.168.254.1 >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo DNS1=xxx.xxx.xxx.xxx >> /etc/sysconfig/network-scripts/ifcfg-eth0;
echo DNS2=xxx.xxx.xxx.yyy >> /etc/sysconfig/network-scripts/ifcfg-eth0;
sed -i 's/^nameserver .*$/nameserver xxx.xxx.xxx.xxx\nnameserver xxx.xxx.xxx.yyy/' /etc/resolv.conf
sed -i 's/^PasswordAuthentication .*$/PasswordAuthentication yes/' /etc/ssh/sshd_config;
systemctl reload sshd;
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = "Yojimbo108/AmazonLinux2"
config.vm.provider "hyperv" do |v|
v.memory = 1024
v.cpus = 1
end
config.vm.define :"stdsv3" do |c1|
c1.vm.hostname = "stdsv3"
end
config.vm.provision "shell", inline: $provisioner_script
end
もう一度、vagrant privisionを実行します。その後VMインスタンスにログインし、意図したとおりの設定になっていることを確認します。
ホストOS側でDHCPサーバを稼働させ、「Hyper-V Internal with WinNAT」ネットワークに所属するゲストOSがDHCPでIPv4設定できるようにする
大きく、以下の作業を実施する必要があります。
- Open DHCP Serverをインストールし、Serviceとして実行させる
- Windows Firewallの設定をする
詳細は下記記事にまとめました。
【Windows】非Server EditionでDHCPサーバを構築する【DHCP】 - Qiita
おわりに
Hyper-Vのネットワーク機能は一部不安定なところがあること、VagrantはHyper-Vの仮想ネットワークを操作する機能がないことから、
Hyper-Vを作業用のVMのハイパーバイザとして利用するにはまだ少し難があります。
現状では、VirtualBoxの利便性にはまだまだかなわないという感触です。
しかしながら、Docker Desktop for Windowsは今後、Hyper-Vに注力していくように見えますので、Hyper-Vの重要性が高まっていくように予測しています。
でもこんな話もありますし、これが実現できるんだったら無理してHyper-Vでいろいろ頑張らなくても良いような気がしてきました。
VirtualBox 6.0 から Hyper-V と共存できるはず - Qiita