Continuous Delivery of a Simple Web Application Tutorial – Part 3

In Part 1 we discussed the architecture of what we’re trying to build.

In Part 2 we created our development server with Ansible.

In Part 3 we will finish off Ansible with creating our Load Balancers and WebServers.  Then we’ll setup Git and check everything in.

In Part 4 we will finish it all off with Jenkins configuration and watch as our code continuously updates.

At this point, all we’ve done is create the development environment, but we haven’t configured any of it.  We’re going to take a break from that for a little bit and set up our web servers and load balancers.  This should be pretty straight forward.

Load Balancers

Cisco OpenStack Private Cloud / Metacloud actually comes with several predefined images.  One of those is the MC-VLB, which is a preconfigured server running HAProxy with the Snapt front end.  You can see all the documentation for managing the HAProxy via the GUI using their documentation.

We’re just going to configure it with Ansible.  We’ve created a file in our ansible directory called load-balancers.yml.  This file contains the following:

We are using the encrypted vars/metacloud_vars.yml file to pass in the appropriate values.  The flavor-id corresponds to what we saw in the GUI.  Its actually a flavor size created specifically for this load balancer image.

Once the VM is up, then we give it the role load-balancer.  This goes to the roles/load-balancer/tasks/main.yml task.  This task looks as follows:

Pretty simple as it just copies our config and restarts the load balancers.  This is one case where we’re not using containers in this setup.  We could have just created our own image using nginx to do it or even haproxy, but we thought it was worth taking a look at the instance to see what Metacloud provided.

The key to this is the /etc/haproxy/haproxy.cfg file.  This file is as follows:

This configuration should highlight one of the glaring problems with our environment.  We’ve put the web servers (which we haven’t even created yet!) in this static file.  What if we want to add more?  What if we get different IP addresses? While this blog won’t go over the solutions, I’d welcome any comments.

Now running:

Our load balancers will come on line and be ready to serve traffic to our web instances.  Let’s create those now.

Web Servers

Calling these instances ‘web servers’ is probably not correct.  They, in fact will be running docker containers that have the appropriate web services on them.  These servers will look just like the development server we created in the previous blog.

This script should look very similar to what you saw in deploying the development server.  The server boots up and it runs the script.  This script is exactly the same as the one in part 1 except at the very end of it, it brings up the latest application container:

This is nice because its completely automated.  The server goes up and the latest web service starts.  We could remove the instance and create a new one and it would get the latest.

As long as there is one server up, our website will stay up.  By putting java on it, Jenkins can use it to run commands and by putting Ansible on it we can configure it if we need to.

Since you haven’t created the ci:5000/vallard/lawngnomed:latest docker image, yours probably won’t work.  But you could give it a docker hub image instead to make sure it gets something and then starts running.

Let’s bring up the web servers in their current state:

Taking Stock

At this point we have accomplished 3 things:

  1. Development Server with all the services are installed
  2. Load Balancers are up and pointing to web servers
  3. Web servers are ready, but don’t have any images yet to run.

Our next step is to start configuring all those services.  This is where our Ansible work is done.  We are using it solely for creating the environment.

Gitlab configuration

Navigating to our public IP address and port 10080, or if you put DNS and are using the nginx reverse proxy, we can now see the login screen.  The default root password is 5iveL!fe.  We are using some of the great containers that were built by Sameer Naik.


We will be forced to create a new password.

create password

Then we need to lock things down.  Since we don’t want just everyone to sign up we can go to the settings page (click the gears in the top right side) and disable some things:


From here we can add users by clicking the ‘Users’ item in the left sidebar.

Add users

I created my vallard user and that is where I’ll upload my code.  Log out as root (unless you need to add more users) and log in with your main account.

The first thing you’ll want to do is create a project.  You may want to create two projects.  One for infrastructure as code (the Ansible scripts we’ve done) and another for the actual application.  Clicking on the cat icon in the top left side will take you to the dashboard.  From there you can create the new projects.  Once you create them you are given instructions on how to set up a git environment.  They look like this:

The first problem you will have if you do this is that you haven’t put your ssh key into Gitlab.  Click on the profile settings icon in the top right (the little person) and click on SSH keys.  Here you can upload your own.

Protip:  run the following command to copy the public key on your mac to the paste buffer:

Entering this in the screen should then allow you to do your first git push.


The Jenkins User

At this point you may want to decide whether or not to create a Jenkins user to do the continuous integration.  We created a Jenkins user and gave that user its own SSH key as well as a login to the Cisco OpenStack dashboard.  Since we created this new user, we also created a keypair for him so that he could get into the instances he created.  Copy the jenkins ssh key-pair to a safe place as we’ll be using it soon.  Add the Jenkins user to your project so that he can check out the code and see it.

End of Part 3

If you got to this part, hopefully you have pushed your Ansible code we created into Gitlab.  You also may have created a Jenkins user that can be used for our continuous integration.  Please let me know if you had any issues, comments, suggestions, or questions along the way.  I want to help.

In the last part 4 we will go over configuring Jenkins and integrating it into Gitlab.  Then we will create some tasks to automatically run to test our systems.