• Skip to primary navigation
  • Skip to main content

jdgreen.io

The personal blog of James Green

  • Home
  • Technology
    • Announcements
    • Industry
    • Reviews/Guides
    • Tech Field Day
    • Interviews
  • Health
    • Food
    • Biohacking
    • Fitness
  • Faith
  • Book Notes
    • Business Books
    • Faith Books
    • Health Books
    • Technology Books
  • About
  • Show Search
Hide Search

automation

Vagrant Series » Multi-Machine Environments (Part 6)

James Green · Aug 7, 2015 ·

Vagrant is neat if you need a whip up a machine to quickly test a script or check compatibility on an operating system that is different than what you normally run. And the value of that isn’t to be minimized. But some of the real power of Vagrant happens when you start to stand up full environments (think 3-tier applications or large scale web server farms) in a repeatable, effortless way. In Hashicorp Land, this is specifically referred to as a “multi-machine” environment. Any Vagrantfile that defines and controls multiple guest machines qualifies for this descriptor.

Defining Multi-Machine Environments

Building a Vagrantfile that will configure a multi-machine environment is as simple as defining multiple VMs with the parameter config.vm.define. In the below example nabbed from Hashicorp documentation, one case see that an Apache front end and MySQL back end are both defined.

Vagrant.configure("2") do |config|
  config.vm.provision "shell", inline: "echo Hello"

  config.vm.define "web" do |web|
    web.vm.box = "apache"
  end
  config.vm.define "db" do |db|
    db.vm.box = "mysql"
  end
end

Once the VMs are defined, configuration takes place by using the inner variable with the same name. In the example, web.anything and db.anything will apply configurations specifically to that machine. Global configurations can still be defined and will apply to all VMs. When configuring a multi-machine environment, it’s important to consider the load order of a Vagrantfile. I covered this in Part 3 of this series, but just to quickly recap, the load order is:

  1. Vagrantfile packaged with the box that is to be used for a given machine.
  2. Vagrantfile in your Vagrant home directory (defaults to ~/.vagrant.d). This lets you specify some defaults for your system user.
  3. Vagrantfile from the project directory. This is the Vagrantfile that you’ll be modifying most of the time.
  4. Multi-machine overrides if any.
  5. Provider-specific overrides, if any.

As the Vagrantfile grows and a large number of machines are defined, it can become a bit of a mess. Scott Lowe wrote about an idea he found over on this blog that breaks all the configuration data out into a separate YAML file. You could also use JSON or XML if you’re more comfortable with that, as in this example.

Accessing Multi-Machine Environments

When using a multi-machine environment, some vagrant commands need to become more specific. If you issue vagrant sshin a multi-machine environment, which machine should be connected to? The commands in a multi-machine environment that only make sense for one machine need to have the machine specified in the command. So in the case of SSH, the command would be vagrant ssh web. In the case of a command like reload, you could issue vagrant reload and reload the whole environment, or you could specify one VM, as in vagrant reload db. Since sometimes one needs to be specific but there’s also a large number of VM’s, the Vagrantfile will also parse regex when it identifies a regular expression for the name, such as /web[A-Za-z0-9]/.

Vagrant Series » Project Setup, Vagrantfiles, and Boxes (Part 3)

James Green · Jul 27, 2015 ·

In the previous post in this series, I looked at how to provision an Ubuntu box with Vagrant in a matter of moments. Now that the process is understood and the power of Vagrant has been seen, it’s time to break it down a little bit and show how Vagrant is able to create a fully functioning VM with a simple vagrant up.

Vagrant Project Setup

When deploying a new development environment, the first thing to do is set up an area for all of the project files. In the previous post, vagrant init hashicorp/precise32actually created the project in whatever directory the terminal was open to. For a bit more organization moving forward, I prefer to create a folder for a given Vagrant environment. The configuration files will be stored here, as will any supporting files. For instance, a www share for an Apache server might exist in this folder. Creating a new project is easy.

mkdir VirtAdmin
cd VirtAdmin/
vagrant init

In the desired location, just create a new folder, and from within that folder run vagrant init.This will automatically generate a Vagrantfile! What’s a Vagrantfile, you might ask?

[Read more…] about Vagrant Series » Project Setup, Vagrantfiles, and Boxes (Part 3)

Vagrant Series » Synced Folders (Part 4)

James Green · Jul 10, 2015 ·

Developing with local tools (IDE, Sublime/Coda/etc) but testing code on a remote machine or local VM can be painful because of the effort required to push the updates to the machine running the application. Vagrant solves this problem with the concept of Synced Folders. For me, this is easy to relate to VMware’s Shared Folders feature of Fusion/Workstation. And as it turns out, this is exactly what’s happening – the Shared Folders feature of the provider is what enables this functionality. This feature allows a local folder to be mirrored with a folder in the guest OS of a virtual machine. What this accomplishes is that very little effort is required to make updates using local tools, but have the changes reflected in the development environment.

