vagrant 知识库

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 
http://wushaobo.info/?p=83

Vagrant让虚拟化技术走近寻常家。脚踏实地地说,网络上类似“两分钟入门”的文章有不少,但求助各种问题的帖子更多,因为vagrant官网的文档太简洁了,这里头有些道理有些坑,都没涉及到。即便是O’Reilly两天前出版的 《Vagrant: Up and Running》 也含糊着某些问题。因而在Google了各种的前人零碎经验的基础上、以自己实践证明之后,有了我这篇文章,希望对涉及到的这些问题能汇总知识做一个澄清,并给读者一个可操作的指导。

文章结构

vagrant 的便利 
vagrant 怎么玩 
vagrant 到底怎么玩 
— vagrant 基础模板哪儿找 
— 辨析 vagrant box | *.box文件 | VM | *.iso文件 
— Vagrantfile 怎么配 
——- [HOWTO] 指定要使用的vagrant box和设置VM名称 
——- [HOWTO] 设置VM对宿主机和外部机器的网络连接 
——- [HOWTO] 配置并启动VM后运行后续安装脚本 
疑难杂症 
— VM上端口的可访问性 
— 修改默认ssh端口 
— 将VM打包成*.box文件前清理网络设置上的障碍 
— 设置共享目录位置与读写权限 
— 多个VM的配置和启动

vagrant 的便利

  • 打造Virtual Machine的过程中可放手做尝试,反复从某个基础模板开始安装或设置。可快速推倒重来,可步步为营。
  • 可快速在一台宿主机上搭建多VM的EndToEnd环境。
  • 管理开发环境,可脚本化复制、操纵等行为,提高自动化程度。

vagrant 怎么玩

简单点说,三步走:

  • 安装 vagrant 、VM软件( Virtualbox 是主流,后文也默认以此为例)
  • 给vagrant添加基础模板(box)
  • 配置Vagrantfile后用vagrant启动VM

满共就三个命令,有些人玩到这就觉得已经伟大的不得了了,至此ssh上VM各种虐。

你还差得远 !

vagrant 到底怎么玩

vagrant 基础模板哪儿找

www.vagrantbox.es 介绍了vagrant的基础模板,并提供了满足各种需求的*.box文件供下载。

推荐选择 minimal + guest additions + puppet|chef 的box,理由:

  • 小,就意味着资源占用少
  • Virtualbox共享目录需要guest additions
  • 预装puppet或chef并非必选。它们对未来提升VM配置自动化有好处,本身不大

辨析 vagrant box | *.box文件 | VM | *.iso文件

解释词汇:

  • 打包了操作系统的 *.iso文件 是无法被vagrant直接使用的
  • VM 是可启动/已启动的虚拟机
  • *.box文件 是vagrant可接受的基础模板文件
  • vagrant box 指vagrant已安装好的基础模板

辨析关系:

  • *.iso文件 可经Virtualbox界面的手动安装得到可启动的 VM
  • VM 可被vagrant package命令打包成为 *.box文件
  • *.box文件 可被vagrant box add命令安装为 vagrant box
  • vagrant box 可被vagrant在Vagrantfile中指定为 VM 运行的基础模板

Vagrantfile 怎么配

Vagrantfile是vagrant配置VM的起点, 官方文档 里零零散散的说明让我明白了“东西很简单,但找对不容易”这句话。

对Vagrantfile,有几个常问 HOWTO :

  1. 指定要使用的vagrant box和设置VM名称
  2. 设置VM对宿主机和外部机器的网络连接
  3. 配置并启动VM后运行后续安装脚本

[HOWTO] 指定要使用的vagrant box和设置VM名称

一看便知。

Vagrant.configure("2") do |config|      # ‘2’的意思是我所用的vagrant-1.2.2属于内部v2版
  config.vm.define :web do |web_config| # 设置此VM名称为web
    web_config.vm.box = "apache-centos" # 指定使用已安装的名为“apache-centos”的vagrant box
  end
end

参考

[HOWTO] 设置VM对宿主机和外部机器的网络连接

  1. 当VM只与宿主机通信时,可设置为私有网络,等效于设置virtualbox使用host-only模式网络适配器。

     config.vm.network :private_network, ip: "192.168.50.4"
    
  2. 当寄宿与同一宿主机上的多台VM之间也需相互通信时,设置各VM为私有网络,但将固定IP设为同一网段。
  3. 当VM需要与宿主机网络内的其他机器通信时,设置为公开网络,等效于设置virtualbox使用bridged模式网络适配器,默认DHCP获取地址。
     config.vm.network :public_network   # vagrant-1.2.2之后的版本可能改用 :bridged
    

