Vagrant 使用记录

2022/03/11

用途

构建和管理虚拟机。

易用的工作流,减少开发环境的部署时间。

虚拟机支持 VirtualBox, VMware, AWS, or 其他

对比 Docker

Vagrant 专注于提供一致的跨平台开发环境工作流 ,而 Docker 是容器管理器,提供一致的容器运行环境。

Docker 容器比虚拟机轻,启动和停止都很快。但是目前缺少对某些操作系统(例如 BSD)的支持,如果你的目标环境是这些系统,用 Vagrant 会更合适。

重度微服务环境,使用 Docker 会更方便,而 Vagrant 使用 Docker provider 可以做到一样的事。Vagrant 的主要优势是提供一致的工作流,也有许多情况下纯 Docker 环境会更有意义。

似乎对比 Docker 没有足够的多的优势?

对比 Terraform

Terrafrom 也是 HashiCorp 的项目。Terraform 用来搭建基础设施。

Terraform 可以描述复杂的本地或远程的基础设施集合。可以在 Terraform 中重现虚拟机生命周期的最小化方面。

Vagrant 提供很多 Terraform 不具备的高级特性(同步目录、自动网络、HTTP 隧道等等),以简化开发环境的使用。因为 Terraform 用在管理基础设施而不是开发环境。

Terraform 用于管理云供应商(例如 AWS)的远程资源,它可以管理跨多个云供应商的大型基础设施。

Vagrant 主要用于少量虚拟机的本地开发环境。

Getting start

安装 VagrantVirtualBox

brew install vagrant

Up & Run

mkdir vagrant-playground
cd $_

vagrant init hashicorp/bionic64
vagrant up

vagrant ssh
logout

vagrant destroy

如果你遇到按 enter 键识别成 ^M 问题,按 Ctrl+C 终止命令,输入 stty sane 之后再试。

参考: https://www.oreilly.com/library/view/bash-cookbook/0596526784/ch19s09.html

Box

虚拟机的基础镜像。当 vagrant init hashicorp/bionic64 执行后,当前目录会添加一个 Vagrantfile 文件:

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/bionic64"
end

vagrant destroy 命令不会删除下载的 box 文件,通过如下方式查找并删除

~/dev/vagrant-playground                                                                                                                                                         16:56:02
❯ vagrant box list
hashicorp/bionic64  (virtualbox, 1.0.282)
ubuntu/bionic64     (virtualbox, 20210623.0.0)
~/dev/vagrant-playground                                                                                                                                                         16:56:03
❯ vagrant box remove hashicorp/bionic64
Removing box 'hashicorp/bionic64' (v1.0.282) with provider 'virtualbox'...

类比 Docker 中的 Base Image

同步本地目录

当前包含 Vagrantfile 的目录,会挂载到虚拟机里的 /vagrant 目录,虚拟机中可以直接修改这个目录的内容。(因此不要在虚拟机中尝试 rm -rf / !)

vagrant up
vagrant ssh
touch /vagrant/foo
logout
ls
# 你可以看到当前目录下多了一个 foo 文件

类比 Dockerfile 中的 VOLUME ?

Provision

利用 Provision 我们可以在每次 vagrant up 启动虚拟机的时候自动安装软件。

下面举一个在虚拟机中启动 apache web 服务器的例子。

本地新建一个目录,名为 html ,添加一个静态页面:

mkdir html
cat <<EOF >> html/index.html
<!DOCTYPE html>
<html>
  <body>
    <h1>Getting started with Vagrant!</h1>
  </body>
</html>
EOF

再添加一段脚本 bootstrap.sh 用命令安装 apache 服务:

#!/usr/bin/env bash

apt-get update
apt-get install -y apache2
if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

更新 Vagrantfile:

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/bionic64"
  config.vm.provision :shell, path: "bootstrap.sh"
end

启动虚拟机 vagrant up

但如果你的虚拟机正在运行,也不需要将它关闭,只需要 vagrant reload --provision

登录虚拟机验证:

vagrant up

##...

vagrant@vagrant:~$ **curl 127.0.0.1**
<!DOCTYPE html>
<html>
  <body>
    <h1>Getting started with Vagrant!</h1>
  </body>
</html>

对于复杂的 provision 脚本,官方推荐直接使用预安装软件的自定义镜像。

类比 Dockerfile 中的 ENTRYPOINT ?

配置端口转发

接着上面的例子,如果我们想从宿主机访问虚拟机的 web 服务怎么办?那就要配置端口转发。

修改 Vagrantfile:

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/bionic64"
  config.vm.provision :shell, path: "bootstrap.sh"
  config.vm.network :forwarded_port, guest: 80, host: 4567
end

然后重载虚拟机 vagrant reload

通过访问本地 4567 端口,就可以访问到虚拟机内的 web 服务了

$ curl 127.0.0.1:4567
<!DOCTYPE html>
<html>
  <body>
    <h1>Getting started with Vagrant!</h1>
  </body>
</html>

Share an Environment

Vagrant Share 是一个插件,让你可以轻松共享本地环境到网络上。

Vagrant Share 依赖 ngrok ,现根据文档安装它。

# MaxOS 为例
brew install ngrok/ngrok/ngrok

安装 Share 插件

vagrant plugin install vagrant-share

共享环境,当前目录下执行

vagrant share

点击链接(按照提示,登录或注册 ngrok 的账号,配置 Authtoken ,即可访问。

你可能碰到 check_permissions 相关的报错,根据错误信息将 $HOME/.netrc 的权限改成 0600 即可。

拆除虚拟机环境

vagrant suspend 可以挂起虚拟机,下次 vagrant up 时可以恢复到挂起前的状态。

缺点是挂起虚拟机需要额外的磁盘空间用来保存内存中的数据。

vagrant halt 可以停止虚拟机,这是优雅停机。

vagrant destroy 销毁虚拟机,可以回收磁盘空间和 RAM。