Vagrant 简介

作者: Jay Palat

您是否听过以下说法? “欢迎加入团队!这是一份包含 15 个应用程序的安装列表,说明文档在团队房间的某个地方。一周后见!” 或者:“什么?你说生产环境崩溃了,但在我的机器上运行良好啊?” 或者:“为什么这个程序在她的机器和他的机器上都能工作,但在我的机器上却不行?”

开发环境正变得越来越复杂,包含更多移动部件和棘手的依赖关系。虚拟化已成为 IT 行业的一大福音,它节省了成本,提高了灵活性,并保持了对复杂环境的控制。与其关注交付端的虚拟化,不如看看如何为开发人员提供灵活性和控制力,以便使用 Vagrant 轻松管理多个开发环境。

什么是 Vagrant?

Vagrant 是一个开源 (MIT) 工具,用于构建和管理由 Mitchell Hashimoto 和 John Bender 开发的虚拟化开发环境。Vagrant 管理托管在 Oracle VirtualBox 中的虚拟机,VirtualBox 是一个完整的 x86 虚拟化器,也是开源的 (GPLv2)。

虚拟机是计算机的软件实现,在虚拟化器上运行完整的操作系统堆栈。它是计算机的完整实现,带有虚拟磁盘、内存和 CPU。运行虚拟化器的机器是宿主机系统。在虚拟化器上运行的虚拟机是客户机系统。就客户机操作系统而言,它运行在真实的硬件上。从宿主机的角度来看,客户机的所有资源都由虚拟化器程序使用。Box 或基础镜像是由 Vagrant 管理的预打包虚拟机。

安装 Vagrant

从 1.0 版本开始,Vagrant 提供了两种安装方法:受支持平台的软件包安装程序或使用 Ruby Gems 的通用安装。本文介绍使用 Gems 进行安装。此方法分为三个部分:1) 安装 VirtualBox,2) 安装 Ruby,以及 3) 安装 Vagrant 本身。

VirtualBox 可从 VirtualBox 主页获得,其中包含适用于 Windows、OS X、Linux 和 Solaris 的构建版本。请注意,Oracle 在下载站点上提供了 Oracle VM VirtualBox Extension Pack,该扩展包为虚拟化器提供了附加功能。Extension Pack 具有单独的许可证(个人使用和评估许可证),使用 Vagrant 不需要它,但是如果您使用的 Box 是使用 Extension Pack 创建的,则您也需要安装 Extension Pack。

Ruby 是一种流行的动态类型面向对象脚本语言。OS X 中开箱即用地提供了 Ruby,大多数 Linux 发行版也提供了 Ruby 软件包。对于 Windows 用户,RubyInstaller 项目提供了一种安装 Ruby 运行时的简便方法。

Ruby 库和应用程序以名为 RubyGems 或 Gems 的软件包形式提供。Ruby 附带一个名为 gem 的软件包管理工具。要安装 Vagrant,请运行 gem 命令


> gem install vagrant

Vagrant 是一个命令行工具。调用不带任何参数的 vagrant 将提供可用参数的列表。我将在本文中介绍大多数这些命令,但这里有一个快速概述

  • init — 创建基本配置文件。

  • up — 启动虚拟机的新实例。

  • suspend — 挂起正在运行的客户机。

  • halt — 停止正在运行的客户机,类似于按下真实机器上的电源按钮。

  • resume — 重新启动已挂起的客户机。

  • reload — 重新启动客户机。

  • status — 确定当前 Vagrantfile 的 vagrant 状态。

  • provision — 运行配置命令。

  • destroy — 删除客户机的当前实例,删除虚拟磁盘和关联文件。

  • box — 用于添加、列出、删除或重新打包 box 文件的一组命令。

  • package — 用于创建新的 box 文件。

  • sshssh 连接到正在运行的客户机。

安装中您需要做的最后一件事是设置基础镜像。Box 或基础镜像是由 Vagrant 管理的预打包虚拟机。使用 box 命令将 Box 添加到您的环境中。vagrant box add 命令接受两个参数,您用来引用 Box 的名称和 Box 的位置


> vagrant box add lucid32 http://files.vagrantup.com/lucid32.box

此命令从远程托管站点通过 HTTP 添加一个名为 “lucid32” 的新 Box。Vagrant 还允许您从本地文件系统安装 Box