参考

[HOWTO] 配置并启动VM后运行后续安装脚本

  1. 追求简单,那么下面两条配置其一就够用了

     config.vm.provision :shell, :inline => "ifconfig"  # inline script
    
     config.vm.provision :shell, :path => "initialize.sh"  # external script
    
  2. 不得不复杂时, Chef / Puppet / Ansible 都是可供你用的。细致配置见 参考 。
  3. 自动化部署是好的,但如果是VM每次安装固定软件,那么就不必了。大可以将不变的软件安装配置完成后,将VM打包成为*.box文件静态化,以后以此box文件作为基础模板做进一步配置。步步为营的提升基础的实践,会加速VM搭建过程并减少配置脚本。

疑难杂症

VM上端口的可访问性

尤其对不连外网的VM,我们辛苦建了它却不能访问它的端口,那要它何用?防火墙是阻止端口访问的罪魁,索性关了它吧。

Centos/Redhat/Fedora 用iptables管理firewall,所以两个办法搞掉它

  1. 停掉iptables的服务, 参考

     $ sudo service iptables save
     $ sudo service iptables stop
     $ sudo iptables off
    
  2. 索性干掉iptables的所有规则, 参考
     $ sudo iptables -F
     $ sudo iptables -X
     $ sudo service iptables save
    

Ubuntu 用ufw管理firewall,关掉它就是了, 参考

$ sudo ufw disable

修改默认ssh端口

场景

ssh端口默认22,那位说“为什么我要改它呢”,我例举一个场景:

假如你要开发一个包含SFTP server的应用。为了给使用者提供便利,你最好保留22端口给用户,使他能使用默认方式通过SFTP传文件。同时,你要将这个应用部署到VM上做测试,那么VM的ssh login就不能同时也用22端口了,你需要为它指定新端口,如 10022。

难点

难点在于下面的约束条件:

  • 原有VM的基础模板默认使用22端口,所以vagrant 不能 一开始就弃用22端口,否则VM无法访问。
  • VM上ssh端口的改变为新端口后,再重启VM前 需要 更改Vagrantfile以选用新端口。
  • vagrant ssh命令 并不 直接访问VM的ssh端口,而是通过访问宿主机的22XX端口来间接ssh login到VM上。
  • vagrant内置了从宿主机22XX端口向VM的22端口的映射,如果VM的新端口并没有被指定映射到宿主机的某个端口上,vagrant ssh命令 仍会 访问原来的宿主机22XX端口即VM的22端口。(vagrant选择22XX端口时的尝试路线是:2222 -> 2201 -> 2202 -> 2203 -> … ,以此保证多台VM启动时不会有端口冲突。)

坑是挺多的吧?Vagrantfile的 ssh settings参考 和 forwarded ports参考 可没把这事儿说这么清楚。

行动大纲

解决问题须要分几步走:

  1. 预先在Vagrantfile中为VM的新端口做端口映射
  2. VM上修改ssh使用的端口到新端口
  3. 在Vagrantfile中指定ssh login时使用VM的新端口
  4. [非必做] 建立新基础模板以固化上述更改

按步骤走起

Step1: 在Vagrantfile中为VM的新端口做端口映射

config.vm.network :forwarded_port, guest: 10022, host: 2255
# config.ssh.port = 2255            # port of host  # commented in step1
# config.ssh.guest_port = 10022     # port of VM    # commented in step1

Step2: VM上修改ssh使用的端口到新端口

  • VM上将22端口换为10022端口:vi编辑sshd_config文件( Centos/Ubuntu: /etc/ssh/sshd_config ;Mac OS X: /etc/sshd_config )

      :%s/#Port 22/Port 10022/g
      :wq
    
  • 重启sshd服务
      $ sudo service sshd restart
    

Step3: 在Vagrantfile中指定ssh login时使用VM的新端口

config.vm.network :forwarded_port, guest: 10022, host: 2255
config.ssh.port = 2255          # port of host  # uncommented in step3
config.ssh.guest_port = 10022   # port of VM    # uncommented in step3

Step4 [optional]: 建立新基础模板以固化上述更改

使用vagrant package命令将改过端口的VM保存为box文件。由这个新基础模板所产生的VM中,10022即为ssh访问端口,使用上述的Vagrantfile可直接通过vagrant ssh访问。

vagrant package <vm-name> --output <new-base.box>

生成新*.box文件前须清理网络设置上的障碍。详见下文。

将VM打包成*.box文件前清理网络设置上的障碍

将手动配置过的VM重新打包生成*.box文件作为新基础模板,在这件事上对linux-based的VM有个关于网络设置的障碍。

