http://www.cyberciti.biz/cloud-computing/use-vagrant-to-create-small-virtual-lab-on-linux-osx
Vagrant is a multi-platform command line tool for creating lightweight, reproducible and portable virtual environments. Vagrant acts as a glue layer between different virtualization solutions (Software, hardware PaaS and IaaS) and different configuration management utilities (Puppet, Chef, etc'). Vagrant was started back at 2010 by Mitchell Hashimoto as a side project and later became one of the first products of HashiCorp - the company Mitchell founded.
While officially described as a tool for setting up development environments, Vagrant can be used for a lot of other purposes by non developers as well:
Since Vagrant is not a virtualization software by itself, it relies on 3rd party providers for doing the virtualization part. For this tutorial I'll assume you have installed Oracle's VirtualBox. VirtualBox is a free multi-platform virtualization software which is supported by Vagrant out of the box.
Configuration Management (CM) vs shell scripts: There's nothing wrong to use Vagrant with simple shell script instead of a full blown CM system. In fact in this tutorial I will use shell as well in order to not over complicate the tutorial. However CM system like Puppet or Chef has certain principles behind them which can help you with provisioning of your environment. For example one of the main principles of CMs is Idempotence which is the ability to apply certain action number of times but be sure the result won't change after the initial result. In environment you find provisioning to be helpful even after the initial provision, you should probably consider using CM instead of shell script.
One options is to provide your students virtual machine disk images that they can import and run. This options has its advantages:
Sample outputs:
Vagrant commands are executed on all machines in the environment. For example in our case, running vagrant up will cause vagrant to start and provision two virtual machines (server & client). If we wanted to create only one of them, we could do vagrant up server and only the server virtual machine would be initialized by vagrant.
If you browse around the menus you should see that currently Nagios is only configured to monitor itself. In the next part we'll add the configurations needed so Nagios will start monitoring the client machine as well.
It's the
and NRPE agent.
First we'll add the following configuration directive in server/nagios.cfg:
Now let's do one more thing and configure the client host to provide additional information to Nagios by using the NRPE monitoring daemon. First in client/nrpe.cfg we need to change line number 81 to:
In case your Vagrantfile use plugins, you want to make sure all your users have the that plugin installed. You can add small ruby test to your Vagrant file that looks something like that:
Vagrant doesn't support running Vagrantfile with multiple number of providers at the same time. However you can run same Vagrantfile with different providers separately (using the --provider flag). However, supporting multiple providers in same Vagrantfile can be tricky as well since some options and features are not the same between providers. So for best compatibility you might want to decide to work with specific provider only. In our tutorial we assume that VirtualBox is used since we use the VBoxManage command line utility to find the IP address of our virtual machines. Running it under VMWare will cause hostmanager to act differently.
Another point you want to be extra careful with is running Vagrant on different OS. In our tutorial for example, the path of VBoxManage.exe needs to exists in the PATH variable or else hostmanager will fail.
Vagrant is a multi-platform command line tool for creating lightweight, reproducible and portable virtual environments. Vagrant acts as a glue layer between different virtualization solutions (Software, hardware PaaS and IaaS) and different configuration management utilities (Puppet, Chef, etc'). Vagrant was started back at 2010 by Mitchell Hashimoto as a side project and later became one of the first products of HashiCorp - the company Mitchell founded.
While officially described as a tool for setting up development environments, Vagrant can be used for a lot of other purposes by non developers as well:
- Creating demo labs
- Testing configuration management tools
- Speeding up the work with non multi-platform tools such as Docker
Vagrant installation
Vagrant installation packages are available for OS X, Windows and Linux (deb and rpm format). Installation is simple "Next, Next, Next, Done" process and doesn't require any special user interaction.A note for Linux users
I strongly suggest that you will install Vagrant from its website and not by using your package manager. A lot of times the official repositories contains very old versions of Vagrant. In this tutorial I will use Vagrant 1.6.5.Since Vagrant is not a virtualization software by itself, it relies on 3rd party providers for doing the virtualization part. For this tutorial I'll assume you have installed Oracle's VirtualBox. VirtualBox is a free multi-platform virtualization software which is supported by Vagrant out of the box.
Vagrant environment variables
By default Vagrant comes with sane default values and you don't need to change any to make it work. However, I will point out number of important ones you should be familiar with:- VAGRANT_DOTFILE_PATH> - This is the directory where Vagrant stores VM-specific state. By default it's '.vagrant' in the same directory as your
Vagrantfile. - VAGRANT_HOME - This is the directory where Vagrant stores its global state. It can get quiet large since it will contain all the base boxes.
By default this is '~/.vagrant.d' - VAGRANT_LOG
- Verbosity level of Vagrant log messages. By default is 'info', change
this to 'debug' in case you really want to know what's going
on or want to submit bug report with log for example. - VAGRANT_DEFAULT_PROVIDER - By default Vagrant is using Virtualbox as its virtualization provider unless requested otherwise. If you using other
provider most of the time, it would make sense to change the default.
Understanding Vagrant terminology
A quick terminology break down:Providers
Providers are the components that enables Vagrant to use different virtualization solutions. Vagrant supports number of software hypervisors out of the box - VirtualBox and Hyper-V. Vagrant also allows adding additional providers via its plugins mechanism. For example you can add support for VMWare products as well as IaaS providers such as AWS.Provisioners
Provisioners allow Vagrant to bring machine into desired state by using simple shell scripts or different configuration management tools such as Puppet or Chef. Provisioning in Vagrant usually happens after machine initialization but can be initiated on demand.Configuration Management (CM) vs shell scripts: There's nothing wrong to use Vagrant with simple shell script instead of a full blown CM system. In fact in this tutorial I will use shell as well in order to not over complicate the tutorial. However CM system like Puppet or Chef has certain principles behind them which can help you with provisioning of your environment. For example one of the main principles of CMs is Idempotence which is the ability to apply certain action number of times but be sure the result won't change after the initial result. In environment you find provisioning to be helpful even after the initial provision, you should probably consider using CM instead of shell script.
Vagrant boxes
Boxes are vagrant packages that allows bundling provider specific machine data (such as vmdk disk images). These packages can be imported on any machine that runs vagrant.Shared/Synced folders
Vagrant allows sharing or syncing of folders from host machine to guest machine. This allows you to edit your files locally and see the changes in the guest machine. Sharing of folders depends on your provider, for example VirtualBox provides its shared folder mechanism. Vagrant also allows syncing by using tools such as rsync or network file share using NFS.Port forwarding
Some providers such as VirtualBox allow running VMs in NAT network mode. In this mode the VM sits in its own private address space which is not accessible from the host machine. In this case port forwarding allows creating forwarding rules that will forward traffic from local port to the port of the virtual machine.Vagrant plugins
Vagrant provides extendability via its plugins API. This creates possibilities to add support for new provisioners, providers and other utilities. For a list of currently available Vagrant plugins take a look here.Creating your first Vagrantfile
Vagrant initial goal was to speed up the creation of virtual environments for development. However, virtual environments has a broader use case. One of the common uses of Virtualization is to set up practice labs, and I will demonstrate how we can do it by using Vagrant.Our (not so) imaginary scenario
Your company using Nagios as its monitoring solution and your team is responsible for maintaining it. You have new personal on your team which isn't familiar with Nagios and you'll like to do few training sessions for them. For the training session you want each member to have its own sandbox environment to play with.One options is to provide your students virtual machine disk images that they can import and run. This options has its advantages:
- Almost no time to first boot.
- Relatively easy process (if you are familiar with Virtualization).
- Access to the internet is not needed (the image can be saved on USB, local file server, etc).
- Users usually not aware how the environment inside the virtual machine was created.
- Can be time consuming to update image with new components.
- Might need to provide additional instructions to users about how to set up the virtual environment (Assign more CPUs and RAM, network settings, etc).
Note: I'm not suggesting in any way that using Vagrant doesn't come with its own set of disadvantages.
The Vagrant configuration
Before we start you should download the tarball with configurations files from here. Bellow is the main config file (Vagrantfile). If you don't have any programing/scripting experience it may seem a bit confusing at first:VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "ubuntu/trusty64" config.vm.provider "virtualbox" do |vb| vb.cpus = 2 end config.vm.network "private_network", type: "dhcp" config.hostmanager.enabled = true config.hostmanager.ip_resolver = proc do |vm, resolving_vm| if vm.id `VBoxManage guestproperty get #{vm.id} "/VirtualBox/GuestInfo/Net/1/V4/IP"`.split()[1] end end config.vm.define :server do |srv| srv.vm.hostname = "nagios-server" srv.vm.synced_folder "server/", "/usr/local/nagios/etc", create: true srv.vm.network "forwarded_port", guest: 80, host: 8080 srv.vm.provision "shell", path: "server-provision" end config.vm.define :client do |cl| cl.vm.hostname = "nagios-client" cl.vm.synced_folder "client/", "/usr/local/nagios/etc", create: true cl.vm.provision "shell", path: "client-provision" end endVagrantfile is really a ruby file (or more specifically a Ruby DSL). While this makes the configuration look a bit weird for the average joe, it's nothing to be worried about and can be pretty powerful feature when needed.
Let's break this block by block:
VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| #this is the outer block endThe outer block creates the main configuration object. Think of it as creation of an object (named 'config') that will hold all our settings. VAGRANTFILE_API_VERSION is a variable storing the value "2". This represent the version number we want out config object to work with. This is mainly done for backwards compatibility between recent versions of Vagrant and older ones. If you are not sure about it, just leave it as is.
config.vm.box = "ubuntu/trusty64"Here we use the config object to set our Vagrant base box to ubuntu/trusty64. More about where this box comes from later in the tutorial.
config.vm.provider "virtualbox" do |vb| vb.cpus = 2 endHere we create provider specific config block. In our case we ask that if machines are being run with VirtualBox provider, then each machine should receive 2 vCPUs by default. Each provider expose different set of options, so provider specific settings needs to be in separate blocks.
config.vm.network "private_network", type: "dhcp"Network config is something that gets special treatment in Vagrant. While it is possible to configure Network via the provider block configuration, Vagrant tries to abstract as much as possible of the (usually) tedious network configuration into few high level settings. In our case, we ask Vagrant to configure private_network networking and assign IP addresses via DHCP. private_network means that each machine will get private ip address from the private address space and machines will be able to communicate with one to another via these addresses. I choose to use DHCP instead of static IPs because I would like my Vagrantfile to be bit more portable. Choosing static IPs could mean collisions with local networks at home or work.
config.hostmanager.enabled = true config.hostmanager.ip_resolver = proc do |vm, resolving_vm| if vm.id `VBoxManage guestproperty get #{vm.id} "/VirtualBox/GuestInfo/Net/1/V4/IP"`.split()[1] end endHostmanager config namespace is not a part of core Vagrant install. It is added by using the Hostmanager Vagrat plugin. This plugin allows a dynamic edit of host file on host and guest machines. It allows us to skip hardcoding IPs into our configuration and to work with hostnames instead of IPs. So later on when actually working with Nagios I can refer to server as nagios-server instead of its IP.
Note for Windows users: In Windows, VBoxManage.exe is not in the %PATH%. You'll want to add VirtualBox's directory (usually something like C:\Program Files\Oracle\VirtualBox) into the PATH variable for this to work.
config.vm.define :server do |srv| srv.vm.hostname = "nagios-server" srv.vm.synced_folder "server/", "/usr/local/nagios/etc", create: true srv.vm.network "forwarded_port", guest: 80, host: 8080 srv.vm.provision "shell", path: "server-provision" end config.vm.define :client do |cl| cl.vm.hostname = "nagios-client" cl.vm.synced_folder "client/", "/usr/local/nagios/etc", create: true cl.vm.provision "shell", path: "client-provision" endThese are two blocks doing the same thing - defining a virtual machine. First line of each block defines machine hostname. Second line of each block defines a synced folder between host and guest machine. These are the folder of Nagios configurations which will allow us to quickly reconfigure Nagios server and Nagios client without the need to SSH into the machine. Third line of the first block defines a port forwarding. This is done mainly for example only since we use private_network and can access machine by IP instead. Last line of each block describes what provisioner we want to use. In our case we would use the simple shell provisioner. Vagrant will copy the files specified in path and execute them after machine is up and running. The server-provision & client-provision files exists inside the tarball. I will not review them in this tutorial.
Run Vagrant
In this section we will initialize our Vagrant environment.Vagrant CLI crash course
Vagrant CLI is quiet straightforward. To see the list of all the common commands type the following in your terminal:vagrant --help
Sample outputs:
Usage: vagrant [options] []
-v, --version Print the version and exit.
-h, --help Print this help.
Common commands:
box manages boxes: installation, removal, etc.
connect connect to a remotely shared Vagrant environment
destroy stops and deletes all traces of the vagrant machine
global-status outputs status Vagrant environments for this user
halt stops the vagrant machine
help shows the help for a subcommand
init initializes a new Vagrant environment by creating a Vagrantfile
login log in to Vagrant Cloud
package packages a running vagrant environment into a box
plugin manages plugins: install, uninstall, update, etc.
provision provisions the vagrant machine
rdp connects to machine via RDP
reload restarts vagrant machine, loads new Vagrantfile configuration
resume resume a suspended vagrant machine
share share your Vagrant environment with anyone in the world
ssh connects to machine via SSH
ssh-config outputs OpenSSH valid configuration to connect to the machine
status outputs status of the vagrant machine
suspend suspends the machine
up starts and provisions the vagrant environment
version prints current and latest Vagrant version
For help on any individual command run `vagrant COMMAND -h`
Additional subcommands are available, but are either more advanced
or not commonly used. To see all subcommands, run the command
`vagrant list-commands`.
Primary commands you want to focus on at first:- init - Create Vagrantfile in current directory.
- up - If environment never been created before, create it and run provision on machines. If machines are stopped (halt), just start them without provision
- halt - Shutdown environment. Equivalent to powering off machines.
- provision - (re)Run provision scripts as defined in Vagrantfile.
- destroy - Stop and delete environment.
- reload - Will restart environment and apply new setting from Vagrantfile without destroying.
- ssh - SSH into machine.
- status - Get environment status to see whether machines are running or not.
Vagrant commands are executed on all machines in the environment. For example in our case, running vagrant up will cause vagrant to start and provision two virtual machines (server & client). If we wanted to create only one of them, we could do vagrant up server and only the server virtual machine would be initialized by vagrant.
Installing plugins
Before we can start our environment, lets install the hostmanager plugin:$ vagrant plugin install vagrant-hostmanager Installing the 'vagrant-hostmanager' plugin. This can take a few minutes... Installed the plugin 'vagrant-hostmanager (1.5.0)'!You can list all installed vagrant plugins with the following command:
$ vagrant plugin list
Vagrant up
Now we are ready to initialize our environment:$ vagrant up Bringing machine 'server' up with 'virtualbox' provider... Bringing machine 'client' up with 'virtualbox' provider... 1==> server: Box 'ubuntu/trusty64' could not be found. Attempting to find and install... server: Box Provider: virtualbox server: Box Version: >= 0 ==> server: Loading metadata for box 'ubuntu/trusty64' server: URL: https://vagrantcloud.com/ubuntu/trusty64 ==> server: Adding box 'ubuntu/trusty64' (v14.04) for provider: virtualbox 1 server: Downloading: https://vagrantcloud.com/ubuntu/trusty64/version/1/provider/virtualbox.box 1==> server: Successfully added box 'ubuntu/trusty64' (v14.04) for 'virtualbox'! 2==> server: Importing base box 'ubuntu/trusty64'... ==> server: Matching MAC address for NAT networking... ==> server: Checking if box 'ubuntu/trusty64' is up to date... 3==> server: Setting the name of the VM: nagioslab_server_1410009838995_55673 ==> server: Clearing any previously set forwarded ports... ==> server: Clearing any previously set network interfaces... ==> server: Preparing network interfaces based on configuration... server: Adapter 1: nat server: Adapter 2: hostonly 4==> server: Forwarding ports... server: 80 => 8080 (adapter 1) server: 22 => 2222 (adapter 1) ==> server: Running 'pre-boot' VM customizations... ==> server: Booting VM... ==> server: Waiting for machine to boot. This may take a few minutes... server: SSH address: 127.0.0.1:2222 server: SSH username: vagrant server: SSH auth method: private key server: Warning: Connection timeout. Retrying... server: Warning: Remote connection disconnect. Retrying... 5==> server: Machine booted and ready! ==> server: Checking for guest additions in VM... ==> server: Setting hostname... ==> server: Configuring and enabling network interfaces... 5==> server: Mounting shared folders... server: /vagrant => /Users/michael/VagrantLab/nagioslab server: /usr/local/nagios/etc => /Users/michael/VagrantLab/nagioslab/server 5==> server: Updating /etc/hosts file on active guest machines... 5==> server: Running provisioner: shell... server: Running: /var/folders/fz/81ddjj6s2bx9s7jg9z7347pr0000gn/T/vagrant-shell20140906-90949-1a8ntti ==> server: stdin: is not a tty ==> server: Ign http://archive.ubuntu.com trusty InRelease ... provisioning log ... ==> server: Starting nagios: ==> server: done. ==> client: Box 'ubuntu/trusty64' could not be found. Attempting to find and install... client: Box Provider: virtualbox client: Box Version: >= 0 ==> client: Loading metadata for box 'ubuntu/trusty64' client: URL: https://vagrantcloud.com/ubuntu/trusty64 6==> client: Adding box 'ubuntu/trusty64' (v14.04) for provider: virtualbox ==> client: Importing base box 'ubuntu/trusty64'... ... similar log to server part ==> client: Starting nagios remote plugin daemon: nrpe ==> client: .Some key points in log:
- 1 At first Vagrant looks for a base box (ubuntu/trusty64), once it doesn't find it, it will download it from vagrantcloud.com (unless configured otherwise).
- 2 After download is finished, it will import the image into Virtualbox.
- 3 Vagrant will rename the machine in Virtualbox to the name specified in the log. If you open Virtualbox, you'll find a running machine with this name.
- 4 Port forwarding takes place.
- 5 After machine is running and ready Vagrant will mount shared folders, edit hosts file (hostmanager plugin) and execute provision shell script that was copied to the machine.
- 6 Notice that the second machine won't re-download the box before importing it since it was saved to Vagrant's cache in the first time.
Checking for status
First of all, lets make sure our machines are really up usingvagrant status
command:$ vagrant status Current machine states: server running (virtualbox) client running (virtualbox) This environment represents multiple VMs. The VMs are all listed above with their current state. For more information about a specific VM, run `vagrant status NAME`.Now let's check nagios is really running on server:
$ vagrant ssh server -c "service nagios status" nagios (pid 4154) is running... Connection to 127.0.0.1 closed.Great. Server is up and Nagios is running. You can now open your web browser and point it to http://localhost:8080/nagios. User is nagiosadmin and password is nagios:
If you browse around the menus you should see that currently Nagios is only configured to monitor itself. In the next part we'll add the configurations needed so Nagios will start monitoring the client machine as well.
Working with Nagios
If you list your folder content after provisioning is finished, you should find two new directories which wasn't there before we ranvagrant up
.It's the
client
and server
folders created during initial provisioning and now contains the configurations of Nagios serverand NRPE agent.
First we'll add the following configuration directive in server/nagios.cfg:
cfg_file=/usr/local/nagios/etc/objects/client.cfgNext, we'll create server/object/client.cfg and put the following configuration inside:
define host{ use linux-server host_name client hostgroups linux-servers alias client address nagios-client }and now restart nagios daemon:
$ vagrant ssh server -c "sudo service nagios restart" Running configuration check... Stopping nagios: /etc/init.d/nagios: 147: kill: No such process done. Starting nagios: done. Connection to 127.0.0.1 closed.In your browser under "Host Groups" you should see new host with the name client and its status should change to UP after few seconds. We have instruct Nagios to watch add new configuration file and in that file we defined new host Nagios should monitor. The address of the new host is nagios-client and its being resolved to the correct address because of the hostmanager plugin which dynamically edits /etc/hosts file and added the correct IP addresses of nagios-client machine.
Now let's do one more thing and configure the client host to provide additional information to Nagios by using the NRPE monitoring daemon. First in client/nrpe.cfg we need to change line number 81 to:
allowed_hosts=127.0.0.1,nagios-serverThen restart nrpe daemon:
$ vagrant ssh client -c "sudo service nrpe restart" Restarting nagios remote plugin daemon: nrpe. Connection to 127.0.0.1 closed.Now lets go back to server/object/client.cfg and add the following lines:
define command{ command_name check_nrpe command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ } define service{ use generic-service host_name client service_description Logged users check_command check_nrpe!check_users } define service{ use generic-service host_name client service_description Load average check_command check_nrpe!check_load } define service{ use generic-service host_name client service_description Zombie procs check_command check_nrpe!check_zombie_procs }Now restart nagios daemon, and after few moments you should see our newly added service checks in
Rinse and repeat
So we created our small Nagios lab environment where we can experiment with different Nagios configurations, plugins and so on. The whole environment is defined in bunch of script files which you can store in your source repository such as Git. Your co-workers can now simply download these configuration files to their machine and runvagrant up
and in the end of the process get exactly the same environment as you have on your machine.Things to watch out for
Portability can be tricky thing and there are couple of thing you need to watch out for when you work with Vagrant. First of all, make sure you all work with same Vagrant versions. Vagrant fixes a lot of issues between releases (and obviously adds a bug or two as well) so you want to be on the same page when running Vagrant. You can include Vagrant.require_version helper config in your Vagrantfile to force only specific versions of Vagrant to run your config.In case your Vagrantfile use plugins, you want to make sure all your users have the that plugin installed. You can add small ruby test to your Vagrant file that looks something like that:
if !Vagrant.has_plugin?('plugin-name') puts "plugin is missing. Bye!" exit 1 endGenerally though, you want to minimize the number of 3rd party plugins to essential minimum.
Vagrant doesn't support running Vagrantfile with multiple number of providers at the same time. However you can run same Vagrantfile with different providers separately (using the --provider flag). However, supporting multiple providers in same Vagrantfile can be tricky as well since some options and features are not the same between providers. So for best compatibility you might want to decide to work with specific provider only. In our tutorial we assume that VirtualBox is used since we use the VBoxManage command line utility to find the IP address of our virtual machines. Running it under VMWare will cause hostmanager to act differently.
Another point you want to be extra careful with is running Vagrant on different OS. In our tutorial for example, the path of VBoxManage.exe needs to exists in the PATH variable or else hostmanager will fail.
No comments:
Post a Comment