Vagrant和Vagrantfile入门
Vagrant 是由hashicorp公司(该公司还开源了Consul、Terraform等工具)开源的用于构建和管理虚拟机环境的工具,对于快速构建开发环境十分有用。Vagrant使用Vagrantfile进行虚拟机编排,和docker-compose有些类似,只不过Vagrant管理的对象是虚拟机,Vagrant支持VirtualBox、 VMware Fusion 和 Hyper-V 等许多虚拟化产品。本文基于VirtualBox做演示
对于开发人员来说,Vagrant可以快速构建剥离多余依赖的一致性环境,通过分享Vagrantfile快速创建相同的开发环境。Vagrantfile是Vagrant的核心。
实践环境
- 系统:Ubuntu 22.04
- Vagrant版本:Vagrant 2.3.4
- VirtualBox版本:7.0.6
各操作系统上安装Vagrant的方法见官方链接 [Install | Vagrant | HashiCorp Developer]()
为什么要用Vagrant?
- 对于运维工程师来说,学习新软件的第一步肯定是要尝试自行搭建一套环境,尤其是Kubernetes、Ceph等大型软件,一般需要多台机器构建分布式集群。使用Vagrantfile可以快速定制多虚拟机组成的服务器基础环境。
- 对研发和测试工程师来说,通过干净的虚拟机环境测试,有也助于复现、排除和定位环境相关的软件问题。
Vagrant基础
Vagrant box
box的概念可以对应docker镜像,也即虚拟机镜像,box是本机全局共享的。Vagrant提供了类似docker hub的在线镜像平台:https://app.vagrantup.com ,可以选择自己需要的基础镜像。
执行vagrant box
命令可以查看和box相关的操作,常用的有如下几个子命令:
- add:在线下载box
- list:列出当前机器上的box
- remove:删除box
常用的Vagrant 指令
常用的Vagrant指令如下:
vagrant init
是初始化Vagrantfile的命令,可以添加各类参数,最常见的是指定需要使用的基础镜像
vagrant up
根据当前目录下的Vagrantfile创建和启动虚拟机
vagrant destroy
销毁Vagrantfile创建的虚拟机
vagrant ssh/scp
ssh相关的子命令,可以使用ssh协议登录虚拟机,scp子命令则可以在虚拟机和物理机之间拷贝文件
vagrant status/global-status
:status查看当前环境下的虚拟机状态,global-status 则可以查看本机上所有的虚拟机状态。
vagrant halt
关闭虚拟机
vagrant reload
重启,基于更新后Vagrantfile更新虚拟机
vagrant port
查看虚拟机和物理机端口映射
以下是基础的vagrant 指令操作
$ mkdir /tmp/vagrant
$ cd /tmp/vagrant
$ vagrant init generic/centos7 -m # -m 的含义是最简化的Vagrantfile
$ cat Vagrantfile # 查看 Vagrantfile中的内容
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "generic/centos7"
end
$ vagrant up --provider=virtualbox # 默认的provider一般是virtualbox,也可以使用--provider指定
$ vagtrant status
Current machine states:
default running (virtualbox) # 新创建的虚拟机名叫default
$ vagrant port
22 (guest) => 2222 (host) 本机的2222端口映射到了虚拟机的22端口
$ vagrant ssh # 登录到默认虚拟机
[vagrant@centos7 ~]$ exit
$ vagrant halt default # 虚拟机关机
==> default: Attempting graceful shutdown of VM...
==> default: [vagrant-hostsupdater] Removing hosts on suspend
$ vagrant status
Current machine states:
default poweroff (virtualbox) # 虚拟机状态变为poweroff
The VM is powered off. To restart the VM, simply run `vagrant up`
$ vagrant destroy # 销毁虚拟机
default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Destroying VM and associated drives...
$ vagrant status
Current machine states:
default not created (virtualbox) # 状态变为 not created
以上创建的虚拟机,在virtualbox的GUI界面上也能看得见,也可以使用virtualbox对其进行管理。
到这里为止基本上就完成了Vagrant的入门,也没什么了不起的,对吧?和直接操作virtualbox也没啥差别嘛!别着急,Vagrant的精华在Vagrantfile,精彩的在后面。
定制Vagrantfile
在上一部分中,我们仅仅使用了Vagrant生成的默认Vagrantfile,Vagrantfile使用的是ruby的语法,非常灵活和强大,我也不会ruby,只能老老实实依葫芦画瓢按照需求来写。
provisioning
功能可以在vagrant up
过程中执行安装软件、运行指定命令等,用来更好的按需定制化系统。Provisioning | Vagrant | HashiCorp Developer
Vagrant 有插件机制,支持的插件列表见链接 Available-Vagrant-Plugins ,Vagrant可以对plugin执行install
、uninstall
、list
、update
等操作。
接下来安装 vagrant-hosts 插件,用于管理虚拟机的/etc/hosts
文件
$ vagrant plugin install vagrant-hosts
$ vagrant plugin list
vagrant-hosts (2.9.0, global)
vagrant-scp (0.5.9, global)
以下是一个比较完整的定制化Vagrantfile,涉及了网络、磁盘、内存、CPU、系统初始化等方面的定制,基于这个Vagrantfile,可以在不会ruby语法的情况下,将Vagrantfile修改成自己需要的样子。
# -*- mode: ruby -*-
# vi: set ft=ruby :
$init_script = <<-'SCRIPT'
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
unlink /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
SCRIPT
$ext_mount = <<-'SCRIPT'
parted -s /dev/sdb mklabel gpt mkpart primary ext4 0% 100%
mkfs.ext4 /dev/sdb1
mkdir /data
mount -t ext4 /dev/sdb1 /data
echo "/dev/sdb1 /data ext4 defaults 0 0" >> /etc/fstab
SCRIPT
Vagrant.configure("2") do | config |
config.vm.box = "generic/centos7"
config.vm.provision "shell", inline: "systemctl stop firewalld.service"
config.vm.provision "shell", inline: $init_script
config.vm.provision "shell", inline: $ext_mount
config.vm.provision "file", source: "~/.vimrc", destination: "~/.vimrc"
config.vm.provision "hosts" do | host |
host.add_host '192.168.56.11', ['node-1']
host.add_host '192.168.56.12', ['node-2']
host.add_host '192.168.56.13', ['node-3']
end
(1..3).each do |i|
config.vm.define "node-#{i}" do | node |
node.vm.hostname = "node-#{i}"
node.vm.disk :disk, name: "data", size: "10GB"
node.vm.provider "virtualbox" do | vb |
vb.customize ["modifyvm", :id, "--memory", "1024"]
vb.customize ["modifyvm", :id, "--cpus", "2"]
end
end
end
config.vm.define "node-1" do | node |
node.vm.network "private_network", ip: "192.168.56.11"
end
config.vm.define "node-2" do | node |
node.vm.network "private_network", ip: "192.168.56.12"
end
config.vm.define "node-3" do | node |
node.vm.network "private_network", ip: "192.168.56.13"
end
end
启动上面定义的Vagrantfile
$ VAGRANT_EXPERIMENTAL=disks vagrant up
这里的vagrant up命令前加了环境变量
VAGRANT_EXPERIMENTAL=disks
,原因是本Vagrantfile中使用的disks相关功能还在实验阶段,如果不加环境变量,相关功能将无法正常使用。如果更新了Vagrantfile,在使用vagrant reload
的时候也需要加上这个环境变量。
接下来解释下这个Vagrantfile每一部分所做的事情。
- 首先定义了2个变量
init_script
和ext_mount
,分别自定义了服务器创建时需要执行的初始化操作。这种多行字符串变量的定义方法叫 Heredoc,Bash中也有类似的操作。 do/end
相当于{}
,也可以用{}
替换 ,用于定义一段代码块。test do |x| ... end
,在这种语句结构中,两个竖线中的x
是局部变量,用于接收前面语句抛出来的值。- 在
config.vm.provision
几行,使用了shell和file这两个内置的Provisioner。在这个过程中可以定义许多主机初始化操作。 - 在
config.vm.provision "hosts"
一行中,使用了前面安装的vagrant-hosts插件,为集群内所有机器都添加了/etc/hosts
静态解析。 (1..3).each do |i| ... end
这里是个循环,分别将1、2、3赋值给i,然后定义了node-1
、node-2
和node-3
这三台主机。并定制了主机的内存、CPU资源和额外data硬盘等。node.vm.network "private_network"
这3处代码则分别定义了3个节点的额外网卡和ip。- 剩余的语句基本上就是赋值和函数执行一类的,没什么好说的,依葫芦画瓢即可,遇到特殊需求再google搜索。
启动Vagrant之后,继续验证主机是否符合预期。
$ vagrant status
Current machine states:
node-1 running (virtualbox)
node-2 running (virtualbox)
node-3 running (virtualbox)
$ vagrant ssh node-3
Last login: Tue Feb 21 23:37:03 2023 from 10.0.2.2
[vagrant@node-3 ~]$ df -hT /dev/sdb1
Filesystem Type Size Used Avail Use% Mounted on
/dev/sdb1 ext4 9.8G 37M 9.2G 1% /data
[vagrant@node-3 ~]$ ip a s eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:6d:39:57 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.13/24 brd 192.168.56.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe6d:3957/64 scope link
valid_lft forever preferred_lft forever
[vagrant@node-3 ~]$ nproc
2
[vagrant@node-3 ~]$ free -m
total used free shared buff/cache available
Mem: 990 130 683 12 176 708
Swap: 2047 0 2047
[vagrant@node-3 ~]$ tail -3 /etc/hosts
192.168.56.11 node-1
192.168.56.12 node-2
192.168.56.13 node-3
[vagrant@node-3 ~]$ systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
通过以上验证,可以看到主机的初始化完全符合我们的定义。
为什么要使用Vagrant?
我个人总结Vagrant有如下几点优势:
- Vagrant十分强大,也有很丰富的插件可以选择:Available Vagrant Plugins · hashicorp/vagrant Wiki · GitHub 。
- 十分灵活的配置方法,且易于分享,简化系统初始化和配置过程。
- 虚拟机可以弥补某些测试场景下Docker的不足,比如需要特定的操作系统版本和内核。
当前暂无评论 »