1、Vagrant快速上手
1.1 Vagrant基础介绍
1.1.1 什么是Vagrant?
Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境。它 使用Oracle的开源VirtualBox虚拟化系统,使用 Chef创建自动化虚拟环境。
注意:
- Vagrant的运行,需要依赖于某项具体的虚拟化技术,比如:
virtualbox、vmware、Hyper-V等 - vagrant其实就是一个管理工具,并不是某项具体的虚拟化技术
1.1.2 Vagrant的构成
base box:vagrant使用的基础镜像文件,可以理解为Vagrant中使用的Linux的镜像文件;providers:镜像文件安装在哪个虚拟机上,vagrant 必须依赖于 Provide,Provide有:vmware、virtualbox、hyper-v,其中,vmware是收费,vartualbox是免费,推荐、hyper-v是微软自带的;provisioners:启动时、启动后,去执行一些shell脚本(如配置网络、安装软件环境等)
1.1.3 为什么需要Vagrant?
常见的问题:
- 开发自己需要搭建开发环境,经常会因某些原因,导致编译出错,无法安装。
- 由于开发环境的不一致性,会导致A程序员写的代码,在B程序员的电脑上跑,可能会出错。
针对以上问题,刚开始的解决办法:
- 在公司的某台服务器上,安装virtualbox虚拟化软件,然后在这个虚拟化平台上,安装虚拟机,并且配置好虚拟机。
- 把配置好的虚拟机IP和用户名、密码交付开发人员
- 根据公司统一的部署文档,搭建开发环境
缺点:每次都要手工创建虚拟机,配置虚拟机的参数,容易出错
后来Vagrant的出现,则很好的解决了上面的问题。Vagrant 可以很好的结合虚拟机(如VirtualBox、Hyper-V、VMWare这个版本要付费,对应的Vagrant 也是收费),根据配置文件,轻松的创建多台虚拟机实验环境。我们可以在配置文件中指定,包括从哪里去下载这个虚拟机、网络该如何连通、主机名、IP地址,甚至可以指定开机后自动配置的脚本。
1.1.4 Vagrant可以做什么?
- 新建、删除虚拟机
- 配置虚拟机的运行参数(例如CPU,内存,硬盘等)
- 管理虚拟机的运行状态(关闭,启动,停止,挂起虚拟机)
- 自动化配置和安装开发环境(通过脚本)
- 打包和分发虚拟机运行环境
1.1.5 Vagrant的特点
- 支持跨平台(支持windows、linux、苹果)
- 可移动性好(由于软件包比较小)
- 自动部署,无需人工参与
- 减少人力培训成本(避免每来一个同事,花时间搭建环境)
- 统一公司的开发环境(统一开发、测试的环境)
1.2 Vagrant的安装
下载Vagrant安装包:www.vagrantup.com/downloads
根据不同的操作系统下载不同的安装包,然后一步一步傻瓜式安装即可。
为了能够创建虚拟机,你需要安装VirtualBox,Windows用户也可以使用系统自带的Hyper-V。
验证是否成功安装:
vagrant --version
安装玩Vagrant需要重启电脑!
1.3vagrant创建虚拟机
1.3.1 Vagrant通过Hyper-V创建虚拟机
3.1.1.1 寻找基础镜像
app.vagrantup.com/boxes/searc…
这里以https://app.vagrantup.com/generic/boxes/ubuntu2004这个镜像进行演示。
1.3.1.2 创建Vagrantfile
vagrant init generic/ubuntu2004
此时会在当前目录下生成一个Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "generic/ubuntu2004"
end
1.3.1.3 创建虚拟机
然后通过下面的命令就可以启动一个虚拟机了:
# 需要在管理员权限下打开的终端中执行
vagrant up --provider=hyperv --color
--provider=hypterv:指定通过Hypter-V创建虚拟机--color:日志输出带颜色,更方便查看过程
执行过程如下:
1.3.1.4 查看是否成功创建
此时打开电脑的Hypter-V管理器就可以看到一台虚拟机正在运行了:
当然也可以通过下面的命令查看:
vagrant status
结果如下:
1.3.2 Vagrant通过VirtualBox创建虚拟机
1.3.2.1 寻找基础镜像
此处以generic/centos7镜像进行演示,地址为:app.vagrantup.com/generic/box…
1.3.2.2 创建Vagrantfile
vagrant init generic/centos7
此时会在当前目录下生成一个Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "generic/centos7"
end
1.3.2.3 创建虚拟机
vagrant up --provider=virtualbox --color
# 也可以不用指定 --provider=virtualbox 这是vagrant默认的provider
运行成功后,在VirtualBox中也出现了一台正在运行的虚拟机:
1.3.3 Vagrant通过VmWare创建虚拟机
1.3.3.1 下载VmWare插件
下载完成之后,双击软件安装,安装完成之后,在终端输入下面的命令,完成插件安装:
vagrant plugin install vagrant-vmware-fusion
vagrant plugin install vagrant-vmware-workstation
vagrant-vmware-desktop这个插件是用于macOS的Vagrant VMware Fusion插件和用于Linux和Windows的Vagrant VMware Workstation插件的统一。
1.3.3.2 查找镜像
以app.vagrantup.com/centos/boxe…
vagrant init centos/7
此时会在当前目录下生成一个Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
end
1.3.3.3 创建虚拟机
vagrant up --provider vmware_desktop
==目前安装玩插件之后,没有能够正常调用VmWareWorkStation创建虚拟机,可能是需要购买付费版的Vagrant和VmWareWorkStation==
1.3.4 说明
国内由于网络问题,很可能下载Vagrant的base box失败或者很慢,我们可以去找一些国内的镜像源。例如:
-
中科大CentOS镜像源:mirrors.ustc.edu.cn/centos-clou…
-
中科大Ubuntu镜像源:mirrors.ustc.edu.cn/ubuntu-clou…
使用的时候只需要在对应的镜像源找到对应的镜像,然后在Vagrantfile中编辑或者添加配置项:
config.vm.box_url = "https://mirrors.ustc.edu.cn/centos-cloud/centos/7/vagrant/x86_64/images/CentOS-7.box"
或者直接通过URL初始化一个Vagrantfile文件:
vagrant init centos7 https://mirrors.ustc.edu.cn/centos-cloud/centos/7/vagrant/x86_64/images/CentOS-7.box
1.4 Vagrant基本操作
- 启动虚拟机:
vagrant up - 检查虚拟机状态:
vagrant status - SSH连接:
vagrant ssh <name>- 通过VirtualBox建立的虚拟机,是通过和本机127.0.0.1上任意端口进行端口映射实现登陆的
- 登陆后需要切换到root用户,执行
sudo -i即可 - 如果需要通过其他工具(Xshell)连接root用户,需要:
- 修改
/etc/ssh/sshd_config文件,保证PermitRootLogin yes - 设置root密码:
passwd
- 修改
- 查看SSH配置文件:
vagrant ssh-config <name> - 休眠虚拟机:
vagrant suspend <name> - 唤醒虚拟机:
vagrant remuse <name> - 重新启动虚拟机:
vagrant reload <name> - 关闭虚拟机:
vagrant halt <name> - 删除/移除虚拟机:
vagrant destroy <name>
2、Vagrantfile配置
2.1 和Vagrant相关的目录
2.1.1 .vagrant/
.vagrant/目录是与当前路径下Vagrantfile创建的虚拟机相关的一些配置文件:
│ Vagrantfile
│
└─.vagrant
├─bundler
│ global.sol
│
├─machines # 存放虚拟机及相关配置
│ └─default # 名为 default 的一台虚拟机
│ └─hyperv # provider为hyperv
│ │ action_configure
│ │ action_provision
│ │ action_set_name
│ │ box_meta # base box的元信息
│ │ creator_uid
│ │ id # 虚拟机的Id
│ │ index_uuid
│ │ private_key # 虚拟机的私钥,用户SSH登陆
│ │ synced_folders # 同步文件夹
│ │ vagrant_cwd
│ │
│ └─Virtual Hard Disks # 虚拟机的磁盘
│ generic-ubuntu2004-hyperv.vhdx
│
└─rgloader
loader.rb
2.1.2 box文件目录
~/.vagrant.d/
C:\USERS\STARYJIE\.VAGRANT.D
│ insecure_private_key
│ plugins.json
│ setup_version
│
├─boxes # box 存放的目录
│ ├─centos-VAGRANTSLASH-7
│ │ │ metadata_url
│ │ │
│ │ └─2004.01
│ │ └─vmware_desktop
│ │ │ box_update_check
│ │ │ centos-7-1-1.x86_64-disk1-000001.vmdk
│ │ │ centos-7-1-1.x86_64-disk1-000002.vmdk
│ │ │ centos-7-1-1.x86_64-disk1.vmdk
│ │ │ centos-7-1-1.x86_64-Snapshot1.vmsn
│ │ │ centos-7-1-1.x86_64-Snapshot2.vmsn
│ │ │ centos-7-1-1.x86_64.vmsd
│ │ │ centos-7-1-1.x86_64.vmx
│ │ │ centos-7-1-1.x86_64.vmxf
│ │ │ metadata.json
│ │ │ Vagrantfile
│ │ │
│ │ └─centos-7-1-1.x86_64-disk1.vmdk.lck
│ │ M21315.lck
│ │
│ ├─centos7
│ └─0
│ └─virtualbox
│ box.ovf
│ centos-7-1-1.x86_64.vmdk
│ metadata.json
│ Vagrantfile
│
│
├─bundler
│ global.sol
│
├─data
│ │ checkpoint_cache
│ │ checkpoint_cache-vmp
│ │ checkpoint_cache-vmu
│ │ checkpoint_signature
│ │ checkpoint_signature-vmp
│ │ checkpoint_signature-vmu
│ │ lock.dotlock.lock
│ │ lock.machine-action-d0779061b33884d75a8d60d422ac2f29.lock
│ │ lock.machine-action-e33d21d50addde8788f46f44eb85a375.lock
│ │
│ ├─fp-leases
│ │ 127_0_0_1_2222
│ │
│ └─machine-index
│ index
│ index.lock
│
├─rgloader
│ loader.rb
│
└─tmp
2.2 Vagrant VM的设置
Vagrant.configure("2") do |config|
config.vm.box = "generic/centos7"
end
Vagrant.configure("2"):使用第2版本的Vagrantfile语法do与end对应,必须成对出现|config|表示定义一个变量,在do和end之间,config变量生效config.vm.box = "generic/centos7":设置VM的box
以上是Vagrantfile关于VM配置的必选项,还有以下一些可选项:
-
设置主机名:
config.vm.hostname = "centos7-demo" -
是否将同步文件夹写入fstab:
config.vm.allow_fstab_modification = true如果为 true,将为同步文件夹添加 fstab 条目。如果为 false,Vagrant 不会对 fstab 进行任何修改。请注意,这可能意味着文件夹不会在机器重新启动时自动挂载。默认为
true。 -
设置默认分配给NAT接口上VM的Mac地址:
config.vm.base_mac -
设置VM的IP地址:
config.vm.base_address -
Vagrant等待机器启动并访问的超时时间:
config.vm.boot_timeoutVagrant 等待机器启动并可以访问的时间(以秒为单位)。默认情况下为 300 秒。
-
设置VM的内存大小,单位是
MB:config.vm.memory -
设置VM的CPU个数:
config.vm.cpus
更多配置请参考官方文档:www.vagrantup.com/docs/vagran… 文档中关于
config.vm的说明。
2.2.1 对Provider的个性化配置
根据不同的Provider,vagrant还提供了个性化配置。
因为Hyper-V不支持很多vagrant的配置,然而VmWare又是收费的,所以这里只讲关于VirtualBox的个性化配置。
对VirtualBox的个性化配置需要通过vb.customize配置来定制,主要参考VBoxManage modifyvm命令的使用方法:
#修改vb.name的值
v.customize ["modifyvm", :id, "--name", "mfsmaster2"]
#如修改显存,缺省为8M,如果启动桌面,至少需要10M,如下修改为16M:
vb.customize ["modifyvm", :id, "--vram", "16"]
#调整虚拟机的内存
vb.customize ["modifyvm", :id, "--memory", "1024"]
#指定虚拟CPU个数
vb.customize ["modifyvm", :id, "--cpus", "2"]
#增加光驱:
vb.customize ["storageattach",:id,"--storagectl", "IDE Controller","--port","0","--device","0","--type","dvddrive","--medium","/Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso"]
#注:meduim参数不可以为空,如果只挂载驱动器不挂在iso,指定为“emptydrive”。如果要卸载光驱,medium传入none即可。
#从这个指令可以看出,customize方法传入一个json数组,按照顺序传入参数即可。
#json数组传入多个参数
v.customize ["modifyvm", :id, "--name", “mfsserver3", "--memory", “2048"]
更多关于VirtualBox的个性化配置需要参考VirtualBox的官方文档:www.virtualbox.org/manual/
2.3 Vagrant SSH连接的配置
2.3.1 配置ssh免密登陆
Vagrant在创建VM的时候就已经设置好了用于SSH连接的密钥对。所以我们在VM启动好之后可以直接通过vagrant ssh <name>进行免密登陆。
可以通过vagrant ssh-config查看当前SSH连接相关的配置:
$ vagrant ssh-config
Host default
HostName 172.25.153.203
User vagrant
Port 22
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile E:/VagrantData/Hyperv/centos7/.vagrant/machines/default/hyperv/private_key
IdentitiesOnly yes
LogLevel FATAL
Vagrant提倡使用密钥进行登录,并且大部分Vagrant的box已经默认禁用了使用密码登陆。如果你必须使用密码登陆,则需要先通过
vagrant ssh <name>进入VM中,通过sudo -i切换为root用户,并且修改/etc/ssh/sshd_config的配置,将PasswordAuthentication no改为PasswordAuthentication yes,然后重启sshd服务:systemctl restart sshd.service。
vagrant ssh-config输出的内容我们可以直接添加到~/.ssh/config文件中,就可以直接通过ssh default进行免密登陆了:
ssh default
登陆效果:
2.3.2 insecure_private_key
- Vagrant在
~/.vagrant.d/目录下存在一个一个insecure_private_key文件,这个私钥是默认存在于vagrant程序中的,所有安装了vagrant程序的用户的insecure_private_key文件都是一样的,这就意味着别人都可以通过这个insecure_private_key来连接我们的VM。 - 但是,Vagrant在创建VM的时候会自动发现这个不安全的
insecure_private_key,并且会自动重新生成一个安全的密钥用于替换insecure_private_key
但是很多时候我们可能需要一次性创建很多的VM进行测试,那么vagrant就会给我们创建对应很多的密钥对,我们在测试的时候每个VM就需要使用对应的密钥来进行连接测试,这样非常不方便,所以,Vagrant给我们提供了一个开关,这个配置就是:
config.ssh.insert_key:默认情况下或者如果设置为 true,Vagrant 将自动插入一个用于 SSH 的密钥对,如果检测到,则替换机器内 Vagrant 的默认不安全密钥。 如果您已经使用私钥对您的客人进行身份验证,或者依赖于默认的不安全密钥,则不会使用此选项。 如果设置为 false,Vagrant 将不会自动向来宾添加密钥对。
如果将config.ssh.insert_key设置为false,那么在创建VM的时候就不会创建新的密钥对,而是使用默认的insecure_private_key:
此时通过vagrant ssh-config可以看到:
Host default
HostName 172.25.151.122
User vagrant
Port 22
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile C:/Users/StaryJie/.vagrant.d/insecure_private_key # 使用了默认的insecure_private_key
IdentitiesOnly yes
LogLevel FATAL
2.3.3 使用自定义的密钥对
- 待补充
2.4 一个Vagrantfile创建多个VM
2.4.1 一次创建多个VM
编写一个Vagrantfile:
Vagrant.configure("2") do |config|
# 设置 box
config.vm.box = "generic/centos7"
# 设置box版本
config.vm.box_version = "4.1.10"
# 设置VM的主机名
config.vm.hostname = "centos7-demo"
# 设置不默认生成密钥对
# config.ssh.insert_key = false
# 定义多台虚拟机,共享上面的配置
config.vm.define "web-server"
config.vm.define "database"
end
此时通过vagrant up就会创建两台VM,但是它们的主机名及其他配置都是一样的:
这是因为,通过config.vm的设置是全局的,所以每一个VM都会生效。
2.4.2 位每个VM个性化配置
如果要设置每个VM各自不同的配置,则需要针对每一个VM单独设置它们各自的配置:
Vagrant.configure("2") do |config|
# 设置 box
config.vm.box = "generic/centos7"
# 设置box版本
config.vm.box_version = "4.1.10"
# 设置VM的主机名
config.vm.hostname = "centos7-demo"
# 设置不默认生成密钥对
# config.ssh.insert_key = false
# 定义多台虚拟机,共享上面的配置
# 为 web-server 定义局部配置,变量为 web
config.vm.define "web-server" do |web|
# 设置主机名
web.vm.hostname = "web"
# 设置box版本
web.vm.box_version = "4.1.12"
end
# 为 database 定义局部配置,变量为 db
config.vm.define "database" do |db|
# 设置主机名
db.vm.hostname = "db"
end
end
这里的web和db都属于局部变量,它们的优先级会比全局变量要高,所以它们各自的配置就不一样了:
当然,如果你想为每个VM设置不同的操作系统也是可以的:
Vagrant.configure("2") do |config|
# 设置 box
config.vm.box = "generic/centos7"
# 设置box版本
# config.vm.box_version = "4.1.10"
# 设置VM的主机名
config.vm.hostname = "centos7-demo"
# 设置不默认生成密钥对
# config.ssh.insert_key = false
# 定义多台虚拟机,共享上面的配置
config.vm.define "web-server" do |web|
web.vm.hostname = "web"
web.vm.box_version = "4.1.12"
end
config.vm.define "database" do |db|
db.vm.box = "generic/ubuntu2004"
db.vm.box_version = "4.1.10"
db.vm.hostname = "db"
end
end
2.4.3 优化Vagrantfile
host_list = [
{
:name => "web-server",
:hostname => "web",
:box => "generic/centos7",
:box_version => "4.1.12"
},
{
:name => "database",
:hostname => "db",
:box => "generic/ubuntu2004",
:box_version => "4.1.10"
},
{
:name => "redis",
:hostname => "cache",
:box => "generic/centos8",
:box_version => "4.1.12"
}
]
Vagrant.configure("2") do |config|
# 遍历
host_list.each do |item|
# 获取到每一台VM
config.vm.define item[:name] do |host|
# 设置base box
host.vm.box = item[:box]
# 设置box版本
host.vm.box_version = item[:box_version]
# 设置主机名
host.vm.hostname = item[:hostname]
end
end
end
2.5 文件同步
2.5.1 VirtualBox文件同步
host_list = [
{
:name => "web-server",
:hostname => "web",
:box => "generic/centos7",
:box_version => "4.1.12"
}
]
Vagrant.configure("2") do |config|
# 遍历
host_list.each do |item|
# 获取到每一台VM
config.vm.define item[:name] do |host|
# 设置base box
host.vm.box = item[:box]
# 设置box版本
host.vm.box_version = item[:box_version]
# 设置主机名
host.vm.hostname = item[:hostname]
end
end
end
此时创建的VirtualBox虚拟机会默认将当前目录通过Rsync同步到虚拟机的/vagrant路径下,但是如果你在虚拟机内部修改文件,并不会同步到本地。
那么怎么解决这个问题呢?
2.5.1.1 修改box的Vagrantfile
为了解决这个问题,我们需要先找到当前VM使用的box的存放路径,然后修改对应目录下的Vagrantfile,删除下面这个配置:
config.vm.synced_folder ".", "/vagrant", type: "rsync"
2.5.1.2 安装vagrant-vbguest插件
# 查看已安装的插件
vagrant plugin list
# 安装指定的插件
vagrant plugin install vagrant-vbguest vagrant-share
# 安装指定版本的插件
vagrant plugin install vagrant-vbguest --plugin-version 0.21
2.5.1.3 销毁并重新创建虚拟机
vagrant destroy -f
vagrant up
也可以通过手动安装VBoxGuestAdditions来解决:
-
首先需要下载对应VirtualBox的
VBoxGuestAdditions,下载页面: download.virtualbox.org/virtualbox -
关闭虚拟机
-
进入虚拟机设置,选择存储
-
在存储介质,控制器IDE中添加新的虚拟光驱
-
创建一个虚拟光驱,选择刚刚下载好的iso镜像:
-
启动虚拟机
-
进入虚拟机,进行安装
VBoxGuestAdditionsvagrant ssh web-server # 进入虚拟机之后 sudo -i mkdir -p /mnt/cdrom mount /dev/cdrom /mnt/cdrom cd /mnt/cdrom ./VBoxLinuxAdditions.run # 等待安装完成即可
2.5.2 Hyper-V同步文件夹
To use the SMB synced folder type on a Windows host, the machine must have PowerShell version 3 or later installed.通过SMB方式同步文件夹,需要Windows上的PowerShell版本大于3。
host_list = [
{
:name => "web-server",
:hostname => "web",
:box => "generic/centos7",
:box_version => "4.1.12"
}
]
Vagrant.configure("2") do |config|
# 遍历
host_list.each do |item|
# 获取到每一台VM
config.vm.define item[:name] do |host|
# 设置base box
host.vm.box = item[:box]
# 设置box版本
host.vm.box_version = item[:box_version]
# 设置主机名
host.vm.hostname = item[:hostname]
# 配置文件同步
config.vm.synced_folder ".", "/vagrant", onwer: "vagrant", group: "vagrant", type: "smb"
end
end
end
在vagrant up启动的时候需要输入当前电脑上用户的账号密码:
此时在虚拟机或者本地电脑上对文件的修改都会互相同步。
2.6 同时适配VirtualBox和Hyper-V文件同步
host_list = [
{
:name => "web-server",
:hostname => "web",
:box => "generic/centos7",
:box_version => "4.1.12"
}
]
Vagrant.configure("2") do |config|
config.vm.provider "hyperv" do |v|
config.vm.synced_folder ".", "/vagrant", onwer: "vagrant", group: "vagrant", type: "smb"
end
config.vm.provider "virtualbox" do |_, override|
override.vm.synced_folder ".", "/vagrant", type: "virtualbox"
end
# 遍历
host_list.each do |item|
# 获取到每一台VM
config.vm.define item[:name] do |host|
# 设置base box
host.vm.box = item[:box]
# 设置box版本
host.vm.box_version = item[:box_version]
# 设置主机名
host.vm.hostname = item[:hostname]
end
end
end
vagrant up --hyperv
效果如下:
3、Vagrant box操作
3.1 vagrant box基本命令
vagrant box有以下几个命令:
-
vagrant box add:添加新的boxvagrant box add generic/ubuntu2004 vagrant box add generic/ubuntu2004 --provider=virtualbox --box-version=4.1.8 -
vagrant box list:列出已经下载好的box -
vagrant box outdated:检查所有box是否有更新,查看已经过期的box -
vagrant box prune:删除已安装box的老旧版本,如果是正在使用的则提示是否确定删除。 -
vagrant box remove:删除指定的box# 删除generic/ubuntu2004所有provider为virtualbox的所有版本的box vagrant box remove generic/ubuntu2004 --provider=virtualbox --all # 删除generic/ubuntu2004所有provider为virtualbox的4.1.8版本的box vagrant box remove generic/ubuntu2004 --provider=virtualbox --box-version=4.1.8 -
vagrant box repackage:打包指定的box到当前文件夹,可用于重新发布。指定box的名字、提供者、版本号需要可通过vagrant box list命令检索到。 -
vagrant box update:用于存在可用更新时更新当前Vagrant环境中的box,也可以通过–box指定单独要更新的box。
3.2 打包自己的box
很多时候我们更多的是需要自己个性化的box,而不是拿别人的box过来,然后每次都需要各种个性化配置。所以vagrant提供了我们自己打包box的功能。
最简单的就是通过vagrant package将一个虚拟机打包成一个box。
3.2.1 基于centos/7启动一个虚拟机
vagrant init centos/7
vagrant up --provider virtualbox
3.2.2 在虚拟机中定制自己需要的box
# 切换到root用户
sudo -i
# 关闭swap分区
sudo swapoff -a
sudo sed -ri 's/.*swap.*/#&/' /etc/fstab
# 关闭selinux
setenforce 0
sed -i.bak 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
# 安装一些工具
yum install -y wget vim tree net-tools lrzsz telnet bash-completion yum-utils device-mapper-persistent-data lvm2
# 更换国内yum repo
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 安装并关闭防火墙
yum install -y iptables-services
systemctl stop iptables.service
systemctl disable iptables.service
iptables -F
# 修改内核参数
modprobe br_netfilter
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# 使内核参数生效
sysctl -p /etc/sysctl.d/k8s.conf
# 为Docker提前配置好加速镜像
mkdir /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": [
"https://rrr9h8xt.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn",
"https://dockerhub.azk8s.cn",
"https://hub-mirror.c.163.com"
],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
# 清空yum缓存
yum clean packages
yum clean headers
yum clean oldheaders
yum clean all
3.2.3 安装VBoxGuestAdditions
安装VBoxGuestAdditions有两种方法:
-
自动安装
vagrant plugin install vagrant-vbguest --plugin-version 0.21安装完成这个插件之后,vagrant会自动给虚拟机安装VBoxGuestAdditions
-
手动安装
需要自己手动下载VBoxGuestAdditions的镜像文件,在虚拟机上挂载进去之后,手动执行安装
推荐使用自动安装。
3.2.4 检查authorized_keys
确保vagrant用户的~/.ssh/authorized_keys文件中存在vagrant insecue public key的公钥:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
如果有
vagrant的公钥信息,需要删除!
3.2.5 确保虚拟机的端口转发正确
确保虚拟机网络的第一块网卡的类型是NAT:
3.2.6 开始打包
# 需要先把虚拟机关机
vagrant halt
# 打包
vagrant package --base <VirtualBox VM Name>
# 添加到本地box列表
vagrant box add --name centos79 --provider=virtualbox ./xxx.box
vagrant package --base centos7_default_1664325457933_58576 --output centos79.box
其中centos7_default_1664325457933_58576就是当前虚拟机的名字,来自于:
将box添加到本地box列表:
vagrant box add --name staryjie/centos7 --provider=virtualbox ./centos79.box
效果如下:
3.2 使用自己的box启动虚拟机
vagrant init staryjie/centos7
生成的Vagrantfile如下:
Vagrant.configure("2") do |config|
config.vm.box = "staryjie/centos7"
end
启动虚拟机:
vagrant up
启动成功:
进入虚拟机,检查环境是否是我们之前个性化之后的:
vagrant ssh
效果如下:
3.3 将box上传到vagrant cloud
3.3.1 注册vagrant cloud账号
浏览器访问:app.vagrantup.com/account/new
3.3.2 验证邮箱
创建成功,需要进行邮箱验证:
3.3.3 登陆
邮箱验证成功,自动登陆:
3.3.4 Create a new Vagrant Box
点击Create a new Vagrant Box:
3.3.5 填写Box的名字权限以及描述信息
填写完成,点击Create Box。
3.3.6 创建一个新的版本
根据提示填写对应的版本号以及描述信息:
填写完成之后,点击Create version。创建完成之后,我们就有了一个v1.0.0版本的Box,但是box文件还没有上传。这时,需要我们上传一个Provider:
点击Add a Provider。
3.3.7 新建一个Provider
首先通过工具计算box文件的SHA256值:
然后在Vagrant Cloud上填写:
填写完成之后,点击Continue upload。
3.3.8 上传box文件
点击选择文件,等待上传完成:
上传完成之后:
3.3.9 发布版本
进入到自己的Box列表内,提示还没有发布版本,点击下面的Release...:
进入到版本发布页面,点击Release version:
发布成功:
3.3.10 测试是否能够使用
vagrant init staryjie/centos7 --box-version 1.0.0
vagrant up --provider virtualbox
能够正常启动虚拟机:
3.4 打包Hyper-V的虚拟机为box
前期步骤和VirtualBox一样,只是关机之后,我们需要通过Hyper-V管理器选中虚拟机,选中右侧的导出:
导出完成之后,进入对应的目录下,删除Snapshots文件夹,然后创建一个metadata.json的文件,写入下面的内容:
{
"provider": "hyperv"
}
然后通过下面的命令进行打包:
cd hyperv_default_1664341712974_9080
tar zcf ../centos7.box ./*
打包完成之后,会在上一级目录下生成一个centos7.box文件,然后登陆到Vagrant Cloud在原先的Box中新增一个Provider上传这个box即可。
点击Add a provider:
填写相关信息,然后进入下一步,上传box文件:
等待上传完成,就可以使用了。
4、Vagrant Network网络配置
4.1 VirtualBox默认网络配置
在我们Vagrant启动VirtualBox的虚拟机的时候,是通过VM和本地电脑的端口转换实现的SSH连接,也是VirtualBox的默认配置:
在VirtualBox关于虚拟机的设置可以看到:
4.2 Hyper-V默认网络配置
Hyper-V,默认使用DHCP分配IP地址,在vagrant up --provider hyperv的时候就可以看到:
在Hyper-V管理器中也可以看到相关的配置:
然后来到Windows网络和Internet设置中:
4.3 Forwarded Ports 端口转发
我们通过vagrant up --porvider virtualbox的时候是通过端口转发实现的SSH连接,所以我们如果在VM中安装一个Nginx,就需要手动在VirtualBox上设置端口转发,才能够被正常访问。
那么这样是非常不方便的,好在Vagrantfile提供了对应的设置参数,能够自动帮我们实现端口转发:
host_list = [
{
:name => "web-virtualbox",
:hostname => "web",
:box => "generic/centos7",
:box_version => "4.1.12"
}
]
Vagrant.configure("2") do |config|
config.vm.provider "hyperv" do |v|
config.vm.synced_folder ".", "/vagrant", onwer: "vagrant", group: "vagrant", type: "smb"
end
config.vm.provider "virtualbox" do |_, override|
override.vm.synced_folder ".", "/vagrant", type: "virtualbox"
end
# 遍历
host_list.each do |item|
# 获取到每一台VM
config.vm.define item[:name] do |host|
# 设置base box
host.vm.box = item[:box]
# 设置box版本
host.vm.box_version = item[:box_version]
# 设置主机名
host.vm.hostname = item[:hostname]
# 设置端口转发,将虚拟机的80端口,映射到本地的8080端口
host.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
end
end
end
host.vm.network "forwarded_port"配置端口转发类型的网络guest: 80:虚拟机内部的80端口host: 8080:映射到本地的8080端口host_ip: "127.0.0.1":绑定到本地的127.0.0.1这个IP上,如果有多个,可以手动指定IPguest_ip:VM的IP地址,默认值是0.0.0.0protocol:协议可选TCP或UDP,默认是TCP
重启VM:
vagrant reload
效果如下:
浏览器访问:127.0.0.1:8080:
forwarded_port只针对VirtualBox生效,对Hyper-V无效。
4.4 Private NetWorks 私有网络
在Hpyer-V创建的多台虚拟机,默认情况下IP之间就是可以互相进行通信的(因为都连接在了同一个网络适配器Adapter)。但是在VirtualBox中创建的虚拟机因为是基于NAT(端口转发)的,所以vagrant创建的多台VirtualBox虚拟机之间是无法进行通信的。
host_list = [
{
:name => "host1"
},
{
:name => "host2"
}
]
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
host_list.each do |item|
config.vm.define item[:name] do |host|
host.vm.hostname = item[:name]
end
end
end
图1:Hyper-V多台VM直接直接通信:
图2:VirtualBox多台VM之间无法通信:
4.4.1 Static IP 静态IP配置
如果需要两台VM之间通信,我们需要手动给它们都添加一个网卡设备,并且要处于一个网段,手动添加就显得非常麻烦了,所以,Vagrant为我们提供了自动化添加的配置:
host_list = [
{
:name => "host1",
:eth1 => "192.168.50.4"
},
{
:name => "host2",
:eth1 => "192.168.50.5"
}
]
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
host_list.each do |item|
config.vm.define item[:name] do |host|
host.vm.hostname = item[:name]
host.vm.network "private_network", ip: item[:eth1]
end
end
end
vagrant reload之后,在VirtualBox中的虚拟机信息中就可以看到多了一个VirtualBox Host-Only Ethernet Adapter #2的适配器:
再看一下两个虚拟机之间是否能够互相通信:
此时两台vagrant创建的VirtualBox虚拟机之间能够正常通信了。
eth0是NAT模式的,主要用于访问互联网eth1是host-only模式,主要用于虚拟机之间的通信
该配置同样无法在
Hyper-V下生效。其实,Vagrant还未我们提供了
DHCP获取IP地址的配置,但是这样我们就无法控制哪台虚拟机是哪个IP了。具体参考官方文档:www.vagrantup.com/docs/networ…
4.4.2 DHCP 自动分配IP
host_list = [
{
:name => "host1-dhcp"
},
{
:name => "host2-dhcp"
}
]
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
host_list.each do |item|
config.vm.define item[:name] do |host|
host.vm.hostname = item[:name]
host.vm.network "private_network", type: "dhcp", name: "VirtualBox Host-Only Ethernet Adapter #2"
end
end
end
name: "VirtualBox Host-Only Ethernet Adapter #2":只要指定对应的适配器名称。
此时直接vagrant reload会有如下报错:
因为此时VirtualBox自动生成的VirtualBox Host-Only Ethernet Adapter #2并没有启用DHCP:
需要我们手动启用DHCP:
此时重启VM就可以正常通过指定的适配器获取到host-only的IP地址了:
4.5 Public NetWorks 共有网络
上面的Private Network私有网络智能保证在创建的多个VM之间能够通信,但是在本地主机并不能直接通信,而是要基于指定的端口转发才行,这样每次新增一个服务都需要去添加一个端口转发,非常不方便,所以为了解决这个问题,vagrant提供了Public Network相关的配置,可以让本地直接能够和VM主机进行通信。
官方文档:www.vagrantup.com/docs/networ…
4.5.1 DHCP自动分配IP
host_list = [
{
:name => "host1"
},
{
:name => "host2"
}
]
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
host_list.each do |item|
config.vm.define item[:name] do |host|
host.vm.hostname = item[:name]
host.vm.network "private_network", type: "dhcp", name: "VirtualBox Host-Only Ethernet Adapter #2"
host.vm.network "public_network"
end
end
end
创建虚拟机的时候,需要选择使用哪个适配器:
此时我们需要根据本地电脑真实提供哪个适配器进行上网来选择,这里无疑是通过Intel(R) Ethernet Connection (7) I219-V,所以我们选择1。
后续如果还要创建
Public Network的VM,那么就可以在配置中直接通过bridge: "Intel(R) Ethernet Connection (7) I219-V"来指定,这样就省去了在vagrant up的时候还需要手动选择适配器。
虚拟机启动完成之后,在VirtualBox中可以看到,此时VM的网络配置中多了一个桥接的网卡:
在本机ping两个VM都是可以正常通信的:
由VM中eth2的网段可以看到,它是通过连接Intel(R) Ethernet Connection (7) I219-V这个网卡实现的桥接,所以VM中桥接的IP地址是和本机的IP在同一个网段。
4.5.2 Static IP 固定IP地址
host_list = [
{
:name => "host1"
},
{
:name => "host2"
}
]
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
host_list.each do |item|
config.vm.define item[:name] do |host|
host.vm.hostname = item[:name]
host.vm.network "private_network", type: "dhcp", name: "VirtualBox Host-Only Ethernet Adapter #2"
host.vm.network "public_network", ip: "192.168.5.234", bridge: "Intel(R) Ethernet Connection (7) I219-V"
end
end
end
你需要知道你指定的
bridge设备的网段,然后根据网段设置ip。
4.5.3 其他配置
更多其他配置可以参考官方文档:www.vagrantup.com/docs/networ…
5、Provisioning任务
Provision就是在我们创建VM的时候帮助我们去执行一些操作,可以使Linux命令,也可以是一个shell脚本等等,可以帮助我们进行进一步的自动化操作。
Vagrant 中的 Provisioner 允许您在机器上自动安装软件、更改配置等,作为 vagrant up 过程的一部分。
每一个config.vm.provision命令字 代码段,我们称之为一个provisioner。根据任务操作的对象,provisioner可以分为:
- hell
- File
- Ansible
- CFEngine
- Chef
- Docker
- Puppet
- Salt
- ......
具体的使用方法以及配置可以参考官方文档:www.vagrantup.com/docs/provis…
5.1 为什么需要Provisioning?
- 提高自动化程度
- 较少人工操作
- 提高工作效率
- 节约时间
- ......
5.2 Provisioning任务什么时候会被执行?
- 第一次执行
vagrant up命令 - 执行
vagrant provision命令 - 执行
vagrant reload --provision或者vagrant up --provision命令 - 也可以通过在启动虚拟机的时候添加
--no-provision参数组织脚本被执行
5.3 Provisioning: Shell
5.3.1 shell inline
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
config.vm.hostname = "nginx"
config.vm.network "public_network", ip: "192.168.5.234", bridge: "Intel(R) Ethernet Connection (7) I219-V"
config.vm.provision "shell", inline: <<-SHELL
sudo yum install -y epel-release
sudo yum install -y nginx
sudo setenforce 0
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
sudo systemctl start nginx.service
sudo systemctl status nginx.service
sudo ip addr
SHELL
end
通过vagrant up --provider virtualbox --provision或者vagrant reload --provision就可以出发provision的执行:
浏览器访问:http://192.168.5.234:
如果使用inline的方式去执行一些命令,比较推荐需要执行命令比较少的情况,如果shell命令太多,会导致整个Vagrantfile变得比较庞大,后期难以维护。建议通过path的方式制定需要执行的shell脚本。将需要执行的shell命令编写成一个脚本进行执行。
5.3.2 shell path
setup.sh
#!/bin/bash
###
# @Author: staryjie staryjie@163.com
# @Date: 2022-09-27 11:19:39
# @LastEditors: staryjie staryjie@163.com
# @LastEditTime: 2022-09-27 11:34:50
# @FilePath: \pydev\provision\shell\path\virtualbox\setup.sh
###
# install some tools
sudo yum install -y wget git vim tree lrzsz gcc glibc-static telnet psmisc net-tools
# stop firewalld and set selinux
sudo setenforce 0
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
# install docker
cd /usr/local/src/ && sudo wget -q https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz && \
sudo tar zxvf docker-19.03.9.tgz && sudo mv ./docker/* /usr/bin/
sudo mkdir -pv /etc/docker && \
sudo cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://rrr9h8xt.mirror.aliyuncs.com"]
}
EOF
sudo cat > /lib/systemd/system/docker.service << EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl start docker.service
sudo systemctl status docker.service
sudo systemctl enable docker.service
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
config.vm.provision "shell", path: "./setup.sh"
end
5.5 Provisioning: Ansible
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Vagrant Index Page!</h1>
</body>
</html>
playbook.yaml
---
- name: test
hosts: all
gather_facts: true
become: true
tasks:
- name: "Stop Firewalld"
service:
name: firewalld
state: stopped
- name: "Add epel-release repo"
yum:
name: epel-release
state: present
- name: "Install Nginx"
yum:
name: nginx
state: present
- name: "Insert Index Page"
template:
src: index.html
dest: /usr/share/nginx/html/index.html
- name: "Start Nginx"
service:
name: nginx
state: started
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
config.vm.hostname = "nginx"
config.vm.network "public_network", ip: "192.168.5.235", bridge: "Intel(R) Ethernet Connection (7) I219-V"
config.vm.provision "ansible", playbook: "./playbook.yaml"
end
因为Windows上无法直接安装
Ansible,需要在Mac或者Linux上执行,所以这里就不放演示结果了!
可以在Mac或者Linux上创建一个Python的虚拟环境:
# 创建虚拟环境
conda create -n vagrant-ansible python=3.9.2
# 激活虚拟环境
conda activate vagrant-ansible
# 安装Ansible
pip install ansible
# 创建虚拟机
vagrant up
那么Ansible是怎么帮我们去执行操作的呢?
-
当我们执行
vagrant up的时候,vagrant会帮我们在.vagrant/provisioner/ansible/inventory/目录下生成一个vagrant_ansible_inventory文件 -
文件中配置了我们定义的VM的端口转发连接配置信息,内容大致如下:
default ansible_hosrt=127.0.0.1 ansible_port=2222 ansible_user='vagrant' ansible_ssh_private_key_file='/Users/staryjie/vagrant/vagrant-ansible/.vagrant/machines/default/virtualbox/private_key' -
vagrant在调用Ansible执行playbook的时候会通过
-i指定上面这个vagrant_ansible_inventory文件,类似于手动执行下面的操作:cd /Users/staryjie/vagrant/vagrant-ansible/ ansible-playbook -i .vagrant/provisioner/ansible/inventory/vagrant_ansible_inventory playbook.yaml -
等待Ansible执行完成
6、常见报错
6.1 意外中断,再次vagrant up报错
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
An action 'up' was attempted on the machine 'default',
but another process is already executing an action on the machine.
Vagrant locks each machine for access by only one process at a time.
Please wait until the other Vagrant process finishes modifying this
machine, then try again.
If you believe this message is in error, please check the process
listing for any "ruby" or "vagrant" processes and kill them. Then
try again.
解决办法:找到并杀死对应的ruby.exe或者vagrant.exe进程。