问题表现

例如设置了private network(等同于virtualbox设置host-only模式的网络适配器)的VM,若不做准备而直接使用vagrant package生成新box文件,那么安装此box文件到vagrant box后在启动VM时,会发现当前Vagrantfile指定的private network配置失败。

[default] Configuring and enabling network interfaces…

The following SSH command responded with a non-zero exit status. 
Vagrant assumes that this means the command failed!

/sbin/ifup eth1 2> /dev/null

被启动的VM以让可以通过vagrant ssh命令去访问,但网络配置上却没有host-only模式的适配器。

分析解决

还记得配置private network时设置的固定ip地址么?是的,问题就在持久网络设备udev规则(persistent network device udev rules)是被原VM设置好的,再用box生成新VM时,这些rules需要被更新。而这和Vagrantfile里对新VM设置private network的指令发生冲突。

既然以后在Vagrantfile里显示地设置private network ip是免不了的,那么只要在生成box文件前干掉udev规则就是了。

sudo rm -f /etc/udev/rule.d/70-persistent-net.rules

题外话

有趣的是这篇 参考 细述了这个问题的因果与对策,反倒是O’Reilly出版的 《Vagrant: Up and Running》 一书中(第6章)对此含糊带过。

该书计划于2013年6月12日出版。试读版中尚仍有对过时命令的介绍(如“repackage”),希望正书出来了不会立即过时。

学习的话, 官网文档 还是应该对照的。

设置共享目录位置与读写权限

Virtualbox共享目录需要VM上装有Guest Additions。自己安装到VM再打包成box文件做基础模板,或者一开始就找好合适的box文件(前文提到过),随便你怎么整好。

vagrant 默认将宿主机上Vagrantfile所载目录共享至VM上的 /vagrant 目录。

我们常需要的是指定共享某个目录,为此vagrant 支持两种方式:

简单:vboxsf

vboxsf是 V irtual boxS hared F older(或 VboxS hared F older)的缩写。很多人知道可以指定vboxsf作类型来mount,却不知这个这个词全称,甚至误解为“虚拟机文件系统”而错写成vboxfs。

vagrant默认使用这种方式共享目录。优点方便,缺点是性能不好。配置时,只要在Vagrantfile里指明:

config.vm.synced_folder "path/on/host", "/absolute/path/on/vm"
  • 前一个参数须是宿主机上已存在的目录,若为相对目录,那是相对Vagrantfile所在目录。
  • 后一个参数须是VM上的绝对路径,若不存在,vagrant会在启动VM时建好,多层的目录也没关系。

正经:NFS

NFS是正途,不过它也挑剔。

vagrant 内置了宿主机和VM两端对NFS的支持与配置的协调。如果你用windows,那vagrant当作你的配置不存在,直接忽略(我也觉得你在瞎胡闹)。Vagrantfile里很容易,标上标记就行了:

config.vm.synced_folder "path/on/host", "/absolute/path/on/vm", :nfs => true
  • 两个目录可以一样,如都用 “/shared” ,藉此建立多个机器节点的共享存储了。

NFS的共享目录这种方式的挑剔之处在于目录内的读写权限。

读写权限

以建立宿主机与VM的共享存储这个应用场景为例,目标是:

  • 两端对共享目录( /shared )的读写无限制
  • 没有root权限的麻烦

如果你在宿主机建 /shared ,然后直接配置关联,那对上述两个目标你都会失败。按我说的步骤来吧:

  1. 宿主机上将建立的共享目录改为可读写

     $ sudo chmod o+w /shared
    
  2. 设置为non-root用户所有
     $ sudo chown <user>:<group> /shared
    
  3. 配置了Vagrantfile后启动VM
     config.vm.synced_folder "/shared", "/shared", :nfs => true
    

这样得到的共享目录对场景设定的目标已大功告成了:

  • 在宿主机和VM两端都它都不是root用户所有

    • 宿主机上 /shared 属于例如twer用户。
    • VM上 /shared 所属的用户会是个数字,如1000。
  • 在宿主机和VM两端它都对读写无限制

多个VM的配置和启动

单Vagrantfile vs 多Vagrantfile

虽然vagrant支持在一个Vagrantfile中配置多个VM,但我个人喜欢为各VM写各自的Vagrantfile。

  • 一来,各个VM的配置和启动都相对独立,如vagrant ssh时可不指定VM名,用默认。
  • 二来,Vagrantfile也不至于常常要改。

