Vagrant搭建虚拟机环境

发布于 2020年8月    阅读 50次

Vagrant 搭建虚拟机

一.Vagrant 是什么

这篇中我们介绍下如何用 Vagrant 神奇,快速搭建虚拟机, 对于要用虚拟机构建分布式集群的时候,Vagrant 就特别有用。

  • Vagrant 其提供了类似于Vagrantfile 用于描述虚拟机的构建, 类似于 Docker 的 Dockerfile, 使得虚拟机的管理变得更加方便和移植。
  • Vagrant 基于 Ruby 开发。
  • Vagrant 不具备虚拟化能力, 其提供的是虚拟化环境构建的抽象描述.其provider 关键字即用来描述 所要用的虚拟化引擎(支持 Docker、VirtualBox、VM)

1.1 Vagrant 的安装

进入官网如下图,选择对应的平台下载即可。

安装完后,执行: Vagrant -v, 如果输出对应版本,证明安装成功。

二.Vagrant 常用命令

子命令 英文释义 中文释义
box manages boxes: installation, removal, etc 管理 box,安装和删除
cloud manages everything related to Vagrant Cloud 管理任何和 Vagrant 云相关的
destroy stops and deletes all traces of the Vagrant machine 停止并且删除 Vagrant 虚拟机的所有文件
global-status outputs status Vagrant environments for this user 输出本机 Vagrant 的所有环境变量
halt stops the Vagrant machine 关闭虚拟机
help shows the help for a subcommand 显示子命令如何使用
init initializes a new Vagrant environment by creating a Vagrantfile 创建 Vagrantfile,用来初始化 Vagrant 环境
login 登入 Vagrant Cloud.
package packages a running Vagrant environment into a box 打包一个正在运行的 Vagrant 环境为一个 Box
plugin manages plugins: install, uninstall, update, etc 管理 Vagrant 的插件安装、删除、更新
port displays information about guest port mappings 显示虚拟机的端口映射信息
powershell connects to machine via powershell remoting 通过远程 powershell 连接到虚拟机
provision provisions the Vagrant machine
push deploys code in this environment to a configured destination 发布虚拟机中到配置的目的地
rdp connects to machine via RDP 通过 RDP 连接到虚拟机
reload restarts Vagrant machine, loads new Vagrantfile configuration 重启虚拟机,加载新的 Vagrantfile 配置
resume resume a suspended Vagrant machine 恢复挂起的虚拟机
snapshot manages snapshots: saving, restoring, etc 管理快照的存储,恢复
SSH connects to machine via SSH 通过 SSH 连接到虚拟机
ssh-config outputs OpenSSH valid configuration to connect to the machine 显示连接到虚拟机的 SSH 配置
status outputs status of the Vagrant machine 输出虚拟机的状态
suspend suspends the machine 挂起虚拟机
up starts and provisions the Vagrant environment 启动并且初始化虚拟机
upload upload to machine via communicator 通过 communicator 上传到虚拟机
validate
vbguest plugin: vagrant-vbguest: install VirtualBox Guest Additions to the machine 插件:vagrant-vbguest,安装 VB 的 Guest Additions 到虚拟机
version prints current and latest Vagrant version 显示当前和最新的 Vagrant 版本
winrm executes commands on a machine via WinRM 通过 WinRM 在虚拟机上执行一条命令
winrm-config outputs WinRM configuration to connect to the machine 显示 WinRM 的配置信息

上述命令有 29 个,我挑我认为最常用的 8 个讲解下。

box

  • 该命令用来添加一个 box 的地址,并给这个 box 取别名,方便后续引用。
  • 一个 box 可以理解为 docker 里对应的镜像的概念。

vagrant box add

vagrant box list 显示本地拥有的可用 box

init

初始化命令,用来生成 Vagrantfile.还可以指定 box 的远程地址,该地址会写入到 Vagrantfile 中。

Usage: Vagrant init [options] [name [url]] Options:

vagrant init centos/7 https://mirrors.ustc.edu.cn/centos-cloud/centos/7/vagrant/x86_64/images/CentOS-7.box

下载 box 并且命名为 centos/7, 并生成 Vagrantfile 文件。

vagrant init centos/7

生成 Vagrantfile 文件里的 config.vm.box = "centos/7" , 引用 centos/7 镜像,会优先找本地,再找 Vagrant Cloud

status

vagrant status 显示当前 Vagrantfile 中虚拟机的状态, 如果是多台虚拟机, 要在后面指定虚拟机名。可以看出当前的虚拟机还未创建。我们需要执行 up 命令才会创建虚拟机。

up

虚拟机启动命令