> vagrant box add rhel5.7 rhel5.7-20120120-1223.box
[vagrant] Downloading with Vagrant::Downloaders::File...
[vagrant] Copying box to temporary location...
[vagrant] Extracting box...
[vagrant] Verifying box...
[vagrant] Cleaning up downloaded box...
> 

现在安装了两个 Box


>vagrant box list
lucid32
rhel5.7

重要的是要注意,您可以重复使用这些基础镜像。一个 Box 可以作为多个项目的基础,而不会受到污染。任何一个项目中的更改都不会更改共享 Box 的其他项目。正如您将看到的,基础镜像中的更改可以轻松地共享到项目中。使用 Vagrant 的强大概念之一是,开发环境现在是完全可抛弃的。您将关键工作持久保存在宿主机上,而客户机可以快速重新加载并从头开始配置。

启动 Vagrant

在宿主机上创建一个目录作为您的起点。此目录是您的工作目录。Vagrant 将自动在客户机和宿主机之间共享此目录。开发人员可以使用他们喜欢的编辑器或 IDE 编辑文件,而无需更新客户机。在宿主机或客户机中所做的更改对用户来说都是立即可见的,无论从哪个角度来看


> mkdir ProjectX
> cd ProjectX

要开始使用,您需要一个 Vagrantfile。Vagrantfile 类似于 Makefile,是一组指令,告诉 Vagrant 如何构建客户机。Vagrant 使用 Ruby 语法进行配置。最简单的 Vagrantfile 如下所示


Vagrant::Config.run do |config|
  config.vm.box = "lucid32"
end

此配置告诉 Vagrant 使用所有默认设置和名为 lucid32 的 Box。实际上,Vagrant 读取四个 Vagrantfile:当前目录中的本地版本、~/.vagrant.d/ 中的用户版本、Box 文件中的 Box 版本以及随 Gem 安装的初始配置。Vagrant 从 Gem 版本开始读取这些文件,到当前目录结束。如果发生冲突,最新版本获胜,因此当前目录覆盖 ~/.vagrant.d,后者覆盖 Box 版本,依此类推。用户只需运行以下命令即可创建新的 Vagrantfile


> vagrant init 

这将在当前目录中创建一个 Vagrantfile。生成的 Vagrantfile 具有许多常用配置参数,并附有关于其用法的注释。该文件力求做到自文档化,但其他信息可从 Vagrant 网站获得。要运行大多数 Vagrant 命令,您需要位于与 Vagrantfile 相同的目录中。

让我们试一试


$ vagrant up
[default] Importing base box 'lucid32'...
[default] The guest additions on this VM do not match the install 
version of VirtualBox! This may cause things such as forwarded 
ports, shared folders, and more to not work properly. If any of 
those things fail on this machine, please update the guest 
additions and repackage the box.

Guest Additions Version: 4.1.0
VirtualBox Version: 4.1.8
[default] Matching MAC address for NAT networking...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Mounting shared folders...
[default] -- v-root: /vagrant

让我们分解一下。我正在使用 VirtualBox 4.1.8 和客户机 4.1.0 运行。在这种情况下,它运行顺利,但警告旨在帮助排除出现的问题。接下来,它为客户机设置网络


[default] Matching MAC address for NAT networking...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)

我使用了网络地址转换和端口转发的默认网络设置。我将宿主机上的端口 2222 转发到客户机上的端口 22。Vagrant 在无头模式下启动客户机,这意味着不会弹出 GUI 界面。对于想要使用客户机 GUI 版本的用户,可以在 Vagrantfile 中选择在窗口中运行。网络设置完成后,Vagrant 启动虚拟机


[default] VM booted and ready for use!
[default] Mounting shared folders...
[default] -- v-root: /vagrant

客户机启动后,Vagrant 将添加共享文件夹。Vagrant 使用 VirtualBox 扩展将当前文件夹(在本例中为 ProjectX)挂载为 /vagrant。用户可以在宿主机操作系统的 ProjectX 目录中复制和操作文件,所有文件和更改都将在客户机中可见。如果共享文件夹由于您有大量文件而性能不佳,Vagrant 确实支持使用 NFS。但是,这确实要求客户机宿主机系统都支持 NFS。目前,Windows 宿主机不支持 NFS。

要访问客户机,Vagrant Box 有一个默认用户,用户名:vagrant,密码:vagrant,以及一个默认共享的不安全 ssh 密钥。如果 Vagrant 用户需要更改客户机操作系统,他们通常拥有 sudo 权限。您可以使用 ssh vagrant@localhost 2222 在宿主机上 ssh 连接到客户机,或者使用 vagrant 快捷方式


