Vagrant 虚拟机管理
一 、 安装
- Vagrant 2.4.0
下载地址:https://developer.hashicorp.com/vagrant/downloads
- VirtualBox 7.0.12
下载地址:https://www.virtualbox.org/wiki/Downloads
二 、 类比docker
Vagrant Box
Box是Vagrant创建虚拟机使用的包格式,它是一个预先配置好的运行环境。
Box File实际上是一个压缩文件(tar,zip,tar.gz),它通常包含了虚拟机镜像、元数据、描述信息、配置文件。
。不同的虚拟化平台需要使用不同的Box。如果在ARM架构下创建虚拟机,需要使用arm64架构的Box文件。
我们可以从Vagrant Cloud网站上找到支持不同虚拟化平台的Box文件。
Vagrant Cloud不像Docker Hub,没有完整的镜像站。
国内源
https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/jammy/20230929/jammy-server-cloudimg-amd64-vagrant.box
三 、 使用
3.1 简单使用
比如我们要创建ubuntu 22.04的虚拟机,有以下两种方式:
●命令行
vagrant init ubuntu/jammy64
vagrant up
●配置文件(Vagrantfile)
创建Vagrantfile文件,然后使用Vagrant up命令启动。
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
end
3.2 创建过程
创建和启动虚拟机主要有下面几个步骤:
- 配置网络
- 转发SSH端口
- 配置ssh用户和密钥对
- 挂载共享目录
配置网络
vagrant总是会将虚拟机的第一个网卡设置为NAT。NAT只能用于虚拟机向外访问,通常用来访问互联网,主机不能访问虚拟机,虚拟机与虚拟机之间也不能通信
转发SSH端口
NAT无法从主机访问虚拟机,为什么可以使用vagrant ssh
连接到虚拟机呢?
这是因为vagrant将虚拟机的ssh端口22
转发到宿主机2222
端口。如果有多个虚拟机,每个虚拟机会转发到不同的端口。
通过vagrant ssh
连接到虚拟机跟使用下列命令是一样的。
ssh vagrant@localhost -p 2222
配置SSH用户
vagrant默认为每个虚拟机创建一个vagrant
用户,密码为vagrant
。
这个用户拥有sudo
权限,默认情况下不启动root
用户。
配置SSH密钥对
vagrant ssh命令不需要输入密码,通过密钥对免密登录虚拟机。
所有的虚拟机Box打包的时候都使用同一个公开的密钥对。这样子显然是不安全的。
内置的密钥对仅用于第一次创建虚拟机的时候,vagrant会通过这个密钥对登录进虚拟机。然后生成一个新的密钥对,并替换公开的密钥对。
挂载共享目录
最后,vagrant会将当前目录设置为共享目录,挂载到虚拟机的/vagrant
目录下。
更新Guest Additions
如果要去掉guest additions
版本不匹配的提示信息,可以手动更新
vagrant plugin install vagrant-vbguest
3.3 Vagrantfile文件
用于配置和管理虚拟机文件,它使用ruby语法,用于定义虚拟机的配置选项,例如虚拟机的操作系统、网络设置、共享文件夹等。
运行vagrant init
命令时,会在当前目录生成Vagrantfile
配置文件,默认的配置文件如下:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
end
在线
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.box_url = "https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/jammy/20230929/jammy-server-cloudimg-amd64-vagrant.box"
end
离线
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.box_url = "file://tmp/ubuntu-2204.box"
end
配置环境变量
ENV["LC_ALL"] = "en_US.UTF-8"
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
end
3.4 Provider和Provision
Vagrantfile
主要用来配置Provider(虚拟化提供者)和Provision(配置管理器)
Vagrant支持不同的虚拟化平台,默认使用VirtualBox,同时官方也支持Vmware(需要安装插件)、Hyper-V和Docker。
Provider
用来适配不同的虚拟化平台。在不同平台下创建虚拟机需要使用不同的Provider,不同的Provider功能有些差异,一些配置选项也有所不同。
Provision
是配置管理器,用于在虚拟机创建完成后,使用shell脚本或自动化运维工具配置环境、安装软件等。不同的配置工具需要使用不同的配置管理器。
Vagrant Provider 虚拟化提供者
primary disk默认是40G,硬盘容量不能比默认值小。
Vagrant.configure("2") do |config|
config.vm.box = "unbuntu/jammy64"
# 规格配置
config.vm.provider : virtualbox do |box|
vbox.name = "ubuntu-22.04"
vbox.cpus = 2
vbox.memory = 2048
vbox.customize ['modifyvm', :id, '--graphicscontroller', 'vmsvga']
end
config.vm.hostname ="ubuntu-1"
config.vm.disk :disk, size:"40GB",primary: true
config.vm.disk :disk, size:"20GB",name: "extra_disk"
end
常用命令
- vagrant reload 重新配置虚拟机
- vagrant halt 关闭虚拟机
- vagrant destroy 删除虚拟机
- vagrant suspend 休眠
- vagrant resume 唤醒
VMware
vagrant plugin install vagrant-vmware-desktop
config.vm.provider "vmware_desktop" do |v|
v.vmx["memsize"] = "1024"
v.vmx["numvcpus"] = "2"
end
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.provider :virtualbox do |vbox|
vbox.cpus = 2
vbox.memory = 2048
end
config.vm.disk :disk, size: "40GB"
end
配置默认的provider
export VAGRANT_DEFAULT_PROVIDER=vmware_desktop
Vagrant Provision 配置管理器
虚拟机创建完成后,通常无法直接满足我们的需求。
Provision配置管理器可以在创建虚拟机的过程中修改配置、自动安装软件等。
这个是自动化的,不需要人工干预,只需一条命令就可以创建一个开箱即用的虚拟环境。
配置管理器支持Chef、Ansible、Puppet、Salt等自动化工具,通常我们使用shell脚本就够了
修改密码
vagrant用户默认的密码是vagrant
,这是不安全的,因此vagrant默认不启动SSH密码登录。
通过provision
修改密码并开启SSH密码登录。
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
# 规格配置
config.vm.provider :virtualbox do |vbox|
vbox.name = "ubuntu-22.04"
vbox.cpus = 2
vbox.memory = 2048
vbox.customize ['modifyvm', :id, '--graphicscontroller', 'vmsvga']
end
# 修改hostname,更新/etc/hosts
config.vm.hostname = "ubuntu-1"
# 设置系统盘容量
config.vm.disk :disk, size: "40GB", primary: true
# 新建一个硬盘
config.vm.disk :disk, size: "20GB", name: "extra_disk"
# 修改vagrant用户密码
config.vm.provision "shell", inline: "echo vagrant:Abc123 | sudo chpasswd"
end
['modifyvm', :id, '--graphicscontroller', 'vmsvga']
:这是传递给 vbox.customize
命令的参数数组,它指定了要进行的具体定制化操作。
'modifyvm'
:这是 VirtualBox 的一个命令行工具 VBoxManage 的命令,用于修改已存在的虚拟机的设置。:id
:这是一个特殊的占位符,Vagrant 在执行时会自动将其替换为当前虚拟机的 ID。'--graphicscontroller'
:这是 VBoxManagemodifyvm
命令的一个选项,用于指定虚拟机使用的图形控制器类型。'vmsvga'
:这是--graphicscontroller
选项的参数,指定使用 VMWare SVGA 图形控制器。这通常用于改善虚拟机的图形性能,特别是在需要更好的 3D 加速时。
启动SSH密码登录
provision
也可以执行shell脚步文件
# 启用ssh密码认证
echo "==> Enable ssh password authentication"
sed -i 's/^PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config
systemctl reload sshd
# 修改vagrant用户密码
config.vm.provision "shell", path: "bootstrap.sh"
什么时候执行
- 配置管理器只在第一次使用
vagrant up
创建环境时执行。 - 如果虚拟机已经创建,
vagrant up
或vagrant reload
不会再次运行配置管理器,需要显式调用
vagrant up --provision
vagrant reload --provision
--手动执行
vagrant provision
3.5 网络
Vagrant 网络:
- NAT(默认)
- 私有网络
- 共有网络
NAT 网络地址转换(默认)
Vagrant总是将虚拟机的第一个网卡设置为NAT(网络地址转发),。
NAT模式下,虚拟机只能单向访问外部网络(通常用来访问互联网),虚拟机对外部互联网是不可见和无法访问的,虚拟机之间也是相互隔离的。
端口转发
在NAT模式下,如果想访问虚拟机中的端口,可以使用端口转发。
这种方式虽然可以访问虚拟机内的服务,但是不适合搭建分布式集群。
config.vm.network "forwarded_port", guest: 80, host: 8080
私有网络
私有网络可以实现虚拟机之间的网络访问,在Virtual Box下,Vagrant将网卡设置为仅主机访问(Host-only)模式。
Host-only顾名思义,只能从宿主机访问虚拟机,无法从外部主机访问虚拟机。
config.vm.network "private_network", ip: "192.168.56.20"
VirtualBox默认将192.168.56.0/21范围内的地址分配给虚拟机。
查看IP地址或者DHCP自动获取
VBoxManage list hostonlynets
config.vm.network "private_network", type: "dhcp"
外部网络
如果要从别的主机进行访问,也可以设置公有网络。
在VirutualBox中,使用bridge网络实现。Bridge网络将虚拟机等同为网络中的真实主机,可以像访问其他主机一样访问虚拟机。
查看桥接网络接口:
VBoxManage list bridgedifs
## bridge的名称中不能包含中文,Vagrant无法识别,需要修改网络的名称。
config.vm.network "public_network", ip: "10.150.36.191", bridge: "en4: USB-eth"
3.6 Vagrant SSH连接虚拟机
Vagrant会为每个虚拟机都生产一对密钥,这个存放在当前的.vagrant
目录下。
在Windows下,ssh可能会报错或者假死,通常第一次创建虚拟机时会出现。
出现这种情况,在virtualbox界面删除虚拟机,重新创建虚拟机即可。
- 与Docker Desktop有冲突
还有一种情况,Vagrant可能会与Docker Desktop有冲突,需要先卸载Docker Desktop,虚拟机创建完成后,再安装Docker Desktop。
免密登录
ssh vagrant@localhost -p 2200 -i .vagrant/machines/default/virtualbox/private_key
3.7 Vagrant 批量创建虚拟机
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
(1..3).each do |i|
config.vm.define "node-#{i}" do |node|
node.vm.provision "shell",
inline: "echo hello from node #{i}"
end
end
end
vm_list = [
{ # hash map
"name" => "node-1",
"cpu" => "2",
"mem" => "2048",
"ip_addr" => "192.168.56.10"
},
{
"name" => "node-2",
"cpu" => "1",
"mem" => "1024",
"ip_addr" => "192.168.56.11"
},
{
"name" => "node-3",
"cpu" => "1",
"mem" => "1024",
"ip_addr" => "192.168.56.12"
}
]
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/jammy64"
vm_list.each do |item|
config.vm.define item["name"] do |node|
node.vm.provider "virtualbox" do |vbox|
vbox.name = item["name"]; # 虚拟机名称
vbox.memory = item["mem"]; # 内存
vbox.cpus = item["cpu"]; # CPU
end
# 设置hostanme
node.vm.hostname = item["name"]
# 设置IP
node.vm.network "private_network", ip: item["ip_addr"]
end
end
end
命令后面加虚拟机的名字,可以单独操作虚拟机:
vagrant up node-1
vagrant halt node-1
vagrant reload node-1
vagrant destroy node-1
vagrant provision node-1
SSH的私钥也分别存放在.vagrant虚拟机名对应的目录下
ssh vagrant@192.168.56.10 -i .vagrant/machines/k3s-server/virtualbox/private_key
四 、 例子
Vagrant 自动部署k3s集群
1.集群规划
主机名 | IP地址 | 类型 |
---|---|---|
k3s-server | 192.168.56.10 | Control Plane 控制平面 |
k3s-agent1 | 192.168.56.11 | 工作节点 |
k3s-agent2 | 192.168.56.12 | 工作节点 |
2.Vagrantfile 配置文件
vm_list = [
{
"name" => "k3s-server",
"cpu" => "2",
"mem" => "2048",
"ip_addr" => "192.168.56.10"
},
{
"name" => "k3s-agent1",
"cpu" => "1",
"mem" => "1024",
"ip_addr" => "192.168.56.11"
},
{
"name" => "k3s-agent2",
"cpu" => "1",
"mem" => "1024",
"ip_addr" => "192.168.56.12"
}
]
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/jammy64"
vm_list.each do |item|
config.vm.define item["name"] do |node|
node.vm.provider "virtualbox" do |vbox|
vbox.name = item["name"]; #虚拟机名称
vbox.memory = item["mem"]; #内存
vbox.cpus = item["cpu"]; #CPU
end
# 设置hostname
node.vm.hostname = item["name"]
# 设置IP
node.vm.network "private_network", ip: item["ip_addr"]
# 执行shell脚本
node.vm.provision "shell" do |script|
script.path = "k3s-install.sh" #脚本路径
script.args = [ item["name"] ] #传递参数
end
end
end
end
3.安装脚本
在安装脚本中,我们通过传入的参数,也就是虚拟机的名字,来执行不同的命令。
环境变量
自动创建K3s集群,需要配置下面两个环境变量:
K3S_TOKEN
:预先约定好token,工作节点自动加入
K3S_URL
:主节点API server的访问地址
由于预先分配了IP,所以可以确定API server的访问地址。
Flannel网络
K3s内置了flannel
作为默认的网络插件(CNI)。
flannel
默认是选择第一个网卡进行网络通信,由于Vagrant虚拟机的第一个网卡是NAT模式,虚拟机之间无法互相访问。因此,在安装k3s时,需要使用--flannel-iface
将第二个网卡enp0s8
设置为默认网络。
echo "==> k3s cluster settings:"
K3S_TOKEN=NEIwQ0IxMEUtNTA2MS00RE
K3S_URL=https://192.168.56.10:6443
FLANNEL_IFACE="enp0s8"
echo " TOKEN: ${TOKEN}"
echo " API_SERVER:${API_SERVER}"
echo " FLANNEL_IFACE:${FLANNEL_IFACE}"
echo "==> disable firewall"
ufw disable
if [ $1 == "k3s-server" ]; then
echo "==> install $1"
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn \
K3S_TOKEN=${TOKEN} \
sh -s - server --flannel-iface ${FLANNEL_IFACE}
else
echo "==> install $1"
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn \
K3S_URL=https://${API_SERVER}:6443 \
K3S_TOKEN=${TOKEN} \
sh -s - --flannel-iface ${FLANNEL_IFACE}
fi