Setting up Vagrant Synced Folders

Synced folders are actually enabled by default; the project directory (the one your Vagrantfile lives in) will be shared with the guest OS at /vagrant. That’s handy enough for getting files back and forth. But the real power of this feature can be shown with a simple example. Let’s say the running Vagrant machine is an Apache server. By sharing the DocumentRoot folder with the host OS, development can be done on the same files that are serving the web page. This means no pushing and pulling to see the changes you’ve made reflected live. Setting up Synced Folders for a given objective is simple: just add the config.vm.synced_foldermethod to the project’s Vagrantfile, specifying the path on the host machine and then the path on the guest machine.

As an example, on my machine I’m using a Vagrant box to do WordPress development for this site. I’m able to play with CSS and make changes to the site’s appearance without tinkering with the live version. Testing new plugins offline is also something I do with this. In the Vagrantfile for my testing box, the following configuration shares the website files:

config.vm.synced_folder "www/", "/srv/www/", :owner => "www-data", :mount_options => [ "dmode=775", "fmode=774" ]

The extra options at the end set permissions on the directory, and specify options to pass to the mount command. This allows me to use Sublime Text 3 and other tools on my MacBook Pro to manipulate the files actively being served from the web server I have spun up. In a more complex environment, you may want to enable/disable the Synced Folder based on conditionals during project setup. Disabling the share can be accomplished by appending disabled: trueto the line.

Alternatives

Depending on the environment, a Shared Folders feature for the provider may not be available. But not to fear! A Synced Folder configuration can also be set up to use NFS for Linux machines (or RSync when nfsd is not available on either the host or guest) and SMB for Windows machines. This means that with few exceptions, Synced Folders can be configured in every environment.

See the full official documentation on Synced Folders here, and don’t forget that the project root is already synced to /vagrant! Next up, a brief look at Vagrant networking.

Vagrant Series » Networking (Part 5)

James Green · Jul 4, 2015 ·

Your use case for Vagrant will determine what sort of networking setup is appropriate. The good news is that there are plenty of options. Vagrant defines three high-level options for networking that are then implemented in a specific way by the provider. The three options – which are a generic description of a type of access – are:

  • Port Forwarding
  • Private Network
  • Public Network

All networking configuration is specified with the method config.vm.network.The identifiers for each type of network are :forwarded_port, :private_network, and :public_network. Following this is a set of options which change based on the provider and the type of network being specified. An example Vagrantfile line for a port forward to port 80 which the host can access on 8080 would be as follows:

config.vm.network "forwarded_port", guest: 80, host: 8080

Multiple networks can be configured simply by adding multiple lines of this same sort of specification. After updating networking in a Vagrantfile, a vagrant reload will make the settings take effect.

Vagrant Networking Options

Port Forwarding

Port forwarding may be the simplest option if only local development is taking place and other local environments don’t need to interact with the one in question. It’s probably less confusing to use a private network in a multi-machine configuration, but in a single machine environment, port forwarding is a simple way to access the guest machine. Do take care to specify whether the forward needs to be TCP or UDP. The forward uses TCP by default, so it will need to be changed if UDP is required. Also, if the port forward needs TCP AND UDP both, you must specify two separate port forwards – one for each. The full list of configuration options for a port forward (as taken directly from the documentation) is as follows:

  • guest (int) – The port on the guest that you want to be exposed on the host. This can be any port.
  • guest_ip (string) – The guest IP to bind the forwarded port to. If this is not set, the port will go to the every interface. By default, this is empty.
  • host (int) – The port on the host that you want to use to access the port on the guest. This must be greater than port 1024 unless Vagrant is running as root (which is not recommended).
  • host_ip (string) – The IP on the host you want to bind the forwarded port to. If not specified, it will be bound to every IP. By default, this is empty.
  • protocol (string) – Either “udp” or “tcp”. This specifies the protocol that will be allowed through the forwarded port. By default this is “tcp”.

Vagrant is intelligent enough to not let you spin up two machines with port forwards using the same host port (8080, for example). By default, this will simply not be allowed. But you can also specify :auto_correct to have Vagrant resolve the conflict on its own.

Private Network

A private network configuration will allow the machine (or multiple machines) to be assigned an IP address in private address space accessible only from the host machine. How this is accomplished depends on the provider; for instance, VMware Fusion would create vmnet? and install a virtual adapter on the host machine connected to this network. This may be less confusing to use in a multi-machine deployment. It does, however, require that at setup time the user has permissions on the host machine to install a virtual network adapter. The private networking mechanism of the provider should have the ability to hand out addresses via DHCP, and that’s likely the easiest way to use this configuration. A static IP can be set if necessary, though.