>vagrant ssh

虽然您可以使用 vagrant ssh 自动访问您的客户机,但有时使用 scpgit 会很有用,这指的是您的 SSH 设置。为了方便起见,您可以更新 ~/.ssh/config 中的条目,其中包含特定于客户机的信息(Windows 用户可以通过对其 PuTTY 配置进行类似的更新来获得类似的结果)


>vagrant ssh-config 
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/jay/.vagrant.d/insecure_private_key
  IdentitiesOnly yes

通过将此信息插入到 ~/.ssh/config 中,您可以使用 scp 访问您的客户机,将文件 my_file 从 /vagrant 移动到宿主机桌面


> scp default:/vagrant/my_file.txt ~/Desktop/my_file.txt

如果您想在您的客户机上运行一个 Web 服务器,并且可以从宿主机访问,该怎么办?让我们添加一个。编辑您的 Vagrant 文件,添加以下行


config.vm.forward_port 80, 8080

forward_port 参数允许宿主机将端口从宿主机转发到客户机。在本例中,您将宿主机上的端口 8080 转发到客户机上的端口 80。默认情况下,Vagrant 使用网络地址转换网络,这意味着客户机可以通过宿主机访问网络。除非端口被转发,否则宿主机网络上的机器无法直接访问客户机。Vagrant 还提供仅主机网络,其中客户机只能访问宿主机或宿主机上的其他客户机,以及桥接网络,其中客户机将与宿主机位于同一网络上。更新 Vagrantfile 后,重新启动系统


>vagrant reload

请确保在 Vagrant 中打开端口转发时,您也打开了客户机上相应的防火墙权限!如果您尝试通过端口转发连接到打开了防火墙的客户机,则初始握手将使用宿主机端口(本例中为 8080)工作,但如果端口 80 被客户机防火墙阻止,则会失败。

完成 Vagrant

完成工作后,您有几个选择。如果您只是今天的工作结束了,或者想为宿主机回收一些资源,您可以简单地挂起 Vagrant


>vagrant suspend

并恢复


>vagrant resume 

当您想重新启动时。所有状态都将保留,并且不会丢失任何内容。一旦环境完全完成,或者如果您想从一个干净的状态重新开始,您可以运行 vagrant destroy。这将删除客户机和共享文件夹 (/vagrant) 之外内容的任何更改。共享文件夹驻留在宿主机上,并且在客户机销毁后仍然存在。

配置客户机

创建和维护虚拟镜像在配置方面可能是一个微妙的平衡。过度配置镜像,当应用程序被补丁替换时,它会更快地变得陈旧。使用简单的基础镜像对镜像进行配置不足,每次创建新实例时,用户都必须花费时间将 Box 配置为项目的确切规范。使用 Vagrant,有一个很好的中间地带。可以创建基础镜像并进行最小限度的更新,以管理操作系统级别的补丁和库,而应用程序可以使用 Chef、Puppet 或 shell 脚本等工具进行配置。

许多系统管理员已经熟悉 Chef 和 Puppet,这两种配置管理工具允许一致地创建和维护系统。通过将 Chef 和 Puppet 插入 Vagrant,用户可以立即利用系统管理员已经创建的脚本来创建最新的开发镜像。

Chef 和 Puppet 都支持以单机/独立模式和服务器模式工作。在 Chef Solo 或 Puppet 独立模式下,镜像的配置都是自包含的。在服务器模式下,Chef 或 Puppet Server 用户可以利用其公司中已建立的现有 Chef 或 Puppet 基础架构。

本文不会详细介绍 Chef,但让我们看一个使用 Chef 如何有帮助的简单示例。Vagrant 可以在没有其他服务器的情况下在 Chef-solo 模式下运行。要设置 Chef,您首先需要一个 Cookbook。Cookbook 是 Recipes 的集合。Recipe 是对您希望如何配置系统的描述。Recipes 也用 Ruby 编写。对于本示例,我从 Opscode 社区站点下载了 Cookbooks。

在本示例中,让我们在客户机上安装 Apache2 和 MySQL。这是设置。在 ProjectX 目录下创建一个名为 “cookbooks” 的目录。从 http://community.opscode.com 下载 Apache2 和 MySQL 的 Cookbooks(请参阅资源)。此外,您还需要两个依赖项:用于获取最新更新的 apt recipe 和 MySQL recipe 所需的 openssl。

