LoginSignup
20
32

More than 3 years have passed since last update.

Ansible検証環境に特化したVagrantを使ったVM構築 - 複数VM・VM間ssh公開鍵認証設定・共有フォルダ

Posted at

はじめに

Ansibleの検証環境を、手元のVirtualBox上にVagrantを使って構築する。
Vagrantを使うとVMの作成は簡単にできるが、Ansibleの検証環境ということで、以下の条件を追加

  • 一つのVagrantfileで複数VM作成
  • VM間で固定IPアドレスでネットワークがつながる
  • VM間のsshアクセスのため同じ秘密鍵・公開鍵を設定
  • AnsibleのPlaybookなどをホストOSから簡単に編集するための共有フォルダ設定

Ansibleのインストールも含めてもいいけど、まぁそこは1台なので手動で。(対象VMにshellでインストールしてもいいけど)

Vagrantfile

急いでいる人向けに、完成品のVagrantfileをまず置いておきます。
ホストOS上のAnsible資材は~/src/ansibleにあります。

Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"

  # shared folder
  config.vm.synced_folder "~/src/ansible", "/ansible", mount_options: ['dmode=755', 'fmode=644']

  # common ssh-private-key
  config.ssh.insert_key = false
  config.ssh.private_key_path = "~/.vagrant.d/insecure_private_key"

  # copy to private-key
  config.vm.provision "file", source: "~/.vagrant.d/insecure_private_key", destination: "/home/vagrant/.ssh/id_rsa"
  config.vm.provision "shell", privileged: false, inline: <<-SHELL
    chmod 600 $HOME/.ssh/id_rsa
  SHELL

  config.vm.define "ansible-controller" do |ansible_controller|
    ansible_controller.vm.network "private_network", ip: "192.168.244.120"
    # OS hostname
    ansible_controller.vm.hostname = "ansible-controller.localhost"
    ansible_controller.vm.provider "virtualbox" do |vb|
      # Customize the amount of memory on the VM:
      vb.memory = "1024"
      # VM name
      vb.name = "ansible-controller"
    end
  end

  config.vm.define "ansible-node01" do |ansible_node01|
    ansible_node01.vm.network "private_network", ip: "192.168.244.121"
    # OS hostname
    ansible_node01.vm.hostname = "ansible-node01.localhost"
    ansible_node01.vm.provider "virtualbox" do |vb|
      # Customize the amount of memory on the VM:
      vb.memory = "1024"
      # VM name
      vb.name = "ansible-node01"
    end
  end

  config.vm.define "ansible-node02" do |ansible_node01|
    ansible_node01.vm.network "private_network", ip: "192.168.244.122"
    # OS hostname
    ansible_node01.vm.hostname = "ansible-node02.localhost"
    ansible_node01.vm.provider "virtualbox" do |vb|
      # Customize the amount of memory on the VM:
      vb.memory = "1024"
      # VM name
      vb.name = "ansible-node02"
    end
  end
end
コマンド 動作
vagrant up 全VM起動
vagrant halt 全VM停止
vagrant destroy 全VM削除
vagrant reload 全VM Vagrantfile読みなおし
vagrant ssh ansible-controller ansible-controllerへsshアクセス
vagrant up ansible-controller ansible-controllerのみ起動
vagrant halt ansible-controller ansible-controllerのみ停止

概要図

vagrant for ansible.png


以下解説

1ファイル複数VMの設定

  config.vm.define "ansible-controller" do |ansible_controller|
    ansible_controller.vm.network "private_network", ip: "192.168.244.120"
    # OS hostname
    ansible_controller.vm.hostname = "ansible-controller.localhost"
    ansible_controller.vm.provider "virtualbox" do |vb|
      # Customize the amount of memory on the VM:
      vb.memory = "1024"
      # VM name
      vb.name = "ansible-controller"
    end
  end

  config.vm.define "ansible-node01" do |ansible_node01|
    ansible_node01.vm.network "private_network", ip: "192.168.244.121"
    # OS hostname
    ansible_node01.vm.hostname = "ansible-node01.localhost"
    ansible_node01.vm.provider "virtualbox" do |vb|
      # Customize the amount of memory on the VM:
      vb.memory = "1024"
      # VM name
      vb.name = "ansible-node01"
    end
  end

だいたいこの部分。(node02は省略)
Rubyの読み書きができずに、初めは既存部分からコピペでうまくいかなかったけど、

  config.vm.define "ansible-controller" do |ansible_controller|

に対して

- config.vm.network
+ ansible_controller.vm.network

と、定義したansible_controllerで設定を定義してやる必要がある。
これをVMの個数分(そして、ホスト名やIPアドレスなどのVM毎に設定が異なる内容に対して)繰り返す。

