Vagrant 搭建虚拟机
作者:weipeng.su 目前就职于携程, 从事大数据开发工作
分享目的
•了解 Vagrant 的作用, 知道 Vagrant 如何快速搭建虚拟机•知道 Vagrantfile 的语法, 能够独立编写 VagrantFile
一.Vagrant 是什么
前面两篇, 我分享了Docker的快速入门和Docker的发展历史.这篇中我们介绍下如何用 Vagrant 神奇,快速搭建虚拟机, 对于要用虚拟机构建分布式集群的时候,Vagrant 就特别有用。
•Vagrant 其提供了类似于Vagrantfile 用于描述虚拟机的构建, 类似于 Docker 的 Dockerfile, 使得虚拟机的管理变得更加方便和移植。•Vagrant 基于 Ruby 开发。•Vagrant 不具备虚拟化能力, 其提供的是虚拟化环境构建的抽象描述.其provider 关键字即用来描述 所要用的虚拟化引擎(支持 Docker、VirtualBox、VM)
1.1 Vagrant 的安装
•Mac 上: brew install vagrant
•其他平台:https://www.vagrantup.com/downloads.html
进入官网如下图,选择对应的平台下载即可。
安装完后,执行: 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 | validates the Vagrantfile | 鉴别 Vagrantfile 语法是否正确 |
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.hostname = "centos/7"
•1.3.3 指定系统启动超时时间。若这段时间内 Vagrang 还无法连接上虚拟机,则认为虚拟机启动过程中发生了错误
config.vm.boot_timeout = 600
•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: < apt-get update apt-get install -y apache2SHELL
其中 "shell"
表示使用的是 shell provider, inline:
表示要执行的内容嵌入在后面, < 表示执行脚本到
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: 8080end
还可以进一步指定哪台虚拟机,哪台宿主机,和转发的 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-vbguestvagrant vbguest