Saturday, August 12, 2017

Vagrant Tutorial


Install Vagrant

1.      Setup proxies on your operation system, so that you can download Vagrant boxes

In my case, my operation system is Win7.

1.1   Check if proxies are already installed 
env | grep –i proxy

1.2   Setup system environments
http_proxy = YOUR_PROXY
https_proxy =YOUR_PROXY


2.      Download and install vagrant 


To upgrade Vagrant, install the newer on the same location, Vagrant will override the existing version. You may need to reinstall all plugins one by one manually (vagrant plugin repair doesn’t help)

3.      Install vagrant plugins:

vagrant plugin install vagrant-proxyconf
vagrant plugin install vagrant-timezone
vagrant plugin list

4.      Install Virtualbox

http://download.virtualbox.org/virtualbox/5.1.22/VirtualBox-5.1.22-115126-Win.exe

vagrant up – a simple Vagrant file

1.      Search boxes: https://atlas.hashicorp.com/boxes/search

Create and edit file Vagrantfile under c:/devops/exp:

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

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = "ubuntu/xenial64"
  config.vm.hostname="exp" 
  


  if Vagrant.has_plugin?("vagrant-proxyconf")
         config.proxy.http         = "YOUR_PROXY"
         config.proxy.https        = "YOUR_PROXY"
         config.proxy.ftp          = "YOUR_PROXY"
         config.proxy.no_proxy  = "localhost,192.168.33.10,127.0.0.1"
  end  
   
  if Vagrant.has_plugin?("vagrant-timezone")
        config.timezone.value="Asia/Shanghai"
  end
 
  config.vm.provider "virtualbox" do |v|
                 v.memory =4096
                 v.cpus = "4"
   end 
   
   config.vm.network "private_network", ip: "192.168.33.10"

   config.vm.synced_folder "../", "/devops", mount_options: ["dmode=777,fmode=777"]      

end

  Run vagrant up will download box ubuntu/xenial64 and create a VM based on the box and configure the VM based on the configuration in the Vagrantfile.

  Run vagrant ssh to logon to the VM.

2.      If download VM through vagrant up  fails, you can manually download the box and add it:

2.1) Manually download ubuntu/xenial64:


2.2) add the downloaded box
$ vagrant box add ubuntu/xenial64 C:/Users/admin/Downloads/xenial-server-cloudimg-amd64-vagrant.box
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'ubuntu/xenial64' (v0) for provider:
    box: Unpacking necessary files from: file:///C:/Users/admin/Downloads/xenial-server-cloudimg-amd64-vagrant.box
    box:
==> box: Successfully added box 'ubuntu/xenial64' (v0) for 'virtualbox'!

2.3) change the version of the added box
The box added above doesn’t have the correct version, you need to manually correct it:

$ vagrant box list
ubuntu/xenial64 (virtualbox, 0)

Vagrant stores boxes in:
C:\Users\admin\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-xenial64




Change C:\Users\admin\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-xenial64\0 To C:\Users\admin\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-xenial64\ 20170523.1.0


Now version is correct:
$ vagrant box list
ubuntu/xenial64 (virtualbox, 20170523.1.0)

Also need to add a file metadata_url under C:\Users\admin\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-xenial64 with content:

Otherwise, vagrant up will run into errors:

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
The box 'ubuntu/xenial64' is not a versioned box. The box was added
directly instead of from a box catalog. Vagrant can only
check the versions of boxes that were added from a catalog
such as from the public Vagrant Server.

vagrant up – provisioning


Add this line into Vagrantfile:
   config.vm.provision :shell, path: "bootstrap-jdk.sh"

bootstrap-jdk.sh is to install java8 and setup JAVA_HOME (note, no need to use sudo):
#!/usr/bin/env bash

v=`java -version 2>&1`

if [[ $v != *'openjdk version "1.8'* ]]; then 
        apt-get update
        apt-get install -y openjdk-8-jre
        echo JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 >> /etc/environment
        source /etc/environment
else
        echo "JDK8 is already installed"
        echo "$v"
fi

