Vagrant
您有多少次因为您和其他团队成员之间的环境差异而受到单元测试失败的打击?构建您的项目并使其准备好进行开发有多容易?Vagrant 提供了一种跨多种操作系统创建可重复开发环境的方法来解决这些问题。它是一个位于现有技术之上的薄层,允许项目参与者通过一个命令重现开发环境:vagrant up
。
Vagrant 是开源软件,并且在每个版本中都获得了来自社区的大量贡献。它于 2010 年首次发布。其创始人 Mitchell Hashimoto 于 2012 年 11 月创立了 HashiCorp 公司,致力于 Vagrant 和其他一些 DevOps 工具的开发。HashiCorp 之后发布了许多其他值得关注的工具,例如 Packer、Consul 和 Serf。这些工具适用于开发生命周期的不同领域。
Vagrant 使用来自各种提供商的虚拟机。它允许使用 Vagrantfile 进行轻松配置。这允许开发团队以可编程的方式每次都以相同的方式设置虚拟机。这种可重复性鼓励开发人员更频繁地销毁和启动环境。现在所有团队成员都在其中进行开发的开发环境可以“存储”在版本控制系统中,这样任何人(无论是新成员还是其他人员)都可以在发出单个命令后设置一个环境。
持续集成系统可以使用相同的方法。以这种方式构建环境和设置项目使开发人员可以确信,一旦以相同的方式配置其他环境,项目将像在开发环境中一样运行。环境特定的单元测试失败是 Vagrant 完全消除的一类问题。
Vagrant 将构建和配置软件的过程从团队内部的口头知识转变为与代码一起存储的可重现配置脚本。其他人可以阅读您的 Vagrantfile 和配置脚本,并在几分钟内在他们的系统上运行您的项目。这有助于快速将新开发人员融入您的团队。在更大的公司内启用跨团队开发更容易,因为更容易启动和运行项目。它还允许设计师或技术文档编写人员快速访问您的项目,而无需了解有关如何设置项目的任何技术细节。
Vagrant 技术最初,Vagrant 仅支持 VirtualBox 作为提供商。提供商是 Vagrant 将与之交互的底层虚拟化技术。在撰写本文时,Vagrant 支持各种提供商,VMware、hyper-v 以及最近的 Docker。Vagrant 默认仅附带 VirtualBox 支持。其他提供商可以使用 Vagrant 的插件系统作为插件添加。出于本文的目的,我使用 VirtualBox 作为提供商,因为它默认且可能对所有人最容易访问。它不是性能最佳的提供商;在大多数情况下,VMware 的性能优于它,而 Docker(虽然它不是直接替代品)在速度方面是一项非常令人兴奋的技术,绝对值得关注。
Vagrant 的下一个可配置部分是配置器支持。虚拟机启动后,Vagrant 使用“配置器”以可重复的方式配置 box。这通常在启动虚拟机的过程中完成。最简单的配置器类型是“shell”,它在 VM 启动时以 root 用户身份运行定义的 shell 脚本。更高级的配置器,例如 Salt、Chef 和 Puppet,也可用。在我的工作场所,我们使用 Puppet 来配置我们的虚拟机,以便更好地将我们的开发系统与在生产环境中运行的机器相匹配。
根据提供商的不同,Vagrant 还允许使用“同步文件夹”;这允许在主机和客户机之间非常容易地共享文件夹。这意味着您团队中的每个开发人员都可以使用在主机上运行的不同 IDE 和工具,但仍然可以在同一客户机上进行开发。正如您将在本文后面看到的那样,Vagrant 使这些事情的设置变得非常容易。
如何安装 VagrantVagrant 具有适用于所有主要操作系统的安装程序:Windows、Linux(deb 和 rpm)和 Mac OS X。这种跨主机操作系统的可移植性允许团队中的开发人员在任何环境中获得相同的本地开发体验。
对于本文,我使用了 Ubuntu 12.04 LTS,并且使用了 Vagrant 主页下载部分的 deb 文件。对于不接受 deb 或 rpm 包类型的 Linux 发行版,仍然可以运行旧版本的 Vagrant,前提是该发行版支持 Ruby 和 Ruby gems,但这在新版本的 Vagrant 中已不再支持。
如果您尚未安装 VirtualBox,则需要安装它。这可以通过包管理器完成,尽管我使用了 Oracle 网站上提供的软件包。
本文使用 Vagrant 1.6 和 VirtualBox 4.3。
使用 Vagrant在本文中,我将介绍如何使用 Vagrant 设置项目,包括如何编写 Vagrantfile、如何使用 Vagrant 启动虚拟机以及如何与该 VM 交互。您需要的第一件事是构建项目的基础 box。基础 box 是一个特定于提供商的精简操作系统磁盘映像,其中安装了一些基本内容。Vagrant 使用 SSH 连接到其所有 box,因此必须启用 SSH 服务器,并且必须为特定用户启用 SSH。制作与 Vagrant 兼容的 box 还有许多其他要求。该过程对于本文来说太复杂了,但更具体的说明可以在 Vagrant 或特定提供商的网站上找到。默认情况下,Vagrant 期望 box 上有一个 vagrant 用户,并且密码(按照惯例)应为“vagrant”。
出于本文的目的,您将使用一个公开可用的基础 box。HashiCorp 为 Ubuntu 12.04 LTS 提供了一个基础 box。要将 box 添加到 Vagrant
$ vagrant box add "hashicorp/precise32"
此命令从 Vagrant 云下载 box。Vagrant 云是 HashiCorp 提供的一项服务,除其他外,它还提供 box 发现功能。社区基础 box 已上传,可以使用。Vagrant 知道您正在从 Vagrant 云访问基础 box,并将直接从那里下载它。下载后,您无需再次下载基础 box 以在同一主机上的其他 Vagrant 项目中使用。您可以使用 list 命令查看可用的 box
$ vagrant box list
hashicorp/precise32 (virtualbox, 1.0.0)
现在 box 已添加,您将编写一个基本的 Vagrantfile。Vagrantfile 是一个 Ruby 文件,它为您的 box 设置某些变量。这是一个基本的 Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise32"
end
这显示了 Vagrant 的强大功能——通过这个简单的文件,可以在 Vagrant 支持的任何系统上创建和启动 Ubuntu 12.04 LTS 虚拟机。要启动 Vagrant VM,只需执行以下操作
$ vagrant up
虚拟机可能需要一些时间才能启动,但是当命令返回到提示符时,您已成功启动了虚拟机。此时,可能值得打开 VirtualBox 应用程序,以便您可以查看已创建的新虚拟机并确保它被标记为正在运行。