提取这些文件并将它们保存到 cookbooks 目录


> ls -l cookbooks/
total 0
drwxr-xr-x@ 10 jay  staff  340 Feb 16 18:49 apache2
drwxr-xr-x@  9 jay  staff  306 Feb 14 12:00 apt
drwxr-xr-x@  9 jay  staff  306 Feb 16 18:23 mysql
drwxr-xr-x@  7 jay  staff  238 Jun  3  2011 openssl

在我的 Vagrantfile 中,我添加了以下行


config.vm.provision :chef_solo do |chef|
  chef.cookbooks_path = "cookbooks"
   chef.add_recipe("apt")
   chef.add_recipe("openssl")
   chef.add_recipe("mysql::server")
   chef.add_recipe("apache2")
  # You may also specify custom JSON attributes:
    chef.json = {
             :mysql => {
                   :server_root_password => "MYSQL PASSWORD"
                  }
              }
  
end

当 Vagrant 运行配置步骤时(包含在 vagrant up 中,但也通过使用 vagrant provision 在正在运行的客户机上可用),它将安装 apt、openssl、mysql 和 apache2。Recipes 也可以接受参数。在本示例中,我包含了一个 mysql recipe 的参数,该参数设置了服务器 root 密码。给定 recipe 的可用参数包含在文档中。这些参数作为 JSON 属性传递给 Vagrant,Vagrant 会将它们传递给 Chef。

使用 Vagrant 管理此操作允许您对环境强制执行变更控制。Vagrantfiles 和 Cookbooks 可以签入源代码控制并像代码资源一样进行管理。分支和标记环境配置可用于跟踪项目开发或需求和软件包更新时的更改。

创建新镜像

传统方法是使用 VirtualBox 使用标准操作系统安装程序创建新的虚拟机镜像。由于操作系统步骤各不相同,我在这里不详细介绍,但以下是一些关键步骤

  • 在选择虚拟磁盘存储详细信息时,选择 “动态分配”——您希望您的磁盘从小开始,但能够根据需要增加。

  • 如果您想将 Chef 或 Puppet 与您的应用程序一起使用,您需要在创建基础镜像时安装 Chef 或 Puppet 应用程序。

  • 安装 VirtualBox Guest Additions。这是支持共享文件夹所必需的!

让我们设置 vagrant 用户。创建一个用户,用户名为 vagrant。将此用户添加到管理员组。更新 sudoers 文件,以确保管理员组中的用户无需密码即可访问 sudo。对于名为 “admin” 的组,它应如下所示


%admin ALL=NOPASSWD:ALL

还要确保 Defaults requiretty 已注释掉。您还需要确保您可以 ssh 进入 Vagrant 帐户。默认情况下,Vagrant 将尝试将不安全的 SSH 密钥与 vagrant ssh 一起使用。要将密钥添加到您的 Vagrant 帐户,请以 vagrant 用户身份执行以下操作


> mkdir .ssh
> chmod 755 .ssh
> curl -L http://github.com/mitchellh/vagrant/raw/master/
↪keys/vagrant.pub
> > .ssh/authorized_keys
> chmod 644 .ssh/authorized_keys

镜像完成后,您需要将镜像打包到 Box 中。要为 Box 创建一组默认配置,您可以创建一个新的 Vagrantfile。使用 vagrant package,它接受两个参数 --base(您在 VirtualBox 中创建的镜像的名称)和 --include(接受您希望包含在 Box 中的文件)


> vagrant package --base RHEL-5.7-64 --include Vagrantfile 

在本示例中,您创建了一个包,其中包含名为 RHEL-5.7-64 的基础镜像,并包含了您的自定义 Vagrantfile。

总结

Vagrant 是一个用于创建和管理灵活开发环境的强大工具。在本文中,我介绍了 Vagrant 镜像的基本使用和创建。

资源

Vagrant 的 Web 主页: http://vagrantup.com

VirtualBox: https://www.virtualbox.org/wiki/Downloads

Ruby: https://ruby-lang.org.cn/en/downloads

RubyInstaller(适用于 Windows): https://rubyinstaller.ruby-lang.org.cn

Opscode 社区站点: http://community.opscode.com

Chef Cookbooks

Vagrantbox.es(一个列出 Boxes 的网站): http://vagrantbox.es

加载 Disqus 评论