不过真正的牛人没我这么小家子气。用统一的一个Vagrantfile来管理多个VM,从大局着眼确是有好处的:

  • 一个Vagrantfile收录了整个大环境中所有VM的基本配置,维持了虚拟网络的上下文完成。你一眼就知道环境里共有哪些VM,也不需要切换目录来检查各VM的状态,跟不会搞混了目录“丢掉”哪个倒霉的VM。
  • 更多地使用Chef/Puppet来配置各VM,比如把VM的ip配置从Vagrantfile后推到puppet进行,保持Vagrantfile的简洁。目的是在对本地环境的VM配置与E2E环境(甚至生产环境)的节点配置上,保持较高的一致性,有利于统一部署方式。
时间: 2024-08-02 18:16:40

vagrant 知识库的相关文章

谈谈Vagrant中的那些坑:CentOS

安装了vagrant之后,当然需要将它投入使用.由于计划中的生产环境是 CentOS 7,因此想搭建一个 基于CentOS 7(x86_64)的虚拟开发环境. 最开始的一系列工作,比如在vbox中安装CentOS 7.打包box文件.将box导入vagrant等都不在此一一细述,后面将有专文总结这些过程. 然后坑来了:修改Vagrantfile配置文件欲实现 public_network: config.vm.network "public_network", ip: "19

vagrant故障记--升级虚拟机linux内核导致无法挂载共享文件夹

i'm new to use vagrant,今天升级了下vbox里的ubuntu12.04内核,结果vagrant reload后出现报错. Failed to mount folders in Linux guest. This is usually because the "vboxsf" file system is not available. Please verify that the guest additions are properly installed in t

使用Vagrant在Windows下部署开发环境

Vagrant介绍 Vagrant可以提供可配置.可再生.便携的工作环境,它主要是一个中间层技术,它的下层是VirtualBox,VMware等虚拟机软件,它的上层是配置管理系统工具,比如Shell Scripts,Chef,Puppet等可以自动化安装和配置软件的工具. 对你有什么用 对于开发人员来说,Vagrant可以帮你统一团队成员的开发环境.如果你或者你的伙伴创建了一个Vagrantfile,那么你只需要执行vagrant up就行了,所有的软件都会安装并且配置好.团队成员可以通过相同的

vagrant 慕课网 学习笔记

搭建一个环境,不需要重复配置,直接利用vagrant复制就可以了 vagrant 和 virtualbox 的版本必须匹配, 不匹配的话可能会出很多未知的错误 搭配问题可以去官网查看 所有源码在 githup.com/apanly/mooc 如果不能FQ 就请访问 git.oschina.net/apanly/mooc 安装git sudo apt-get install git http://www.imooc.com/video/14218 3-5 vagrant ThinkPHP5运行环境

Vagrant box ubuntu/xenial64 没有密码的解决方法

参考了Vagrant box ubuntu/xenial64 の ubuntuユーザ の passwordについて 1. 可以通过 Git Bash 使用  vagrant ssh 登录到Ubuntu/xenial64的终端中 2. 在终端中输入: vim useradd.sh 文件内容 #!/bin/bash set -Ceu USER="vagrant" # password "vagrant" を SHA-512 でハッシュ化 PASSWORD=$(perl

vagrant初始登录失败的一般性解决方案

vagrant初始登录失败的一般性解决方案 http://www.cnblogs.com/csliwei/p/5860005.html 今天mac机上,遇到的 vagrant halt && vagrant up后 一直卡在: ==> default: Running 'pre-boot' VM customizations...==> default: Booting VM...==> default: Waiting for machine to boot. This

vagrant 启动错误

Stderr: VBoxManage.EXE: error: Failed to create the VirtualBox object!VBoxManage.EXE: error: Code E_NOINTERFACE (0x80004002) - No such interface supported (extended info not available 在VirtualBox安装目录中找到VBoxManage.exe,右击选择属性,设置Windows Server 2008兼容模式运

在WINDOWS上通过VAGRANT练习ANSIBLE

有点曲折,但没办法,还要通过VAGRANT里的ANSIBLE建DOCKER呢.. VagrantFile # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure(2) do |config| config.vm.box = "ubuntu/trusty64" if (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil config.vm.synced_

vagrant随笔

最近开始和几个朋友搞一个项目,用到了vagrant.主要是看重它可以让开发人员在同样开发环境下开发,这样避免每个开发人员因为开发环境不一样导致最后代码上线的一些问题. 优点:我们可以通过 Vagrant 封装一个 Linux 的开发环境,分发给团队成员.成员可以在自己喜欢的桌面系统(Mac/Windows/Linux)上开发程序,代码却能统一在封装好的环境里运行,非常霸气. 下面使用步骤: 1.下载vagrant和VirtualBox vagrant 下载地址: http://www.vagra