生活不会因为某个节点而变得与众不同,未来的幸运,都是过往努力的积攒。
vagrant 是我在本地 osx 系统下做测试环境时候开始研究的,以前只是单一的用 vbox 装个本地虚机时并没有发觉用或者不用有什么差别,但随着本地开始有一些特殊需求的时候,才发觉 vagrant 提供的功能还是很值得称赞的。
provisioning
类似于开机启动,可以开机执行某个命令,可以执行某个脚本都可以
比如我想在开机后自动安装某个包,同步下时间,那么如果是 vbox 的虚机可能你得连到虚机里,然后在/etc/rc.local下写上命令等等,但在 Vagrantfile 里,可以直接以配置的形式体现,下面这段是配置里自带的一段,开机自动更新包,安装 Apache
- config.vm.provision "shell", inline: <<-SHELL
- apt-get update
- apt-get install -y apache2
- SHELL
所以只要把中间那部分换成自己的命令就好,但是如果命令太长,还有逻辑判断,***是开机执行个脚本,那在配置文件里应该这样写
- config.vm.provision :shell, path: "<scriptname.sh>"
注意这里的路径是以Vagrantfile所在的目录为根目录的,上述的写法,脚本就必须存放在和 Vagrantfile同级就可以
vagrant 创建集群
如果是 vbox 或者是 VMware 的话,模拟一个集群方法就是多建几个虚机环境,然后打通内网,无论是 clone 还是新建都还挺麻烦的,但是 vagrant 靠一个配置文件就可以完成,这里直接引用 go-best-practice 里的这段话
Vagrant支持单机模拟多台机器,而且支持一个配置文件Vagrntfile就可以跑分布式系统。这种多机器模式特别适合以下几种人:
快速建立产品网络的多机器环境,例如web服务器、db服务器
建立一个分布式系统,学习他们是如何交互的
测试API和其他组件的通信
容灾模拟,网络断网、机器死机、连接超时等情况
现在我们来建立多台VM跑起來,並且让他们之间能够相通信,假设一台是应用服务器、一台是DB服务器,那么这个结构在Vagrant中非常简单,其实和单台的配置差不多,你只需要通过config.vm.define来定义不同的角色就可以了,现在我们打开配置文件进行如下设置:
- Vagrant.configure("2") do |config|
- config.vm.define :web do |web|
- web.vm.provider "virtualbox" do |v|
- v.customize ["modifyvm", :id, "--name", "web", "--memory", "512"]
- end
- web.vm.box = "base"
- web.vm.hostname = "web"
- web.vm.network :private_network, ip: "11.11.1.1"
- end
- config.vm.define :db do |db|
- db.vm.provider "virtualbox" do |v|
- v.customize ["modifyvm", :id, "--name", "db", "--memory", "512"]
- end
- db.vm.box = "base"
- db.vm.hostname = "db"
- db.vm.network :private_network, ip: "11.11.1.2"
- end
- end
这里的设置和前面我们单机设置配置类似,只是我们使用了:web以及:db分別做了两个VM的设置,并且给每个VM设置了不同的hostname和IP,设置好之后再使用vagrant up将虚拟机跑起来:
再次启动并连接,连接并需要指定角色即可
- $ vagrant up
- $ vagrant ssh web
- vagrant@web:~$
- $ vagrant ssh db
- vagrant@db:~$
批量生成机器
上面的情况适合于想建立个小集群,用于特定的环境,而现在有个需求想一次性生成10台机器,用上面的方法就略显复杂了,得写一大串配置文件,显得臃肿,不过 vagrant 也提供了特定的方式
以下这个配置来源于 https://jacobustczhi.gitbooks.io/-vagrant/content/chapter.html
- 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://atlas.hashicorp.com/search.
- (0..10).each do |i|
- config.vm.define "node#{i}" do |node|
- # 设置虚拟机的Box
- node.vm.box = "ubuntu/trusty64"
- # 设置虚拟机的主机名
- node.vm.hostname="node#{i}"
- # 设置虚拟机的IP
- node.vm.network "public_network", bridge: "eno1", ip: "192.168.17.20#{i}"
- # VirtaulBox相关配置
- node.vm.provider "virtualbox" do |v|
- v.name = "node#{i}"
- v.memory = 1024
- v.cpus = 1
- end
- end
- if ARGV[0] == "up" && ! File.exist?("./disk1.vdi")
- # 运行脚本增加swap空间
- config.vm.provision "shell", path: "increase_swap.sh"
- end
- end
- end
可以看到,与创建单个虚拟机相比,这里多了层循环,而变量 i 可以用于设置节点的名称与IP,使用#{i}取值:
- (0..10).each do |i|
- end
plugin
根据网友KiwenLau的文章里提到了一个错误
VirtualBox 设置共享目录时需要在虚拟机中安装VirtualBox Guest Additions,这个 Vagrant会自动安装。但是,VirtualBox Guest Additions是内核模块,当虚拟机的内核升级之后,VirtualBox Guest Additions会失效,导致共享目录挂载失败,出错信息如下:
- 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 the guest and
- can work properly. The command attempted was:
- mount -t vboxsf -o uid=id -u vagrant,gid=getent group vagrant | cut -d: -f3 vagrant /vagrant
- mount -t vboxsf -o uid=id -u vagrant,gid=id -g vagrant vagrant /vagrant
- The error output from the last command was:
- stdin: is not a tty
- /sbin/mount.vboxsf: mounting failed with the error: No such device
安装 Vagrant 插件vagrant-vbguest可以解决这个问题,因为该插件会在虚拟机内核升级之后重新安装VirtualBox Guest Additions。
- $ vagrant plugin install vagrant-vbguest