各VMで共通の定義については、VM毎の設定に書かずに既存の定義部分のままでよい。

  config.vm.box = "centos/7"

ベースになるBoxの種類とかね。

VM間で固定IPアドレスでネットワークがつながる

デフォルトの(インターネットアクセスもできる)NAT用のアドレスだと、VM間でpingは通るけど、IPアドレスが固定ではないので検証には不向き。
ついでにホストOSからもアクセスできないし。

ということでホストオンリーアダプタを使って同セグメントの固定IPアドレスを設定する。

これはVM毎に設定する。
この部分。

  config.vm.define "ansible-controller" do |ansible_controller|
    ansible_controller.vm.network "private_network", ip: "192.168.244.120"
    #[...]
  end

  config.vm.define "ansible-node01" do |ansible_node01|
    ansible_node01.vm.network "private_network", ip: "192.168.244.121"
    #[...]
  end

  config.vm.define "ansible-node02" do |ansible_node01|
    ansible_node01.vm.network "private_network", ip: "192.168.244.122"
    #[...]
  end

VM間のsshアクセスのため同じ秘密鍵・公開鍵を設定

あきらめて手動で設定したろかーと最も苦労した部分。。

Vagrantのssh関連は特に指定がない場合は、VM毎に秘密鍵・公開鍵が作成され、ホストOSからのvagrant ssh [hostname]実行によるsshアクセスはVM毎の公開鍵で行われる。
そのため、この公開鍵ではVM間の公開鍵認証には使えない。
また、秘密鍵はVM内には保持されず、ホストOS上のみに配置される。

作成・使用されるssh鍵は、VM実行中に以下のコマンドで確認できる。

zaki@mascarpone% vagrant ssh-config
Host ansible-controller
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/Users/zaki/src/vagrant/ansible/.vagrant/machines/ansible-controller/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

Host ansible-node01
  HostName 127.0.0.1
  User vagrant
  Port 2200
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/Users/zaki/src/vagrant/ansible/.vagrant/machines/ansible-node01/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

zaki@mascarpone%

IdentityFileに(vagrant sshで)使用する秘密鍵のパスが表示され、VM毎に異なるのがわかる。

そこでまずは、「各VMで同じ秘密鍵・公開鍵を使うための設定」を行う。

  config.ssh.insert_key = false

このconfig.ssh.insert_keyfalseにする設定によって、「VM毎にsshの秘密鍵・公開鍵を作成・設定する」という動作が無くなる。

次に、config.ssh.private_key_pathで、替わりの秘密鍵を指定する。(ちなみにデフォルトで~/.vagrant.d/insecure_private_keyの鍵が使用される)
実はVagrantをインストールすると、ホームディレクトリ以下~/.vagrant.d/insecure_private_keyにパスフレーズなしの共通設定用の鍵が生成されている。今回はこれを使う。
もちろんssh-keygenでパスフレーズなしの鍵を別途作成してそれを使っても良い。

  config.ssh.private_key_path = "~/.vagrant.d/insecure_private_key"

この設定の状態でssh-configを確認すると、各VMで同じ秘密鍵・公開鍵を使用する設定になる。

zaki@mascarpone% vagrant ssh-config
Host ansible-controller
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/Users/zaki/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

Host ansible-node01
  HostName 127.0.0.1
  User vagrant
  Port 2200
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/Users/zaki/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

zaki@mascarpone%

ただし、このままでは、ホストOS→ゲストOS間のsshアクセスで使用するssh鍵が、各ゲストOSで同じになっただけで、各ゲストOS上にこの秘密鍵がまだないため、ゲストOS同士で公開鍵認証ができない。(秘密鍵がホストOS上にしかないため)

そこで、このホストOS上の秘密鍵を、作成したVM上にコピーする処理を追加する。

  config.vm.provision "file", source: "~/.vagrant.d/insecure_private_key", destination: "/home/vagrant/.ssh/id_rsa"

ホストOS上にあるファイルをゲストOSにコピーするにはFile Provisionerを使用する。
(大項目にPushなんてあるから、こっち使ってできると思い込んでいろいろやってもうまくいかなかったのであきらめかけたけど、別の機能だった…)
これでホストOS上のsource: "~/.vagrant.d/insecure_private_key"のファイルを、ゲストOSのdestination: "/home/vagrant/.ssh/id_rsa"へ配布できる。

ただしこれだけだと、mode設定が維持できず他者にもread権限がついてしまってssh実行時にエラーとなるため、手動で権限設定を追加する。
File Provisionで指定できればいいのによくわからなかったので、shellで。

  config.vm.provision "shell", privileged: false, inline: <<-SHELL
    chmod 600 $HOME/.ssh/id_rsa
  SHELL