Public Network

A public network configuration is much the same as a private network, with the exception that the network adapter of the guest machine is actually bridged to an adapter that is connected to the upstream network. You can either specify the adapter to bridge to in the Vagrantfile like this:

config.vm.network "public_network", bridge: "en1: Wi-Fi (AirPort)"

Or, you can leave it unspecified, and when you do a vagrant up, a wizard will prompt you for the adapter to bridge to, like this:

==> default: Available bridged network interfaces:
1) en0: Wi-Fi (AirPort)
2) en1: Thunderbolt 1
3) en2: Thunderbolt 2
4) bridge0
5) p2p0
6) awdl0
==> default: When choosing an interface, it is usually the one that is
==> default: being used to connect to the internet.
    default: Which interface should the network bridge to?

One word of wisdom when using this wizard – @vmcutlip and I found out after fiddling with it a bit that the wizard is asking for the menu number, not the interface name. So specifying ‘en0’ will bomb, and not be very specific about why. If you want en0, just type ‘1.’

As mentioned, the implementation of these three options will differ depending on the underlying provider. So be sure to do some research into the exact provider in use for your case. Next up in the series, Teardown!

Vagrant Series » Introduction (Part 1)

James Green · Jul 2, 2015 ·

I’ve been hearing about Vagrant for well over a year now, but until this point I haven’t had a requirement to dig in. Vagrant seems to come up in the same conversations as configuration management tools like Puppet, Chef, Ansible, and so forth. Those are tools I’m also only vaguely familiar with. I created a few Puppet manifests a while back just to get the idea, but maybe Puppet should be the next series! But in the short term, we’ll use a bit of Puppet in this series to configure Vagrant boxes. At any rate, this series is going to walk through the concept and implications of Vagrant, the initial setup and use, and then branch out into some more interesting stuff. Let’s start at the beginning.

What is Vagrant?

Vagrant is a tool developed by HasiCorp (named after founder Mitchell Hashimoto) to facilitate the rapid and accurate deployment of development environments. Historically, there have been many hours spent on-boarding new employees, setting up contractors or consultants, and recreating production environments on development systems. The aim of Vagrant is to eliminate that overhead by automating the deployment of development systems, the configuration of which is stored in a version control system like Git. This ensures not only efficiency, but unity between team members and environments.

Vagrant is the configuration engine, but workloads are still provisioned in virtual machines or containers on the platforms you know and love like VirtualBox, VMware Fusion/Workstation, Docker, or AWS. There’s a growing list of providers, and if none of those fit the bill, you could also roll your own.

Why Would I Want Vagrant?

As mentioned, a few of the main benefits of leveraging Vagrant are the rapid provisioning time of new environments, as well as the ability to reproduce environments with 100% accuracy. That may mean mirroring the production environment to be sure development is taking place on a matching system, or it may mean ensuring that all developers on a team are using the exact same development environment as they create and test code. The granularity of dependencies in some systems can make manually replicating a development environment extremely challenging; but this is actually quite simple with Vagrant. And because Vagrant is doing the configuration, the system can be deployed on Windows, Mac, or Linux with exactly the same result.

Now, I’m the farthest thing from a developer, which begs the question: “Why do I care about Vagrant, and what use could it have for me?” Well, first and foremost, my job as an infrastructure architect is to design a platform that makes developers productive and helps them to deliver their product efficiently and with as few bugs as possible. Understanding how Vagrant can make them more efficient will help me design a better infrastructure for them. Secondly, however, there are certainly applications for infrastructure/operations folks. Imagine I’m creating a shell script to configure production systems in mass. It would take a matter of minutes to spin up a similar system local to my machine that I can test my script on as I create it.

How Do I Get Started?

Thankfully, since I’m so far behind, the installation of Vagrant is super easy at this point. The next post in this series will document the initial setup and instantiating my first Vagrant box. As a very brief preview of how complicated Vagrant is, the steps to get up and running follow.

  • Install VirtualBox
  • Install Vagrant
  • Download and initialize a “box” (a Vagrant environment package)
  • Run ‘vagrant up’

At the end of that whole 10-15 minute span, you’ll have a running machine configured exactly as specified and ready for consumption!

I think this is going to be a great learning experience, and I hope that by learning how to make the best use of Vagrant, I’ll also get a good head start on some other tools like Puppet/Chef. I also hope to wrap my head around the day-to-day life of a developer a bit better. As DevOps culture becomes increasingly popular, the infrastructure engineer / developer hybrid role is quite valuable. And I’m all about being valuable. 🙂

  • Go to page 1
  • Go to page 2
  • Go to Next Page »

Copyright © 2023 · Monochrome Pro on Genesis Framework · WordPress · Log in

Posting....