如果你是开发者或者DevOps工程师,那么你应该听到或者看到过Vagrant。如果没有听说过也不要紧,马上你就可以通过本文体验到它的方便之处。官方解释:它是一种可用于在笔记本电脑或台式机上创建虚拟机的个人虚拟化管理工具。更感性一点说的话就是你不需要重装电脑就可以在你的Windows/Mac笔记本上使用Linux了!
Vagrant是一个可以在个人计算机上管理虚拟机生命周期的应用程序。在底层,它需要一个虚拟机管理程序来创建和运行一个虚拟机,它的老搭档是VirtualBox,因为它免费嘛。当然它也支持 Hyper-V 和 VMWare。
首先你要在你的个人计算机(在虚拟化术语中又称主机)上安装VirtualBox和Vagrant。下面要在你的计算机上创建的虚拟机称为客户机。
Virtual Box下载地址,选择对应的操作系统以及平台和体系结构(Intel x86,AMD64等)下载,安装选择默认值即可(注意Mac下安装如果是High Sierra一定要在安全选项给Oracle权限,不然安装会报错,下面的实验也会出问题)。
通过上面的准备,让我们马上创建第一个Ubuntu虚拟机并通过SSH尝试连接它吧。
在Windows上启动命令提示符或在Mac上启动终端,运行以下命令来创建并启动你的Ubuntu虚拟机。
vagrant init hashicorp/precise64
vagrant up
这两行命令后发生的事情我们后面会讲,但现在我们先在本地机器上启动Ubuntu主机即可。第二个命令会有点慢,200K/s的话大概要半小时左右,可以先往下看哈。
在基于UNIX的Mac上,使用SSH到客户机非常简单:只需使用以下命令:
$ vagrant ssh
但在Windows上,这可能就有点困难了,因为它没有原生的SSH客户端,译者用的Mac,所以也没有试过,大家可以自己试试。当一个客户机被创建时,用户vagrant以及它的公钥会一并添加到客户机上。该用户的私钥在主机上可用,可以使用命令“vagrant ssh-config ”查看公钥的路径和 SSHD 在客户机上运行的端口(SSH客户端应连接的端口)。
$ vagrant ssh-config
Host HOST
HostName 127.0.0.1
User vagrant
Port 2222
IdentityFile /Users/USERNAME/vagrant/.vagrant/machines/HOST/virtualbox/private_key
然后你就可以使用这些信息来用像PuTTY这样的SSH客户端来访问客机了。
如果你的需求只是创建一个Ubuntu主机并且用它做点什么,那么你可以不知道当init和up这样的命令在运行时会发生什么。但是,如果您想将Vagrant用作开发环境或者自动化部署,那就需要了解上述简单的配置步骤之外的东西来为你推出基于Vagrant的解决方案做理论支撑。
还记得上面的第一条init命令吗,它会将虚拟机的配置写入到当前目录下的Vagrantfile文件中。当然你也可以自行配置此文件的名称和位置。
示例中,Vagrant init命令会生成Vagrantfile,去掉注释之后,你可以得到以下内容:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "hashicorp/precise64"
end
尽管Vagrantfile的默认文件注释很长,也就是大部分选项都是默认关闭的,你可以按照需求来打开相应配置。
VirtualBox安装是一次性工作,我们之后一般都在Vagrantfile中配置需要的机器并启动它。
关键的是要找到一个合适的基础映像来构建你的客户机,主要是选择操作系统和其提供的默认环境。基础镜像被称为“box”,由配置项config.vm.box指定。box“hashicorp / precise64”指定安装Ubuntu 64位的一个版本。其他操作系统的盒子的示例如下:
客户机启动后,可以使用各种配置方法进行进一步配置,例如内联shell命令,可以通过URL访问的本地脚本。例如,通过在Vagrantfile中添加以下部分,可以将本地脚本作为配置脚本运行:
Vagrant.configure("2") do |config|
config.vm.provision "shell", path: "script.sh"
end
在DevOps驱动的环境中,虚拟机由一些配置管理(CM)工具(如Ansible)进行配置。Vagrant也提供了相应支持。例如,Ansible playbook playbook.yml可以针对新创建的客户机运行,方法是将其指定为Vagrantfile中的provisioner:
Vagrant.configure(2) do |config|
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end
end
客户机在经过几个阶段之后才会从主机中删除。如果配置环节在Vagrantfile已经Vagrant用来管理VM的生命周期的脚本和playbooks中是可以完全捕获的,那么这些客户机可以随时重新创建。
以下是Vagrant各个命令对应的生命周期阶段和一些相关说明:
up - 该命令用于启动Vagrantfile中定义的虚拟机。如果它还没有在主机上,它将被创建。客户机启动并运行后,用户可以登录。
provision - Vagrantfile中定义的预配置器,可以在已经运行的客户机上运行。
reload - 如果在创建客户机之后更改了Vagrantfile,则可以使用此命令重新启动具有更改配置的VM。
suspend/resume - 可以使用这些命令挂起或恢复访客机器。
halt - 关闭来宾机,但底层资源仍然保留。
destory - 关闭客机并从主机中删除相关资源。
可以在主机上创建多个访客机器来完成各种网络操作任务,所有任务均由Vagrant管理。
客户机上打开的端口不能直接访问。访客机器端口通过从主机端口转发到所需的访客机器端口在主机上访问。例如下面一个VM的Vagrantfile中有以下定义:
config.vm.network "forwarded_port", guest: 80, host: 8080
在这种情况下,如果HTTP服务器在客机上的端口80上运行,则可以通过http://host-machine-name:8080来访问它。
访客机器可以使用DHCP来分配IP地址或者从Vagrantfile中分配静态IP。以下是Vagrantfile中的相关示例配置:
config.vm.network "private_network", type: "dhcp"
config.vm.network "private_network", ip: "10.30.2.144"
Vagrant也支持公共网络选项,以将访客机器公开给互联网。由于Vagrant主要用作开发基础设施,因此我不清楚它的用途。
主机上的Vagrantfile所在的项目根目录作为/vagrant挂载在来宾机器上,并且也是可配置的。其他磁盘位置可以如下映射:
config.vm.synced_folder "www/", "/srv/www"
第一个条目在主机上的真实文件夹,第二个条目取决于目录在客机上挂载的位置。如果源路径不是绝对路径,则其是相对于客户机根目录的。
可以使用rsync,NFS和SMB等多种方法来支持在主机和客户机之间共享目录。共享文件夹的行为将取决于你设置的方法。
可以在主机上创建多个访客机器,其受本地可用系统资源的限制。在下面的Vagrantfile代码片段中定义了两个访客机器web和db:
Vagrant.configure("2") do |config|
config.vm.provision "shell", inline: "echo Hello"
config.vm.define "web" do |web|
web.vm.box = "apache"
end
config.vm.define "db" do |db|
db.vm.box = "mysql"
end
end
我们上面讨论过的各种配置选项可以分别应用到每个客户机上。我们也可以像最后一个例子一样通过配置中的内联shell脚本让这些机器共享同样的配置。
Vagrant的真正威力是通过在您的笔记本电脑上设置多机环境进行开发和测试而释放出来的(就像Python的Anaconda和virtualenv一样)。由于复杂的环境配置所涉及的所有步骤都可以在Vagrantfile和相关脚本中捕获,因此可以在团队成员之间共享来实现环境的统一和版本控制。
如果我们使用像前面提到的Ansible这样的CM提供者来构建基于Vagrant的开发环境,将其推广到生产是非常容易的。
而且,这种以代码表示的开发环境的建立和维护过程将影响应用程序开发过程。因为与应用程序代码一样,Vagrant代码可以在开发团队成员之间共享,并且可以由版本控制。
如果公司没有专门维护的数据中心或将服务器托管给其他服务商,只是使用公共云,则使用Vagrant可以最小化需要运行多个客户机来部署开发环境的的本地笔记本电脑的运算开销。
如果你决定将Vagrant加入你日常开发的Toolkit中,那么将它的官方文档通读一遍就是你的必修课了,况且内容也不多嘛。