これで各VMで同じ秘密鍵・公開鍵を使いつつ、VM内に秘密鍵の配布まで設定できる。

AnsibleのPlaybookなどをホストOSから簡単に編集するための共有フォルダ設定

Ansibleの資材はホストOSの~/src/ansibleにあるとする。
この部分。

  # shared folder
  config.vm.synced_folder "~/src/ansible", "/ansible", mount_options: ['dmode=755', 'fmode=644']

ホストOSの~/src/ansibleを、ゲストOSの/ansibleにマウントする。
オプションを何もつけない場合、ファイルやディレクトリが777のフルオープン状態になり、Ansibleの実行で警告が出力されるなど検証に差し支える。

 [WARNING] Ansible is being run in a world writable directory (/ansible/practice), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir

で、共有フォルダ設定自体もすんなりとはいかなかったけど、こちらはエラーメッセージでググればすぐに答えにたどり着いたので問題なかった。
初実行時はこんなエラーが出力された。

==> default: Mounting shared folders...
    default: /vagrant_data => C:/Users/zaki/src/vagrant/data
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

mount -t vboxsf -o uid=1000,gid=1000 vagrant_data /vagrant_data

The error output from the command was:

mount: unknown filesystem type 'vboxsf'

調べた感じだと、vboxsfでマウントするためのGuest Additionsが古いのが原因っぽい。
Vagrantのプラグインvagrant-vbguestを入れておくと、VM起動時によしなにしてくれるらしい。

Vagrantで共有フォルダのマウントに失敗するときの対処方法 - Qiita

ので、設定する。

プラグインインストール

zaki@mascarpone% vagrant plugin install vagrant-vbguest
Installing the 'vagrant-vbguest' plugin. This can take a few minutes...
Installed the plugin 'vagrant-vbguest (0.18.0)'!
zaki@mascarpone% vagrant plugin list
vagrant-disksize (0.1.3, global)
vagrant-vbguest (0.18.0, global)

現在のGuest Additionsの確認

zaki@mascarpone% vagrant vbguest --status
[default] No Virtualbox Guest Additions installation found.

なんと入っていなかった。

Guest Additionsのインストール(更新)

vagrant vbguestと引数・オプションなしで実行する。

zaki@mascarpone% vagrant vbguest
[default] No Virtualbox Guest Additions installation found.
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ty1.mirror.newmediaexpress.com
 * extras: ty1.mirror.newmediaexpress.com
 * updates: ty1.mirror.newmediaexpress.com
 :
 :
Dependencies Resolved

================================================================================
 Package                   Arch      Version                   Repository  Size
================================================================================
Installing:
 gcc                       x86_64    4.8.5-36.el7_6.2          updates     16 M
 kernel-devel              x86_64    3.10.0-957.5.1.el7        updates     17 M
 kernel-devel              x86_64    3.10.0-957.21.3.el7       updates     17 M
 perl                      x86_64    4:5.16.3-294.el7_6        updates    8.0 M
:
:

インストール処理が始まる。

:
Dependency Updated:
  glibc.x86_64 0:2.17-260.el7_6.5     glibc-common.x86_64 0:2.17-260.el7_6.5
  libgcc.x86_64 0:4.8.5-36.el7_6.2    libgomp.x86_64 0:4.8.5-36.el7_6.2

Complete!
Copy iso file C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso into the box /tmp/VBoxGuestAdditions.iso
Mounting Virtualbox Guest Additions ISO to: /mnt
mount: /dev/loop0 is write-protected, mounting read-only
Installing Virtualbox Guest Additions 5.2.26 - guest version is unknown
Verifying archive integrity... All good.
Uncompressing VirtualBox 5.2.26 Guest Additions for Linux........
VirtualBox Guest Additions installer
Copying additional installer modules ...
Installing additional modules ...
VirtualBox Guest Additions: Building the VirtualBox Guest Additions kernel
modules.  This may take a while.
VirtualBox Guest Additions: To build modules for other installed kernels, run
VirtualBox Guest Additions:   /sbin/rcvboxadd quicksetup <version>
VirtualBox Guest Additions: Building the modules for kernel
3.10.0-957.5.1.el7.x86_64.
VirtualBox Guest Additions: Starting.
Redirecting to /bin/systemctl start vboxadd.service
Redirecting to /bin/systemctl start vboxadd-service.service
Unmounting Virtualbox Guest Additions ISO from: /mnt
zaki@mascarpone% vagrant vbguest --status
[default] GuestAdditions 5.2.26 running --- OK.
zaki@mascarpone%

これでvagrant reloadすれば、共有フォルダ設定が有効になる。

20
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
32