ALittleGuy

ALittleGuy

Vagrant虚拟机管理工具使用

1063
2021-10-14

简介

Vagrant是一款简单高效的虚拟机管理工具,可以配合VirtaulBox、VMware等虚拟机软件使用,用命令行操作虚拟机,帮助你快速的搭建和管理虚拟机环境,总体感觉有点类似于使用Docker管理Docker容器的感觉。

使用Vagrant可以快速的搭建虚拟机或者起一套集群,而且可以通过Vagrantfile和相应的脚本将设计好的虚拟机进行移植,如果你经常需要学习搭建k8s、hadoop之类的分布式系统,Vagrant会是一个很好的工具。

依赖

这里使用VirtualBox作为虚拟机软件,首先安装好VirtualBox和Vagrant

镜像准备

和Docker很类似,需要先准备相关的镜像,这里以Ubuntu18作示例

这里调用清华的源去下载一个Ubuntu18的Box

vagrant box add https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/bionic/current/bionic-server-cloudimg-amd64-vagrant.box --name ubuntu18

查看下载的结果

vagrant box list

01

创建虚拟机

首先尝试创建并且运行一个简单的Ubuntu虚拟机

vagrant init ubuntu18
ls
vagrant up

然后通过ssh进入,可以看到一个Ubuntu的虚拟机很快就创建好了

vagrant ssh

03

Vagrantfile

Vagrantfile是整个虚拟机定义的关键,这个文件使用ruby的语法对虚拟机作了一些常用的定义,首先看一下文件的结构,默认的文件内容很简单:

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu18"
end

来看一些常见的定义:

# -*- mode: ruby -*-
# vi: set ft=ruby:

#这里的“2”,指的是使用Vagrantfile使用的版本,默认不需要改动
Vagrant.configure("2") do |config|
  #指定使用的镜像
  config.vm.box = "ubuntu18"

  #指定使用public_network,通过bridge参数指定网卡,网络具体内容在后面
  config.vm.network "public_network" , bridge: "wlan0"

  #指定虚拟机开机的时候执行的脚本,可以使用当前路径指定,也可以使用绝对路径
  config.vm.provision "shell" , path: "startup.sh" 

  #指定虚拟机的mac地址,k8s集群可能会用到mac地址的信息。如果不特别指定,使用vagrant创建的集群mac地址会相同
  config.vm.base_mac = "080027000000"
  
  #指定共享的文件目录,默认当前目录已经映射到了虚拟机”/vagrant“中,你也可以专门指定
  config.vm.synced_folder "./" , "/share_folder"  , craete: true

  #指定虚拟机的内存、CPU等等
  config.vm.provider "virtualbox" do |vb| 
    vb.memory = "512"
    vb.cpus = "1"
    vb.gui = false
  end
end

然后再启动

touch startup.sh
vagrant up
vagrant ssh

Vagrant网络

vagrant中提供三种网络模型,通过在Vagrantfile指定相应的网络模型

一般Vagrant会为虚拟机默认创建一张nat网卡用于连接Internet以及vagrant ssh的连接,宿主机对应的网卡为vmnet8,虚拟机对应的网卡为enp0s3

05

06

端口转发

只需要简单的指定虚拟机到宿主机的端口映射即可实现端口的转发

# -*- mode: ruby -*-
# vi: set ft=ruby:
Vagrant.configure("2") do |config|
  #指定使用的镜像
  config.vm.box = "ubuntu18"

  #指定使用forwarded_port网络,即端口转发,将虚拟机的80端口转发到宿主机的8080端口
  config.vm.network "forwarded_port" , guest: 80 , host:8080
end

这里用一个简单nginx做一下测试

vagrant reload
vagrant ssh

# 进入虚拟机
sudo apt-get install nginx
sudo systemctl start nginx.service
exit

# 离开虚拟机
curl localhost:8080

04

私有网络

私有网络的建立对应virtualbox的Host-Only模式,私有网络中宿主机对应的网卡一般以vboxnet开头

09

  • 一种是不指定网络的ip,指定使用dhcp自动分配,宿主机自动创建一张网卡,并为虚拟机分配ip
  • 一种是指定了网络的ip,宿主机根据你的ip自动创建一张网卡,同时给虚拟机分配指定的ip,需要保证指定ip的有效性。如果需要搭建集群要保证个个虚拟机在同一网段下。以及不要使用**.1**结尾的ip,这个ip通常作为网关。
# -*- mode: ruby -*-
# vi: set ft=ruby:
Vagrant.configure("2") do |config|
  #指定使用的镜像
  config.vm.box = "ubuntu18"

  #指定使用private_network网络,即私有网络
  #可以自行指定网络ip(需要保证ip有效),如果不指定,可以指定DHCP分配一个ip
  config.vm.network "private_network" , ip: "192.168.100.10"
  # config.vm.network "private_network" , type: "dhcp"

end

同样部署一个nginx服务

vagrant reload
vagrant ssh

# 进入虚拟机
sudo apt-get install nginx
sudo systemctl start nginx.service
exit

# 离开虚拟机
curl 192.168.100.10

公有网络

公有网络的建立对应的是virtualbox中的Bridge模式,局域网为虚拟机分配一个ip,局域网内的其他机器也可以访问到

