はじめに
数年前から環境構築を自動で整えたいと思っていて、
ようやくVagrant + Ansible の勉強をはじめました。
本記事の範囲は
- とりあえず仮想マシンを2台立ち上げ
- Ansibleで操作できるようになる土台が整うまで
を目指し、
vagrant upが満足に立ち上がる様にまでの手順と
自分が躓いた箇所とその対応を記録したものです。
勉強の元ネタ
@hidekuro 様の記事を手始めに勉強させてもらいました。
Vagrant + Ansibleで環境構築をコード化する(1)導入
Vagrantfile はココを元ネタにしております。
環境
母艦:Ubuntu 18.04.2 LTS
仮想マシンの制御用ソフト:libvirtd (libvirt) 4.0.0、Vagrant 2.0.2
子1:Ubuntu 18.04.2 LTS (ホスト名:controller)
子2:Ubuntu 18.04.2 LTS (ホスト名:remote)
操作は可能な限りTerminalからコマンドで行っています。
libvirtのインストール
ubuntu 18.04 上でkvm仮想マシンを動作させるまでの最低限の手順 を参考にインストールしました。
$ sudo apt install libvirt-clients
$ sudo apt install qemu-utils
$ sudo apt install qemu-kvm
$ sudo apt install virtinst
$ sudo apt install libvirt-bin
vagrantの環境設定
~/.vagrant 配下が大容量必要になるとのことなので
Vagrantのホームディレクトリを変更しました。
$ sudo mkdir -p /srv/vagrant/home
$ sudo chown -R user:user /srv/vagrant
$ echo "VAGRANT_HOME=/srv/vagrant/home" >> ~/.bashrc
$ source ~/.bashrc
出来上がったVagrantfile
Vagrant.configure(2) do |config|
# remote-VM
config.vm.define "remote" do |remote|
remote.vm.box = "generic/ubuntu1804"
remote.vm.hostname = "ansible-remote"
remote.vm.network "private_network", ip: "172.16.97.102"
remote.vm.synced_folder './remote/', '/vagrant', type: '9p', :mount_options => ['dmode=775', 'fmode=664']
remote.vm.provider "virtualbox" do |vb|
vb.memory = 1024
vb.cpus = 2
end
remote.vm.provision "shell", inline: <<-SHELL
# DNS config
sed -i.bak -e "s/^DNS=.*$/DNS=8.8.8.8 192.168.122.1/g" /etc/systemd/resolved.conf
systemctl restart systemd-resolved.service
SHELL
end
# control-VM
config.vm.define "control" do |control|
control.vm.box = "generic/ubuntu1804"
control.vm.hostname = "ansible-control"
control.vm.network "private_network", ip: "172.16.97.101"
control.vm.synced_folder './control/', '/vagrant', type: '9p', :mount_options => ['dmode=775', 'fmode=664']
control.vm.provider "virtualbox" do |vb|
vb.memory = 512
vb.cpus = 2
end
control.vm.provision "shell", inline: <<-SHELL
# DNS config
sed -i.bak -e "s/^DNS=.*$/DNS=8.8.8.8 192.168.122.1/g" /etc/systemd/resolved.conf
systemctl restart systemd-resolved.service
apt update
# expect
apt -y install expect
# ansible
apt -y install software-properties-common
apt-add-repository --yes --update ppa:ansible/ansible
apt -y install ansible
apt -y autoremove
SHELL
control.vm.provision "shell", privileged: false, inline: <<-SHELL
# ssh
mkdir -p ~/.ssh
ssh-keygen -N "" -t ed25519 -f ~/.ssh/id_ed25519
rm -f ~/.ssh/known_hosts
# ssh-copy-id
cp -f /vagrant/expect_sendkey.expect ~/expect_sendkey.expect
chmod 774 ~/expect_sendkey.expect
~/expect_sendkey.expect vagrant@172.16.97.102
SHELL
end
end
エラー
その1
$ vagrant up
A Vagrant environment or target machine is required to run this
command. Run `vagrant init` to create a new Vagrant environment. Or,
get an ID of a target machine from `vagrant global-status` to run
this command on. A final option is to change to a directory with a
Vagrantfile and to try again.
カレントディレクトリにVagrantfileが無いだけでした。
カレントディレクトリを移動します。
$ cd ~/.vagrant.d
その2
$ vagrant up
Bringing machine 'remote' up with 'libvirt' provider...
Bringing machine 'control' up with 'libvirt' provider...
==> remote: An error occurred. The error will be shown after all tasks complete.
==> control: An error occurred. The error will be shown after all tasks complete.
An error occurred while executing multiple actions in parallel.
Any errors that occurred are shown below.
An error occurred while executing the action on the 'remote'
machine. Please handle this error then try again:
Name `vagrant_remote` of domain about to create is already taken. Please try to run
`vagrant up` command again.
An error occurred while executing the action on the 'control'
machine. Please handle this error then try again:
Name `vagrant_control` of domain about to create is already taken. Please try to run
`vagrant up` command again.
VAGRANT_HOME の場所をデフォルトから別の場所へ変更したので、
思い切って~/.vagrant
ディレクトリを削除(rm -rf)してしまいました。
ついでに1からやり直したくなったので、Vagrantfileを残して
仮想マシン等(boxes,data,gems,等...)すべて物理削除(rm -rf)してしまった後、
vagrant up
した時に出たエラーです。
libvert側に名前が残っていたので、名前衝突によってエラーがでていました。
$ virsh list --all
Id Name State
----------------------------------------------------
- vagrant_control shut off
- vagrant_remote shut off
$ virsh undefine vagrant_control
Domain vagrant_control has been undefined
$ virsh undefine vagrant_remote
Domain vagrant_remote has been undefined
上記のように、libvirt側も名前を消したら、解消しました。
その3
$ vagrant up
:
:
control: Running: inline script
control: /tmp/vagrant-shell: line 10: unexpected EOF while looking for matching `''
control: /tmp/vagrant-shell: line 14: syntax error: unexpected end of file
==> control: An error occurred. The error will be shown after all tasks complete.
An error occurred while executing multiple actions in parallel.
Any errors that occurred are shown below.
An error occurred while executing the action on the 'control'
machine. Please handle this error then try again:
The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.
「`」の数が合わないとのエラー。
実際にcontrolにログインして/tmp/vagrantファイルを見てみると、、、、
$ cat /tmp/vagrant-shell
:
mkdir -p ~/.ssh
echo -e 'y
' | ssh-keygen -N "" -f ~/.ssh/id_rsa
:
たしかに数が合ってない。。。。
Vagrantfileを確認してみると、、、
:
control.vm.provision "shell", inline: <<-SHELL
:
mkdir -p ~/.ssh
echo -e 'y\n' | ssh-keygen -N "" -f ~/.ssh/id_rsa
:
SHELL
:
ぱっと見おかしいところが無さそうですが、
echo -e 'y\n' | ssh-keygen
の\n が改行として解釈されてしまったようです。
エスケープ処理(\を重ねる)で対応しました。
:
control.vm.provision "shell", inline: <<-SHELL
:
mkdir -p ~/.ssh
echo -e 'y\\n' | ssh-keygen -N "" -f ~/.ssh/id_rsa
:
SHELL
うまく行きました。
その4
$ vagrant up
:
==> control: Installing NFS client...
==> control: An error occurred. The error will be shown after all tasks complete.
An error occurred while executing multiple actions in parallel.
Any errors that occurred are shown below.
An error occurred while executing the action on the 'control'
machine. Please handle this error then try again:
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
apt-get -yqq update
apt-get -yqq install nfs-common portmap
exit $?
Stdout from the command:
Stderr from the command:
E: Failed to fetch http://us.archive.ubuntu.com/ubuntu/pool/main/k/keyutils/keyutils_1.5.9-9.2ubuntu2_amd64.deb Temporary failure resolving 'us.archive.ubuntu.com'
E: Failed to fetch http://us.archive.ubuntu.com/ubuntu/pool/main/libn/libnfsidmap/libnfsidmap2_0.25-5.1_amd64.deb Temporary failure resolving 'us.archive.ubuntu.com'
E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/libt/libtirpc/libtirpc1_0.2.5-1.2ubuntu0.1_amd64.deb Temporary failure resolving 'us.archive.ubuntu.com'
E: Failed to fetch http://us.archive.ubuntu.com/ubuntu/pool/main/r/rpcbind/rpcbind_0.2.3-0.6_amd64.deb Temporary failure resolving 'us.archive.ubuntu.com'
E: Failed to fetch http://us.archive.ubuntu.com/ubuntu/pool/main/n/nfs-utils/nfs-common_1.3.4-2.1ubuntu5.1_amd64.deb Temporary failure resolving 'us.archive.ubuntu.com'
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
NFSのインストール〜設定まわりで失敗したようです。
:
control.vm.synced_folder ".", "/vagrant", :mount_options => ['dmode=775', 'fmode=664']
:
Vagrant provider for libvirt. #Synced_Folders を見てみると若干書式が違っていました。
以下の様に修正してみると、、、、
control.vm.synced_folder './', '/vagrant', type: '9p', :mount_options => ['dmode=775', 'fmode=664']
無事起動できました!
$ vagrant up
:
==> control: Configuring and enabling network interfaces...
==> control: mounting p9 share in guest
==> control: Running provisioner: shell...
control: Running: inline script
:
その5
日本語化
Ubuntuの日本語環境 を参考にaptのリポジトリの更新を行いました
control.vm.provision "shell", inline: <<-SHELL
# Japanese
cd /tmp
wget -nv https://www.ubuntulinux.jp/ubuntu-ja-archive-keyring.gpg
apt-key add /tmp/ubuntu-ja-archive-keyring.gpg
cd /tmp
wget -nv https://www.ubuntulinux.jp/ubuntu-jp-ppa-keyring.gpg
apt-key add /tmp/ubuntu-jp-ppa-keyring.gpg
mkdir -p /etc/apt/sources.list.d
cd /etc/apt/sources.list.d
wget -nv https://www.ubuntulinux.jp/sources.list.d/bionic.list
mv bionic.list ubuntu-ja.list
apt update
SHELL
オプションの -q
はエラーも黙らせてしまうようなので-nv
オプションに変更してます。
あと問題の切り分けのためにwget
、apt-key
を分割しました。
==> control: Running provisioner: shell...
control: Running: inline script
control: wget: unable to resolve host address 'www.ubuntulinux.jp'
control: Warning: apt-key output should not be parsed (stdout is not a terminal)
control: gpg: can't open '/tmp/ubuntu-ja-archive-keyring.gpg': No such file or directory
調べてみるとwgetでファイルが取得できていませんでした。
vagrant sshでログインした後、確認するとIPアドレスではpingが通りますが、
ホスト名だと迷子になってました。どうやらDNSの名前解決に失敗しているようです。
nsswitch.conf弄ったり、--natdnshostresolver1
onにしたり、offにしたり、
色々やってみましたが、destroy -> up を繰り返すたびに挙動が不安定です。
で、やっと見つけましたresolve.confを修正しました。
ほんと探しまくりました(2週間くらい。。。)
control.vm.provision "shell", inline: <<-SHELL
# DNS config
sed -i.bak -e "s/^DNS=.*$/DNS=8.8.8.8 192.168.122.1/g" /etc/systemd/resolved.conf
systemctl restart systemd-resolved.service
SHELL
DNSの接続先を8.8.8.8(GoogleのDNS)、母艦のvirbr0インタフェースに指定しています。
その他、調べていく中で、たくさんの方々の記事を参考にさせて頂きました。
- Vagrant + Ansibleで環境構築をコード化する(2)Playbookを使う
- Vagrant + Ansibleで環境構築をコード化する(3)もっとPlaybook
- Vagrant + Ansibleで環境構築をコード化する(4)さらにPlaybook ~終わり~
- vagrant-libvirtの使い方
- KVMのゲストマシンから外部へ通信できるようにする
- Ubuntu 18.04: NFSサーバのnfs-kernel-serverをインストールする
- Vagrant provisioning using shell - how to setup storm project
- sedコマンドの備忘録
- Ubuntu Linux 18.04 LTSに、VagrantをインストールしてUbuntu Linux 18.04 LTSのboxを起動するまで
- Ubuntu 16.10 その7 - ローカルDNSリゾルバーの仕組みが変わる・systemd-resolvedの採用
- VagrantのトラブルシュートのためにDebugログを出力する
- GitHubでEd25519鍵をつかう