Usage: Vagrant up [options] [name|id]

Options: --[no-]provision Enable or disable provisioning --provision-with x,y,z Enable only certain provisioners, by type or by name. --[no-]destroy-on-error Destroy machine if any fatal error happens (default to true) --[no-]parallel Enable or disable parallelism if provider supports it --provider PROVIDER Back the machine with a specific provider --[no-]install-provider If possible, install the provider if it isn't installed

  • 使用 Vagrant up 直接启动 Vagrantfile 中配置的所有虚拟机 vagrant up
  • 启动名为 node1 的虚拟机 vagrant up node1

SSH

  • vagrant ssh 连接到虚拟机(如果只有一台虚拟机可以省略虚拟机名)
  • vagrant ssh node1 连接到 node1 虚拟机

halt

  • vagrant halt 关闭虚拟机(如果只有一台虚拟机可以省略虚拟机名)
  • vagrant halt node1 关闭名称为 node1 的虚拟机

suspend

  • vagrant suspend 挂起虚拟机(如果只有一台虚拟机可以省略虚拟机名)

resume

  • vagrant resume 恢复挂起的虚拟机
  • vagrant resume node1

destory

  • vagrant destory node1 销毁 node1 虚拟机

三.Vagrantfile 文件语法

Vagrant 使用 Ruby 编写,所以其 Vagrantfile 遵循 Ruby 语法。不用去了解 Ruby 语法,有编程经验的套着模板基本能够理解和编写。

打开 Vagrantfile 你会发现其中包含了关于虚拟机的大量设置,每个配置项还很贴心的包含了注释说明

其中比较常用的配置项有下面几个:

  • 1.3.1 指定使用哪个 box 启动虚拟机(box),本机如果没有,则会从 Vagrant Cloud 中搜索
config.vm.box = "centos/7"
  • 1.3.2 指定虚拟机的主机名(hostname)
config.vm.box = "centos/7"
  • 1.3.3 指定系统启动超时时间。若这段时间内 Vagrang 还无法连接上虚拟机,则认为虚拟机启动过程中发生了错误
config.vm.hostname = "centos/7"
  • 1.3.4 指定 Vagrant 和虚拟机的通信方式。一般为 ssh, windows 下为 winrm
config.vm.communicator = "ssh"
  • 1.3.5 指定给虚拟机分配物理资源(内存、CPU 核数、显存、虚拟机名)
config.vm.provider "virtualbox" do |vb|
  # Display the VirtualBox GUI when booting the machine
  vb.gui = true

  # Customize the amount of memory on the VM:
  vb.memory = "1024"
  vb.cpus = 2
  vb.customize ["modifyvm", :id, "--vram", "128"]
  vb.name = "centos7"
end

比如这段配置指明了虚拟机引擎为 "virtualbox",并且定义了为其分配的资源为: 1G内存\2个CPU\128M显存\虚拟机的名称为centos7

这些配置都是以 config.vm 为前缀,表示虚拟机配置。分别有 box, hostname, boot_timeout, communicator,provider

  • 1.3.6 指定要安装的软件或者执行的命令
config.vm.provision "shell", inline: <<-SHELL
  apt-get update
  apt-get install -y apache2
SHELL

其中 "shell" 表示使用的是 shell provider, inline: 表示要执行的内容嵌入在后面, <<-SHELL 表示执行脚本到 SHELL 这一行结束。

除了 inline: ,还可以是 path: 表示要执行的内容存放在后面指定的文件中。

config.vm.provision :shell, path: "./setup.sh"

Vagrant 会在三种情况下触发 provision:

  • 第一次使用 Vagrant up 创建虚拟环境,且没有指定 --no-provision
  • 运行命令 vagrant provision
  • 运行 vagrant reload --provision

shell 这种方式也被称为 shell provider, 还有一种叫做 file provider: 将主机上的文件拷贝到虚拟机中但并不执行脚本的内容。这个类似于 Dockerfile 的 ADD,如下表示将 shell 文件下 setup.sh 脚本拷贝到虚拟机的根目录

config.vm.provision "file",source: "shell/setup.sh",destination: "/setup.sh"
  • 1.3.7 指定宿主机和虚拟机之间要同步的目录,以此实现文件共享

可以在 Vagrantfile 中通过 config.vm.synced_folder 来添加 Synced Folder.如下表示将当前宿主机 执行vagrant命令文件夹下的labs文件夹 和虚拟机的 /home/vagrant/labs 进行同步

config.vm.synced_folder "./labs", "/home/vagrant/labs"
  • 1.3.8 网络配置

网络配置我认是比较重要的,单独放在 4 中介绍

