I wanted to have a look at using Vagrant with vSphere to help provision a dev environment, mainly for an excuse to have a look at Vagrant. This post will cover the steps I used to get Vagrant up and running, and able to provision a VM on an ESXi host, via vCenter.
To start with, we need a place to run Vagrant. I decided on using a minimal Centos 7 build as my Vagrant host. After installing Centos, the Ruby package will need to be installed. To do so, I followed the tutorial here, covering how to get a recent version of Ruby installed. Once installed you can check the version:
[root@localhost ~]# ruby --version ruby 2.1.8p440 (2015-12-16 revision 53160) [x86_64-linux]
The version I have installed it 2.1.8. With that done we can move on to installing Vagrant. First we need to download the .rpm package, which can be found here. On my system, I used ‘wget’ to download the Centos Vagrant rpm file:
[root@localhost ~]# wget https://releases.hashicorp.com/vagrant/1.9.5/vagrant_1.9.5_x86_64.rpm?_ga=2.226527455.374667570.1497954439-963434566.1497954439
Then I used the rpm tool to install the package:
[root@localhost ~]# rpm --install vagrant_1.9.5_x86_64.rpm\?_ga\=2.226527455.374667570.1497954439-963434566.1497954439
Once done, confirm Vagrant is installed by running:
[root@localhost ~]# vagrant --version Vagrant 1.9.5
Next, the Vagrant vSphere plugin needs to be installed, to allow Vagrant to communicate with vSphere:
[root@localhost ~]# vagrant plugin install vagrant-vsphere
At this point we can move onto creating a virtual machine template in vCenter, before going back to configuring Vagrant to use it later on. For this article I decided to use a Photon OS virtual machine, as it’s a minimal install, and comes packaged with VMtools. The Photon OS .OVA can be downloaded here. You can read the Photon OS Administration Guide here, which covers a number of things, including how to configure networking. We also need to install the sudo package, as we’ll need it when prepping the VM template for use with Vagrant.
Preparing a Photon OS Template
After deploying the Photon OS VM there are a few steps needed to prepare it for use with Vagrant. First of all the user that Vagrant will use to connect to the VM needs to be created, and given a password:
[root@localhost ~]# useradd -m vagrant [root@localhost ~]# passwd vagrant
Next, we need to give the new Vagrant user rights to sudo without using a password. To do so, run ‘visudo’ then add the following lines to the config file:
Defaults:vagrant !requiretty vagrant ALL=(ALL) NOPASSWD:ALL
Next, we need to create the .ssh/authorized_keys file to allow the Vagrant box to SSH into the VM without having to supply credentials:
[root@localhost ~]# mkdir -p /home/vagrant/.ssh [root@localhost ~]# curl -k https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub -o /home/vagrant/.ssh/authorized_keys
Then we need to adjust the permissions on the newly created file, so that the Vagrant user has access and is the owner:
[root@localhost ~]# chmod 0700 /home/vagrant/.ssh [root@localhost ~]# chmod 0600 /home/vagrant/.ssh/authorized_keys [root@localhost ~]# chown -R vagrant:vagrant /home/vagrant/.ssh
With that done, the prep work for the virtual machine template is complete. Shutdown the guest OS, then convert the virtual machine to a template:
Configuring Vagrant to work with vSphere
With the template ready, it’s time to go back to Vagrant to continue it’s configuration. Vagrant uses the concept of ‘boxes’ which is usually a packaged OS which Vagrant can deploy. However, when using vSphere, we already have a packaged OS in the form of the vSphere template just created. Instead we need to create a ‘dummy’ box which Vagrant can use to deploy the vSphere template. With the vSphere Vagrant plugin installed, there should be a dummy box already available. On my deployment it could be found in:
/root/.vagrant.d/gems/2.2.5/gems/vagrant-vsphere-1.12.1/example_box
Though you may find it in a different location depending on the version you are using. Navigate to that location – you should see a metadata.json file with the following contents:
{ "provider": "vsphere" }
We need to zip this file to turn it into the ‘dummy’ box. To do so, run:
[root@localhost ~]# tar cvzf dummy.box ./metadata.json
Next we need to create a folder to store the dummy box in. This will become the working directory for this box:
[root@localhost ~]# mkdir -p ~/vagrant_vm/example_box [root@localhost ~]# mv dummy.box ~/vagrant_vm/example_box [root@localhost ~]# cd ~/vagrant_vm/
The last step to getting this working is to create a ‘vagrant file’. A vagrant file is what Vagrant uses to provision and start the virtual machine – it contains information about connecting to vSphere, what template to use, the name of the VM and more. To create it, use you preferred text editor and save the file as ‘Vagrantfile’ in the current location. The contents of my Vagrantfile look like this:
Vagrant.configure(2) do |config| config.vm.box = 'vsphere' config.vm.box_url = './example_box/dummy.box' config.vm.provider 'vsphere' do |vsphere| # vCenter or ESXi host to connect to vsphere.host = 'vcenter.test.local' # The location within vCenter vsphere.compute_resource_name = 'esxi.test.local' # VM Resource Pool if required # vsphere.resource_pool_name = 'VagrantVMs' # Virtual Machine template to use vsphere.template_name = 'PhotonTemplate' # Provisioned Virtual Machine Name vsphere.name = 'PhotonVM01' # vSphere Credentials vsphere.user = 'administrator@vsphere.local' vsphere.password = 'password' # vCenter Customisation Spec to use, and IP configuration vsphere.customization_spec_name = 'photon' config.vm.network 'private_network', ip: '192.168.5.224' # If your're using an untrusted certificate vsphere.insecure = true end end
Most of the content above needs on explanation. One part worth covering however is the ‘config.vm.network ‘private_network’, ip: ‘192.168.5.224” setting. This will set the IP address of the provisioned virtual machine. However, in order for it to work on vSphere we need to set up a Customization Specification in vCenter and refer to it in the Vagrantfile using the ‘vsphere.customization_spec_name’ parameter. Note that we will need to specify a static IP in the customization specification, however which ever IP is used there will be overwritten by the one set in the Vagrantfile when the VM is deployed.
With that done, we’re all set to deploy a VM using Vagrant. Whilst still in the same directory as the Vagrantfile, run:
[root@localhost ~]# vagrant up -provider=vsphere
When this command is executed, you’ll see a bunch of tasks run:
Bringing machine 'default' up with 'vsphere' provider... ==> default: Calling vSphere CloneVM with the following settings: ==> default: -- Template VM: TestDC/vm/PhotonTemplate ==> default: -- Target VM: TestDC/vm/PhotonVM01 ==> default: New virtual machine successfully cloned ==> default: Waiting for the machine to report its IP address... default: Timeout: 240 seconds default: IP: 192.168.5.187 ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 192.168.5.187:22 default: SSH username: vagrant default: SSH auth method: private key default: Warning: Host unreachable. Retrying... default: Warning: Host unreachable. Retrying... default: Warning: Host unreachable. Retrying... default: default: Vagrant insecure key detected. Vagrant will automatically replace default: this with a newly generated keypair for better security. default: default: Inserting generated public key within guest... ==> default: Machine booted and ready!
We can now check the VM is ready by establishing a session to it using the ‘vagrant ssh’ command:
[root@localhost vagrant_vm]# vagrant ssh Last login: Wed Jun 21 14:36:33 2017 from 192.168.5.157 vagrant@PhotonVM01 [ ~ ]$ ifconfig eth0 Link encap:Ethernet HWaddr 00:50:56:b6:bc:81 inet addr:192.168.5.224 Bcast:192.168.5.255 Mask:255.255.255.0 inet6 addr: fe80::250:56ff:feb6:bc81/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1533 errors:0 dropped:0 overruns:0 frame:0 TX packets:425 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:120131 (120.1 KB) TX bytes:57420 (57.4 KB)
After establishing the SSH session I ran ‘ifconfig’ to check the IP address. Note that the output shows that the IP address of the VM matches the one that was specified in the Vagrant file that was used to provision the VM.
That’s about all for this article, I’ll be posting some more on Vagrant in the near future, looking at provisioning multiple VMs. For now, we can tidy up the environment by issuing the ‘vagrant destroy’ command, which will power off and delete the provisioned VM.