Alright!, let’s build upon a previous post. I did what is described on this post for an internal demo with my team and decided to share it here so you can run off and build cooler stuff based on this work.

On this post we will deploy 3 OpenStack instances that will reside behind an Nginx VM configured as a load balancer. It is a simple cloud web-scale example. You can do this with OpenStack or even using modern container infrastructures.

Let’s begin…

First we need our load balancer. For this example, we will name the host http://www.puppet.xuxo and configure it to serve our page from 3 hosts: linux-web001.puppet.xuxo, linux-web002.puppet.xuxo, and linux-web003.puppet.xuxo.

Note: In my setup, my Puppet Master is also a DNS server. Every time a node gets provisioned by Puppet, the FQDN and other host info gets exported and when Puppet agent runs on the master, it updates the DNS zone. Therefore, I really don’t need to worry about new servers, etc. being found across my infrastructure. In your setup, you might have to populate hosts files to make all this work seamlessly.

Of course we will be using Puppet to build the load balancer. Let’s create some quick code to make this happen. On the location of your Puppet code, create our folder:

mkdir -p nginx_loadbalancer/{files,templates,manifests}

Inside manifests, let’s create the class loadbalancer.pp with this content:

class nginx_loadbalancer::loadbalancer {
    package {'nginx':
    ensure => 'installed',
    service {'nginx':
      ensure => 'running',
      enable => true,
    file {'/etc/nginx/nginx.conf':
      ensure => file,
      source => 'puppet:///modules/nginx_loadbalancer/nginx.conf',
      notify => Service['nginx'],

On the code above we reference a basic configuration file that resides in the files directory:

events { }

http {

      upstream web_rack {
      server linux-web001.puppet.xuxo:80;
      server linux-web002.puppet.xuxo:80;
      server linux-web003.puppet.xuxo:80;

server {
       listen 80;
       server_name www.puppet.xuxo;
       location / {
       proxy_pass http://web_rack;

Classify a node to be http://www.puppet.xuxo and run the puppet agent. Our load balancer will be built.

Right now you will get a ‘Bad Gateway‘ message if you try to browse http://www.puppet.xuxo since we have nothing behind our load balancer. To create the instances we refer back to the OpenStack VM provisioning we did previously:

On the OpenStack directory we created in the prior post, create or modify the following three files:

instances: Simple text files with instance names Bash script to provision the VMs The cloud bootstrap file for OpenStack

Edit instances and populate with some instance names:


Edit as below and replace values with yours. The comments describe what the script is doing:

# shell script to demo the deployment of an openstack instance
# get creative, you can loop through a file to create multiple instances,etc.
# Uses accompanying user_data script to provision Puppet agent
# jesus at

# --change variables or source from file.
# Replace with your OpenStack environment data. You can use
# Private side IP instead of OStack's associated floating one

export master_ip="192.x.x.x"
export user_data_script=""
export key="<your_key_name>"
export img="centos_7_x86_64"
export flavor="d1.small"
export sec_group="<your_sec_group>"
# v where we installed the openstack client
export ostack_dir="/Users/jgarcia/.ostack_env/bin"

export OS_AUTH_URL="https://<your_ostack_provider>:5000/v2.0"
export OS_TENANT_ID="9e7fd724f0764461ac5cbe874d8fb5e5"
export OS_TENANT_NAME="<your_tenant_name>"
export OS_PROJECT_NAME="<your_project_name>"
export OS_USERNAME="<your_username>"

if [ -z "$OS_REGION_NAME" ];
 then unset OS_REGION_NAME

# function definition
function provisionVM(){

echo "Please enter your OpenStack Password: "

# Here we will loop through instances and create each VM
# We will also associate a floating IP to each one

for i in `cat instances`;
 echo "Creating VM $i"
 ${ostack_dir}/openstack server create --user-data ${user_data_script} --image ${img} --flavor ${flavor} --security-group ${sec_group} --key-name ${key} $i
 echo "Assigning floating IP"
 float_ip=`${ostack_dir}/openstack ip floating list | grep None | awk -F '|' '{print $3}' | head -1`
 ${ostack_dir}/openstack ip floating add ${float_ip} $i
 echo "Floating IP assigned"
 ${ostack_dir}/openstack server show $i


Now edit This is the cloud injection file that will provide some initial configuration to our VMs. On ours, it will add some basic host info and provision Puppet’s agent to get to the master and retrieve catalogs:

SHOST=$(curl -s|awk -F '.' '{print $1}')
PIPV4=$(ifconfig -a|grep -w inet|awk '{print $2}'|grep 192)
grep -i $PHOST /etc/hosts || HSET=1
grep -i $PIPV4 /etc/hosts || HSET=1

# Replace with your master's info
echo "192.x.x.x master.puppet.xuxo master" >> /etc/hosts
#echo "$PIPV4 $PHOST $PHOST.puppet.xuxo" >> /etc/hosts
hostname $PHOST
sleep 10
curl -k https://<your master>:8140/packages/current/install.bash | bash

Ok!, we’re good to go! Open a terminal and run our provisioner:


The machines will begin building one by one and bound to the Puppet Master.

Note: In my setup, the Puppet Master is configured to auto-sign certificate requests for any machine with the domain name of .puppet.xuxo. This is a very common setup for cloud provisioning where numerous machines get built.

Once done, the loadbalancer can be restarted to serve the page. I have made the page to refresh and show which host is serving the page:


The HTML is simple and uses Facter to gather the FQDN and IP of each host to demo this exercise properly.

Thank you for reading and you can get the files used for this exercise here.


One thought on “Let’s micro web-scale something!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s