四.Vagrant 网络

Vagrant 网络配置我认为是比较重要的一点,所以单独出来进行说明。Vagrant 通过 config.vm.network 来配置网络。Vagrant 抽象的网络有三种,分别是

forwarded_port 网络

即端口转发, 本质会创建一个 NAT 网络

将宿主机的 8080 映射到虚拟机的 80 端口。当访问宿主机的 8080 流量,就会被转发给这个虚拟机的 80 端口。

Vagrant.configure("2") do |config|
  config.vm.network "forwarded_port", guest: 80, host: 8080
end

还可以进一步指定哪台虚拟机,哪台宿主机,和转发的 TCP/IP 协议

  • guest_ip: 指定转发到虚拟机的哪个 IP 上,默认会转发到虚拟机的每个 IP 接口上
  • host_ip: 指定只有访问主机哪个 IP 上的端口才进行转发,默认也是主机的每个 IP
  • protocol: 指定转发的协议是 "tcp" 还是 "udp",默认是 "tcp"

private_network 网络

即私有网络,其是一个局域网, 使用的不是公网 IP,而是私有 IP.所以这些虚拟机不能被外界互联网访问。

在这种网络中我们需要指定 IP 地址的生成方式是 DHCP 动态 IP,还是静态 IP.

  • DHCP 动态 IP
agrant.configure("2") do |config|
  config.vm.network "private_network", type: "dhcp"
end
  • 静态 IP
agrant.configure("2") do |config|
  config.vm.network "private_network", type: "dhcp"
end

public_network 网络

即公有网络。这些虚拟机具有公网 IP,能够被外界互联网访问

  • DHCP 动态 IP
Vagrant.configure("2") do |config|
  config.vm.network "public_network"
end
  • 静态 IP
config.vm.network "public_network", ip: "62.168.0.17"
  • 桥接网卡

可以通过 bridge 参数来指定桥接的网卡

config.vm.network "public_network", bridge: "en1: Wi-Fi (AirPort)"

有些 provider 甚至支持桥接多个网卡

config.vm.network "public_network", bridge: [
  "en1: Wi-Fi (AirPort)",
  "en6: Broadcom NetXtreme Gigabit Ethernet Controller",
]

五.Vagrant 快速搭建虚拟机

  • 我们用 Vagrant 快速搭建两台虚拟机, 分别叫 docker-node1 和 docker-node2,IP 分别为 192.168.205.10、192.168.205.11.内存为 1G、CPU 为 1 核心。

以下为 Vagrantfile 模板

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

Vagrant.require_version ">= 1.6.0"

Vagrant.configure(2) do |config|

end

我们基于模板来写

boxes = [
    {
        :name => "docker-node1",
        :eth1 => "192.168.205.10",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "docker-node2",
        :eth1 => "192.168.205.11",
        :mem => "1024",
        :cpu => "1"
    }
]

这是 Ruby 语法,可以看成构建了一个数组对象,包含两个字典。

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

Vagrant.require_version ">= 1.6.0"

boxes = [
    {
        :name => "docker-node1",
        :eth1 => "192.168.205.10",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "docker-node2",
        :eth1 => "192.168.205.11",
        :mem => "1024",
        :cpu => "1"
    }
]

Vagrant.configure(2) do |config|

  config.vm.box = "centos/7"

  boxes.each do |opts|
        config.vm.provider "virtualbox" do |v|
          v.customize ["modifyvm", :id, "--memory", opts[:mem]]
          v.customize ["modifyvm", :id, "--cpus", opts[:cpu]]
        end
        config.vm.network :private_network, ip: opts[:eth1]
      end
  end

  config.vm.synced_folder "./labs", "/home/vagrant/labs"
  config.vm.provision "shell", privileged: true, path: "./setup.sh"
  • 这个配置文件里我们说明了采用私有网络进行部署、并且每台机器的私有地址是多少,分配的资源。和宿主机共享的文件夹。以及开启虚拟机后要执行的脚本 setup.sh。

我们运行 Vagrant up.就可以开始构建这台虚拟机

最后运行 Vagrant status 可以查看构建后的虚拟机状态,由于我这已经挂起了虚拟机,所以当前状态是 saved.

六.可能遇到的问题

  • The VirtualBox VM was created with a user that doesn't match the current user running Vagrant.

运行 rm -fr .vagrant. 删除 Vagrantfile 所在文件下的该目录

  • Vagrant was unable to mount VirtualBox shared folders•Vagrant mount: unknown filesystem type 'vboxsf'

运行如下命令,安装 Vagrant vbguest 插件

vagrant plugin install vagrant-vbguest
vagrant vbguest