Run vagrant up --provision, which will run provisioning scripts.

vagrant up multiple VMs


The solution is to define VMs in a file boxes.yml, and have Vagrantfile parse boxes.yml and set VMs up. 

boxes.yml:
boxes:
  os:
    ubuntu: xenial64
    ubuntu_version: xenial64      
    proxy: YOUR_PORXY
 
  ctrl:
    name: ctrl
    ip: '192.168.33.2'
    memory: '2048'    
    size: 1
  elks:
    name: elk
    ip: '192.168.33.5'
    memory: '1024'    
    size: 2

  ports:
    ctrl:    
      - { guest: 80, host: 7500 }
      - { guest: 27017, host: 27017 }    
      - { guest: 3000, host: 6500 }      
    elk1:
      - { guest: 5601, host: 5601 }
    elk2:
      - { guest: 5602, host: 5602 }

boxes.yml defines two sets of VMs: ctrl and elk. ctl set will have 1 VMs, elk set will have 2 VMs with names elk1 and elk2. ctrl’s ip is '192.168.33.2', elk1’s ip is '192.168.33.51' and elk2’s ip is '192.168.33.52'. Port forwarding is configured in the port block. 

Vagrantfile loads boxes.yml, parses it and sets up VMs according to the configuration in boxes.yml:

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

require 'yaml'
current_dir    = File.dirname(File.expand_path(__FILE__))
box_file="#{current_dir}/boxes.yml"
configs        = YAML.load_file(box_file)
boxes = configs['boxes']
noproxy="localhost,127.0.0.1,"
       
noproxy="#{noproxy}#{boxes['ctrl']['ip']},"

(1..boxes['elks']['size']).each do |i|
       
        noproxy="#{noproxy}#{boxes['elks']['ip']}#{i}"
       
        if i<boxes['elks']['size']           
               noproxy="#{noproxy},"
        end            
end

puts "no proxy is:"
puts noproxy

Vagrant.configure(2) do |config|
  
  if Vagrant.has_plugin?("vagrant-proxyconf")
               config.proxy.http         = "#{boxes['os']['proxy']}"
               config.proxy.https        = "#{boxes['os']['proxy']}"
               config.proxy.ftp          = "#{boxes['os']['proxy']}"
               #ip address wildcard such as 192.168.33.* doesn't work, must specify the exact ip address
               config.proxy.no_proxy  = "#{noproxy}"
  end
  
  if Vagrant.has_plugin?("vagrant-timezone")
                config.timezone.value="Asia/Shanghai"
  end
 
  config.vm.box = "ubuntu/#{boxes['os']['ubuntu']}"
 
  config.vm.define boxes['ctrl']['name'] do |d|            
               d.vm.hostname = boxes['ctrl']['name']
               d.vm.network "private_network", ip: boxes['ctrl']['ip']            
                             
               d.vm.provider "virtualbox" do |v|
                 v.memory = boxes['ctrl']['memory']
               end
              
               if boxes['ports'].key? 'ctrl'
                       vmports=boxes['ports']['ctrl']                      
                       vmports.each { |portmap|
                              d.vm.network "forwarded_port", guest: portmap['guest'], host: portmap['host']                       
                       }
               end           
              
  end
 
   (1..boxes['elks']['size']).each do |i|
               config.vm.define "#{boxes['elks']['name']}#{i}"      do |d|               
                         d.vm.hostname = "#{boxes['elks']['name']}#{i}"    
                         d.vm.network "private_network", ip: "#{boxes['elks']['ip']}#{i}"       
                        
                         d.vm.provider "virtualbox" do |v|
                              v.memory =  boxes['elks']['memory']
                         end
                        
                         if boxes['ports'].key? "#{boxes['elks']['name']}#{i}"
                              vmports=boxes['ports']["#{boxes['elks']['name']}#{i}"]                             
                              vmports.each { |portmap|
                                      d.vm.network "forwarded_port", guest: portmap['guest'], host: portmap['host']                            
                              }
                        end
               end
    end
end

No comments:

Post a Comment