# -*- mode: ruby -*-
# vi: set ft=ruby:
Vagrant.configure("2") do |config|
  #指定使用的镜像
  config.vm.box = "ubuntu18"

  #指定使用public_network网络,即公有网络,这里采用的是Bridge网络,即桥接模式,需要指定宿主机有效的网卡
  #公有网络默认就是DHCP分配ip
  config.vm.network "public_network" ,bridge: "wlan0"
  #config.vm.network "public_network" ,bridge: "wlan0", ip: "10.252.75.192"

end

可以看到物理机和虚拟机在同一网段下

宿主机:

08

虚拟机:

07

同样部署一个nginx服务

vagrant reload
vagrant ssh

# 进入虚拟机
sudo apt-get install nginx
sudo systemctl start nginx.service
exit

# 离开虚拟机
curl 10.252.75.192 

多台主机建立

通过ruby的语法同时指定多台或者单台虚拟机来部署集群

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  # 设定虚拟机的内存和CPU
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "512"
  end

  #(1..3)指定虚拟机的数量
  (1..3).each do |i| 
    config.vm.define "node#{i}" do |node|
      node.vm.hostname = "node#{i}"
      node.vm.network "private_network" , ip: "192.168.100.10#{i}"
      node.vm.synced_folder "app#{i}" , "/vagrant"  
      node.vm.box = "ubuntu18"
      node.vm.provision "shell" , path: "bootstrap-node.sh"
      node.vm.provision "shell" , path: "bootstrap-common.sh"
      node.vm.base_mac = "08002700000#{i}"
    end
  end

  # 单独指定一台虚拟机
  config.vm.define "master" do |master|
    master.vm.hostname = "master"
    master.vm.box = "ubuntu18"
    master.vm.network "private_network" , ip: "192.168.100.200"
    master.vm.synced_folder "master" , "/vagrant" 
    master.vm.provision "shell" , path: "bootstrap-master.sh"
    master.vm.provision "shell" , path: "bootstrap-common.sh"
    master.vm.base_mac = "080027000000"
  end
end

注意在创建虚拟机之前需要创建用到的脚本和目录

vagrant init 
vim Vagrantfile   
mkdir app1 app2 app3 master 
touch bootstrap-common.sh bootstrap-node.sh bootstrap-master.sh
vagrant up

搭建简单的nginx集群

这里的搭建就先不考虑高可用的情况,用虚拟ip和nginx的默认的负载均衡搭建一个简单的集群

对应的Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  # 设定虚拟机的内存和CPU
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "512"
  end

  #(1..3)指定虚拟机的数量
  (1..3).each do |i| 
    config.vm.define "node#{i}" do |node|
      node.vm.hostname = "node#{i}"
      node.vm.network "private_network" , ip: "192.168.100.10#{i}"
      node.vm.synced_folder "app#{i}" , "/vagrant"  
      node.vm.synced_folder "common" , "/common"  
      node.vm.box = "ubuntu18"
      node.vm.provision "shell" , path: "bootstrap-node.sh"
      node.vm.provision "shell" , path: "bootstrap-common.sh"
      node.vm.base_mac = "08002700000#{i}"
    end
  end

  # 单独指定一台虚拟机
  config.vm.define "master" do |master|
    master.vm.hostname = "master"
    master.vm.box = "ubuntu18"
    master.vm.network "private_network" , ip: "192.168.100.200"
    master.vm.synced_folder "master" , "/vagrant" 
    master.vm.synced_folder "common" , "/common" 
    master.vm.provision "shell" , path: "bootstrap-master.sh"
    master.vm.provision "shell" , path: "bootstrap-common.sh"
    master.vm.base_mac = "080027000000"
  end
end

建立对应的脚本和文件

mkdir app1 app2 app3 master common
touch bootstrap-common.sh bootstrap-node.sh bootstrap-master.sh

配置nginx安装的脚本,同时准备一份简单的nginx.conf文件直接输入进去

bootstrap-common.sh

apt-get install -y nginx
echo 'user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
        worker_connections 768;
}
http {
    myapp1 {
        192.168.100.101;
        192.168.100.102;
        192.168.100.103;
        192.168.100.200;
    }

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        gzip on;
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}
' > /etc/nginx/nginx.conf
systemctl start nginx

配置虚拟网卡,通过一个虚拟ip来访问

bootstrap-master.sh

ifconfig enp0s8:1 192.168.100.201 broadcast 192.168.100.255 netmask 255.255.255.0 up
route add -host 192.168.100.201 dev enp0s8:1

启动集群

vagrant up
curl 192.168.100.201 

常用命令操作

操作效果
vagrant up [box]根据Vagrantfile建立虚拟机,可选参数指定建立的虚拟机,默认全部建立
vagrant status [box]查看虚拟机状态,可选参数指定查看的虚拟机,默认全部查看
vagrant status [box]
vagrant init [box]在当前目录建立Vagrantfile,可选参数指定镜像名称
vagrant halt [box]关闭虚拟机,可选参数关闭建立的虚拟机,默认全部关闭,开机需要使用vagrant up
vagrant reload [box]重启虚拟机,并根据新的Vagrantfile重载虚拟机,可选参数指定重载的虚拟机,默认全部重载
vagrant box add [link]根据link链接下载对应的box,https://app.vagrantup.com/boxes/search,可以在这个链接里搜索对应的box
vagrant destroy [box]删除虚拟机,可选参数指定删除的虚拟机,默认全部删除

参考文档

https://tangbaoping.github.io/vagrant_doc_zh/v2/
https://www.vagrantup.com/docs
https://mlog.club/article/1286811