使用Vagrant构建专门用于Ansible验证环境的虚拟机 – 包括多个虚拟机、虚拟机之间的SSH公钥认证设置和共享文件夹
首先
使用Vagrant在我的VirtualBox上构建Ansible验证环境。虽然使用Vagrant可以轻松创建虚拟机,但考虑到Ansible的验证环境,我还添加了以下条件。
-
- 一つのVagrantfileで複数VM作成
-
- VM間で固定IPアドレスでネットワークがつながる
-
- VM間のsshアクセスのため同じ秘密鍵・公開鍵を設定
- AnsibleのPlaybookなどをホストOSから簡単に編集するための共有フォルダ設定
虽然包括Ansible的安装也可以,但因为只有一台主机,所以可以手动安装(也可以在目标虚拟机中使用shell安装)。
- Vagrantとは?についてはこちら
Vagrantfile (虚拟机配置文件)
为了迎合急于需要的人,首先提供完整的Vagrantfile。
主机OS上的Ansible资源位于~/src/ansible目录下。
# -*- 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のみ停止简图
以下是对这个问题的解释
配置多个虚拟机的文件
-
- Multi-Machine – Vagrant by HashiCorp
- [Vagrant] Vagrant で複数のVM を立ち上げて、お互いに通信できるようにするには [VirtualBox] – Qiita
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控制器上定義設定。並且需要將這個設定重複應用於每個虛擬機器上 (而且,對於每個虛擬機的主機名稱和IP地址等有不同設定的內容,也需要重複設定)。
关于各个虚拟机共享的定义,无需在每个虚拟机的设置中书写,可以保持现有的定义部分不变。
config.vm.box = "centos/7"
基于的Box种类之类的吗。
在虚拟机之间通过固定IP地址建立网络连接。
使用默认(具有互联网访问功能)的NAT地址,虚拟机之间可以互相ping通,但由于IP地址不固定,不适合进行验证工作。
另外,也无法从主机操作系统访问它。
因此,使用主机模式适配器来设置同一网段的固定IP地址。
-
- Vagrantを使ったVirtualBoxへのVM構築 – Qiita
- Ubuntu 18.04(on VirtualBox) ホストOSからの通信 – Qiita
每个虚拟机都需要设置这个。这个部分。
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相关操作会为每个虚拟机创建一对密钥,其中包括私钥和公钥。来源于主机操作系统的vagrant ssh [hostname]命令将使用相应虚拟机的公钥进行SSH访问。
因此,这个公钥无法用于虚拟机之间的公钥认证。
此外,私钥不会存储在虚拟机内部,而只会放置在主机操作系统上。
可以使用以下命令来确认在VM运行时创建和使用的SSH密钥。
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%
在使用vagrant ssh时,会显示IdentityFile中使用的私钥路径,并且可以看到每个虚拟机的路径是不同的。
首先,在每个虚拟机上进行“使用相同的私钥和公钥设置”的配置。
config.ssh.insert_key = false
通过将config.ssh.insert_key设置为false,将不再需要“为每个虚拟机创建和配置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时,每个虚拟机都将使用相同的密钥对。
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%
然而,如果保持现状,用于主机操作系统到客户操作系统之间的ssh访问的ssh密钥将仅在每个客户操作系统上保持相同,因此,由于每个客户操作系统上尚未存在该私钥,客户操作系统之间将无法进行公钥认证。(由于私钥仅存在于主机操作系统上)
因此,需要添加将该主机操作系统上的密钥拷贝到创建的虚拟机上的过程。
config.vm.provision "file", source: "~/.vagrant.d/insecure_private_key", destination: "/home/vagrant/.ssh/id_rsa"
使用File Provisioner将主机操作系统上的文件复制到客户操作系统中。
(因为有推送等大项目,所以我误以为可以使用这个功能,做了很多尝试但无法成功,所以差点放弃了,但原来是另外一个功能…)
现在可以使用这个功能将主机操作系统上的源文件:”~/.vagrant.d/insecure_private_key”分发到客户操作系统的目标位置:”/home/vagrant/.ssh/id_rsa”。
然而,只有这样的话,无法维持mode设置,而且其他人也会获得读取权限,导致在执行ssh时出现错误,因此需要手动添加权限设置。
希望可以通过File Provision进行指定,但我不是很清楚,所以使用了shell来处理。
config.vm.provision "shell", privileged: false, inline: <<-SHELL
chmod 600 $HOME/.ssh/id_rsa
SHELL
使用此方法,在每个虚拟机上使用相同的私钥和公钥,并在虚拟机内设置私钥分发。
为了方便从主机操作系统上编辑Ansible的Playbook等文件,设置共享文件夹。
假设Ansible的资料存放在主机的~/src/ansible目录下。
# shared folder
config.vm.synced_folder "~/src/ansible", "/ansible", mount_options: ['dmode=755', 'fmode=644']
如果没有添加任何选项,将主机操作系统的~/src/ansible挂载到客户操作系统的/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
-
- vagrant で synced_folder の権限変更 – Qiita
- Basic Usage – Synced Folders – Vagrant by HashiCorp
所以,共享文件夹的设置本身并不顺利,但是在这方面通过错误信息搜索很快找到了答案,所以没有问题。
在首次运行时,输出了这样的错误。
==> 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'
根据我的调查,问题似乎是因为Guest Additions太旧而导致无法使用vboxsf进行挂载。如果安装了Vagrant插件vagrant-vbguest,在启动虚拟机时会自动做一些处理。
当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命令,共享文件夹设置将会生效。