上一节中,咱们介绍了怎样安装 Vagrant,安装自己并不困难。本章节中咱们首先要快速上手,以便得到一个直观的概念:html
打开命令行工具,终端工具,或者iTerm2等,创建一个咱们将要新建虚机的项目目录,例如 first-vm:node
cd $HOME mkdir -p vms/first-vm cd vms/first-vm
Windows的命令可能像这样:nginx
cd %HOME% mkdir -p vms\first-vm cd vms\first-vm
咱们须要一个彻底空白的工做目录做为开始。如上咱们新建一个目录当作项目目录的基准位置。git
以 Ubuntu 操做系统为虚拟机的例子,咱们能够这样初始化:shell
vagrant init ubuntu/xenial64
这个命令将会去下载 ubuntu 的 box 镜像回来,而后以该镜像为核心,在工做目录下创建一份虚拟机规范描述文件 Vagrantfile。有关的描述咱们稍后会加以介绍。apache
在这里,你须要知道的是,你能够修改或查看这个文本格式的文件。本质上说,Vagrantfile采用ruby等价的语法,因此你能够选择文本编辑器按照ruby进行语法加亮。在启动这个vagrant虚机以前,能够修改Vagrantfile中的配置,例如添加更多网卡。ubuntu
那么,咱们能够启动这个虚机或者关闭它:后端
vagrant up #启动虚机 vagrant halt #中止虚机 vagrant destroy [-f] #删除虚机
删除虚机的指令将会所有删除虚机的后端vmm中的所有相关文件、快照等等,但并不会删除项目目录中的 Vagrantfile 。缓存
当虚机启动以后,在项目目录执行命令 vagrant ssh 能够登陆到虚拟机中。安全
虚机目录 /vagrant 和项目目录是自动同步的,在虚机中写入/vagrant中将会在宿主机中的项目目录中找到相应的内容。
虚机是完整的 Ubuntu 操做系统,当使用 vagrant ssh 登陆到虚拟机中以后,你获得了一个虚拟机的终端控制台,如今你可使用 Ubuntu 自身的shell指令了,而且能够随时经过 exit 结束控制台返回到宿主机的控制台环境。
$ vagrant up ... $ vagrant ssh vagrant@vm1> ll /vagrant ... vagrant@vm1> exit $ ... $ vagrant shutdown
vagrant init [name [url]] # 初始化当前目录到 vagrant 环境 vagrant up # 启动虚拟机 vagrant halt # 关闭虚拟机 vagrant reload # 重启虚拟机 vagrant status # 查看虚拟机运行状态 vagrant destroy [-f] # 销毁当前虚拟机(但不删除Vagrantfile) vagrant suspend # 挂起当前虚拟机 vagrant resume # 恢复被挂起的vm vagrant ssh # SSH 登陆至虚拟机 vagrant box add ADDRESS # 安装box文件/url到本地 vagrant box list # 列出全部本地已安装的box列表 vagrant box outdated # 检查已安装的box是否有更新的版本 vagrant box remove NAME # 删除某个已安装的box vagrant package # 打包当前虚拟机环境为box文件以用于分发 vagrant plugin # 安装卸载vagrant插件 vagrant provision # 执行专门的环境初始化脚本 vagrant ssh-config # 输出ssh链接的一些信息 vagrant version # 获取vagrant的版本
更多命令能够查看 vagrant 官方的文档。
对于刚创建的第一个虚拟机镜像first-vm,它的项目目录名称为“first-vm”,而且已经至少使用 vagrant up 启动过一次了,那么咱们如今能够将这个虚拟机导出为box包:
vagrant package --base=first-vm --output=first-vm-v1.box
这个box一样能够被添加到本机的vagrant boxes缓存中:
vagrant box add first-vm-v1.box --name=first-vm-v1
box文件其实是一个 OVF 包。
开源虚拟化格式OVF文件是一种开源的文件规范,它描述了一个开源、安全、有效、可拓展的便携式虚拟打包以及软件分布格式,它通常有几个部分组成,分别是ovf文件、mf文件、cert文件、vmdk文件和iso文件。
若是网络模式中使用 private_network 的话,在打包以前须要清除一下private_network的设置,避免没必要要的错误:
vm$ sudo rm -f /etc/udev/rule.d/70-persistent-net.rules
这条bash指令应该在虚机中被执行,对于不一样的操做系统来讲,文件的位置多是有变化的。
将这个box文件分发给同事,则他们也能够建立一个彻底等价的虚拟机。
vagrant box add first-vm-v1.box --name=myteam/first-vm-v1 vagrant init my-team/first-vm-v1 vagrant up
此前,咱们经过 vagrant init 的指令建立了新的虚拟机环境,在工做目录中一个 Vagrantfile将被自动建立,若是它还没有存在的话。
这个文件一般应该是这样子的:
# -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| # The most common configuration options are documented and commented below. # For a complete reference, please see the online documentation at # https://docs.vagrantup.com. # Every Vagrant development environment requires a box. You can search for # boxes at https://vagrantcloud.com/search. config.vm.box = "ubuntu/xenial64" # Disable automatic box update checking. If you disable this, then # boxes will only be checked for updates when the user runs # `vagrant box outdated`. This is not recommended. # config.vm.box_check_update = false # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine. In the example below, # accessing "localhost:8080" will access port 80 on the guest machine. # NOTE: This will enable public access to the opened port # config.vm.network "forwarded_port", guest: 80, host: 8080 # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine and only allow access # via 127.0.0.1 to disable public access # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" # Create a private network, which allows host-only access to the machine # using a specific IP. # config.vm.network "private_network", ip: "192.168.33.10" # Create a public network, which generally matched to bridged network. # Bridged networks make the machine appear as another physical device on # your network. # config.vm.network "public_network" # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third # argument is a set of non-required options. # config.vm.synced_folder "../data", "/vagrant_data" # Provider-specific configuration so you can fine-tune various # backing providers for Vagrant. These expose provider-specific options. # Example for VirtualBox: # # 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" # end # # View the documentation for the provider you are using for more # information on available options. # Enable provisioning with a shell script. Additional provisioners such as # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the # documentation for more information about their specific syntax and use. # config.vm.provision "shell", inline: <<-SHELL # apt-get update # apt-get install -y apache2 # SHELL end
这个文件的内容很容易读懂。
box
config.vm.box = "ubuntu/xenial64"
这句话是指定操做系统用的。换句话说,你用文本编辑器修改它也就会随心替换系统了。
只不过若是你真的要这么作的话,须要执行 vagrant destroy; vagrant up 这样的序列,以便清理旧的虚拟机设施和以新的虚机配置建立相应的设施。
对于 VirtualBox来讲,它提供了 VBoxManage 命令行工具能够针对某个 VM 作不少事,modifyvm 就是一条能够修订 VM 配置参数的子命令。而Vagrant也能够在配置文件 Vagrantfile 中操做 virtualbox 以达到相似的目的。例如:
config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--name", "bastion", "--memory", "2048"] end
这个示例能够修改 VM 的内存为 2GB。
网络设置
默认状况下,vagrant通知provider建立 NAT 类型的网卡,这样虚拟机将可以和主机之间相互通信,同时VM可以借助宿主机的外网环境直接访问公网。
在这种状况下,咱们能够指定VM的端口转发来暴露VM中的应用程序的端口,从而在宿主机上能够直接与该端口进行通讯。
config.vm.network "forwarded_port", guest: 80, host: 8080
例如,咱们在VM中安装了nginx的话,上面的端口转发设定能够将其暴露为宿主机的 :8080 ,这样咱们从宿主机或者内网的其余主机均可以访问VM中的nginx服务了。
网络配置是个大话题,咱们稍后会专列一章更多地讲述几种最佳实践。
同步文件夹
咱们曾经提到过当 SSH 到 VM 中时,/vagrant 实际上和主机的VM工做目录是等价的,也就是 Vagrantfile 所在的那个目录。这种特性实际上就是 vagrant 创建的一个同步目录的机制。通常来讲,它是经过 provider 的所谓 共享文件夹(Shared Folder)的特性来实现的。
咱们固然并不须要关心 provider 的特性,也没必要关心 vagrant 是怎么作的。咱们只须要知道,这个链接点是能够被自定义的:
config.vm.synced_folder "../data", "/vagrant_data"
上面这一配置,会将宿主机的 VM工做目录/../data 映射为 VM中的 /vagrant_data。
你还能够作到更多:
使用ruby循环语句创建多个 VMs
在一个Vagrantfile配置中,创建一组VMs是很容易的事情:
(1..3).each do |i| config.vm.define "node-#{i}" do |node| node.vm.provision "shell", inline: "echo hello from node #{i}" end end
值得注意的是,使用ruby的 for i in 1..3 do 循环,你没法获得想要的结果。缘由是 for i in 语句在每次循环迭代时为 i 赋新的值,并重用循环体的语句块,这就致使 |node| 也并不获得新的副本,而是上一次循环时的 node,结果是你只能获得一个不断修改后的单一的 VM。以下所示:
# THIS DOES NOT WORK! for i in 1..3 do config.vm.define "node-#{i}" do |node| node.vm.provision "shell", inline: "echo hello from node #{i}" end end
替换 VM 的 Locale
通常状况下,SSH会话沿用宿主机控制台的Locale,但你能够经过预约义覆盖它,在会话中老是使用特定的语言:
ENV["LC_ALL"] = "en_US.UTF-8" Vagrant.configure("2") do |config| # ... end
Provisioning
Provisioning 也是一个大话题。我会考虑单列一章。
不过在这里,咱们主要是说起这个机制能干些什么。
简单地说,Provisioning是一个首次启动时的后初始化点,它发生在 VM 操做系统被安装就绪,并首次启动完成时。你能够编写 Shell 脚本在这个点自动完成你的专属环境初始化动做,例如安装标准服务、安装bash扩展组件(例如git-prompt)、创建必要的工做文件夹和拉取特定的分发包之类。
若是有必要,在从此,即便VM已经完成了首次初始化了,你也能够经过 vagrant up --provision
这样的指令来强制 VM 开机和再次执行 Provisioning 脚本。
在 Vagrantfile 中,典型地能够这样指定 Provioning:
$script = <<-SCRIPT echo I am provisioning... date > /etc/vagrant_provisioned_at SCRIPT Vagrant.configure("2") do |config| config.vm.provision "shell", inline: $script end
也能够指定一个脚本文件,注意咱们经过 /vagrant 传递 provision.sh 到 VM 中,而典型的 box 系统中,/vagrant 是在 $PATH 搜索路径中的:
Vagrant.configure("2") do |config| config.vm.provision "shell", path: "provision.sh" end
你也能够指定脚本的全路径名,甚至能够在 path 中指定一个 url。