图 1. VirtualBox 屏幕截图
正如我之前提到的,用于 Vagrant 的基础 box 必须可以通过 SSH 访问。这允许您通过在与 Vagrantfile 相同的目录中执行以下操作来连接到您的新虚拟机
$ vagrant ssh
您将留在虚拟机中的 bash 提示符中。通过两个命令,您已启动 VM 并 ssh
进入 VM。在继续更强大地使用 Vagrant 之前,还需要注意一件事是,默认情况下,Vagrant 共享 Vagrantfile 所在的目录,该目录位于 /vagrant 文件夹下。
客户机
$ cd /vagrant
$ echo "test" > test
主机
$ ls
test Vagrantfile
应该很清楚,您在客户机上创建了一个新文件“test”,并且该文件出现在主机上的同一目录中。Vagrant 使用 VirtualBox 共享文件夹,使您可以非常轻松地保持主机和客户机之间的文件同步。当使用 Vagrant 开发软件项目时,这尤其有用,因为您希望能够本地编辑文件并使这些更改自动出现在您的开发 VM 中以进行测试。它允许开发人员在与团队中任何其他人相同的平台上进行开发时运行他们选择的编辑器。
配置您已经了解了如何使用 Vagrant 启动简单的虚拟机,接下来,让我们看看如何以可重复的方式配置该 VM。如前所述,Vagrant 支持各种配置器,但为了本文的目的,由于 bash 脚本的熟悉性,将使用 bash 脚本。添加配置步骤只需在 Vagrantfile 中的配置块内添加一行即可。引导程序也可以是内联脚本,但在大多数情况下,提供包含配置步骤的脚本文件是有意义的。
将以下 bootstrap.sh 脚本添加到与 Vagrantfile 相同的目录中
#!/usr/bin/env bash
# provisioning is run as root by default
# make sure system sources are up to date.
apt-get update
# install a web server
echo "==== Installing NGINX ===="
apt-get install -y nginx
echo "==== Start the NGINX Server ===="
service nginx start
此引导脚本首先确保系统源是最新的。然后它安装 nginx Web 服务器。通过将以下行添加到配置块,将配置添加到 Vagrantfile,以便您的 Vagrantfile 现在看起来像这样
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise32"
config.vm.provision :shell, :path => "bootstrap.sh"
end
要使用新的配置,请销毁正在运行的 VM。这将停止并删除虚拟机。要销毁 VM,只需使用命令 vagrant destroy
。在运行 destroy 命令后,基础 box 仍然可用。现在要测试新配置,只需运行 vagrant up
。当 Vagrantfile 中存在配置步骤时,Vagrant 会在 box 启动后自动配置它。您可以使用 --no-provision
标志关闭配置。
当 vagrant up
完成后,您将能够像以前一样 ssh
进入机器。如下所示,让我们确保配置已成功。请注意,nginx 现在已安装在系统上并在系统上运行
$ vagrant ssh
$ which nginx
/usr/sbin/nginx
$ netstat -at | grep http
tcp 0 0 *:http *:* LISTEN
虚拟机已配置,并且 nginx 已设置并启动。可以测试 Web 服务器是否正常工作,但是如果您必须 ssh
进入 box 进行测试,则会更加困难。接下来,让我们看看如何配置网络。
访问虚拟机端口的第一个选项是端口转发。在此示例中,nginx 在端口 80 上提供 http 流量。要将客户机端口 80 转发到主机上的端口 8080,请将以下行添加到 Vagrantfile
config.vm.network "forwarded_port", guest: 80, host: 8080
和以前一样,销毁 VM 并再次执行 vagrant up
。虚拟机启动并配置后,可以在主机端口 8080 上访问 Web 服务器。在您喜欢的浏览器上,访问 https://127.0.0.1:8080/ 以迎接 nginx 主页。这是连接到虚拟机的更简单方法之一。
例如,让我们修改 bootstrap.sh 以将 Vagrant 目录中的“html”目录链接到 nginx 根目录。这将是进行简单的静态 HTML 网站开发的示例。这可以分发给任何人,以修改主机上的 HTML 并立即在客户机上看到结果。
修订后的引导程序如下所示
#!/usr/bin/env bash
# provisioning is run as root by default
# make sure system sources are up to date.
apt-get update
# install a web server
echo "==== Installing NGINX ===="
apt-get install -y nginx
echo "==== Start the NGINX Server ===="
service nginx start
echo "==== Symlink Test Directory ===="
ln -s /vagrant/html/ /usr/share/nginx/www/html
一旦 VM 由 Vagrant 启动和配置,您就可以通过 nginx Web 服务器使用转发的端口访问 html 目录。例如,使用 curl
$ curl "https://127.0.0.1:8080/html/tester.html"
此示例假定您的 Vagrant 目录中有一个 html 目录,其中包含一个 tester.html 文件。
如果您想提供一种访问虚拟机的方式,就像它是网络上的另一台机器一样,该怎么办?Vagrant 提供了一种非常简单的方法来使用 VirtualBox 网络在同一 LAN 上为虚拟机设置静态 IP。从 Vagrantfile 中删除端口转发行,并将其替换为以下内容
config.vm.network "private_network", ip: "192.168.56.20"
重新运行 vagrant up
后,您可以使用上面指定的 IP 地址从主机访问您的虚拟机。在我自己的项目中,我使用此专用网络通过修改 /etc/hosts 文件为我的静态 IP 分配一个域名。这允许测试依赖于特定域名的复杂 http 重定向流。
它还允许多个 Vagrant 虚拟机相互联系,因为它是主机和网络上所有其他虚拟机之间的共享网络。对于分布式项目,能够控制多个独立组件的网络访问非常强大,所有这些组件都有自己的 Vagrantfile(或共享)。
同样,在我的工作环境中,启动多个虚拟机并不罕见,一个用于数据库,一个用于应用服务器,一个用于 squid 代理。针对这些测试运行功能测试,模拟生产环境设置。Vagrant 允许您以简单、易于重复的方式执行此操作,并且专用网络意味着在设置各个组件之间的互通方面没有任何麻烦。
我要介绍的 Vagrant 的最后一部分是在一个 Vagrantfile 中拥有多台机器。我已经给出了一个示例,说明为什么您可能想要为不同的组件拥有多个 Vagrantfile,以便可以单独或作为一个整体对其进行测试/开发。当单个项目可以有多个不属于一台机器的部分时,在一个 Vagrantfile 中拥有多台机器非常强大。通常在 Web 开发项目中,您将在同一台机器上运行应用服务器和数据库进行测试,但当该系统进入生产环境时,将有多个应用服务器和数据库。这是由于未经测试的组件配置而导致许多生产 bug 的原因。
Vagrant 允许您通过单个 Vagrantfile 管理所有这些。如果多台机器的想法让您感兴趣,我还建议仔细研究 Vagrant 的新 Docker 容器选项。Docker 构建于 Linux 容器之上,并允许您比 VirtualBox 更快地启动机器。如果提供商级别启动机器的速度更快,则 Vagrant 中的多机器支持将更加强大。
对于多机器支持,Vagrantfile 允许您配置多台机器,每台机器都有自己的配置。下面的 Vagrantfile 显示了一个 MySQL 主从 Vagrantfile 可能看起来像什么样的示例
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise32"
config.vm.define "master" do |master|
master.vm.provision :shell, :path => "master_bootstrap.sh"
master.vm.network "private_network", ip: "192.168.56.20"
end
config.vm.define "slave" do |slave|
slave.vm.provision :shell, :path => "slave_bootstrap.sh"
slave.vm.network "private_network", ip: "192.168.56.21"
end
end
每台机器都使用第一个配置块定义为单独的块。它们支持与普通单机 Vagrant 配置块相同的所有选项。例如,对于此处的主服务器,您定义要运行的 shell 配置脚本以及要为此虚拟机提供的静态 IP 地址。这允许您以与单机相同简单可重复的方式测试分布式系统。
当使用像上面这样的多机器配置时,您必须运行 Vagrant 命令的方式有一些变化。运行 vagrant up
将自动启动两个 box。将首先配置主服务器,然后再配置从服务器。您可以选择仅启动其中一台机器,方法是提供机器名称
$ vagrant up master
当 box 启动并配置后,在使用 vagrant ssh
时,您还必须指定机器名称。
让我们回顾一下您在这里取得的成就:多台虚拟机启动、自动配置和一致的 IP 地址,只需一个命令——vagrant up
。这在三大主要操作系统和许多不同的提供商(包括最流行的虚拟化技术和云服务)中都是可重复的。
这消除了在本地开发系统中工作的许多痛点。切换到使用 Vagrant 进行本地开发和持续集成系统有很多优点。所有开发人员的测试机器都在运行相同的代码,并以相同的方式进行配置。测试失败与特定开发人员的设置无关,并且应该可以通过在任何人的机器上运行 vagrant up
来重现。本文仅介绍了 Vagrant 的一些惊人功能,因此我也鼓励您阅读 http://docs.vagrantup.com 上的精彩文档。