Continuous Delivery of a Simple Web Application Tutorial – Part 4

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 finished off Ansible with creating our Load Balancers and WebServers and setup Git to check everything in.

In this last part, we’re going to configure Jenkins to use all of these components and do the orchestration for the application delivery pipeline.

1. Configure Global Security

When this Jenkins container first comes up, we lock it down so people can’t access it.  This is done by clicking configure Jenkins and then Configure Global Security.  The ‘Enable Security’ button should be clicked and then you can decide how you want the others to be set.  Mine looks like the screenshot below.

Screen Shot 2015-06-15 at 9.05.43 AM

Notice that you have the option of tying this into an LDAP system.  I’m just using the local database and not allowing new users to sign up.

When you hit apply, you’ll then be able to create an account.  Once created, log back in with this account.

2. Install Plugins

The great thing about Jenkins is all the different plugins it provides to be able to test and automate the tasks.  I added a few plugins for my setup, but you may need more to run the test cases.

I used the following plugins:  Gitlab, OpenStack Cloud Plugin, Docker Build and Publish, Slack, and SSH.







Once added, I applied the changes and restarted the system.

3. Configure Global Gitlab Plugin

From the main window, we go to Manage Jenkins and then Configure System.  We’ll add the Gitlab integration.  This is as simple as filling out the form for out Gitlab instance.  Using the internal hostname for this is the easiest way.  However, if you put your gitlab instance in another Cisco OpenStack Private Cloud availability zone then you may need to specify the public IP.  My configuration looks as below:


The API Token is found in the profile section under Gitlab.  Look at the account icon and then the ‘Account’ field.  Test the connection to make sure you can connect and that it shows ‘Success’.


4.  Configure global OpenStack Plugin

Connecting to Cisco OpenStack Private Cloud is now just a matter of entering in the right credentials.  We first add a new cloud.


The tricky thing here is to enter the right credentials.  Make sure the Identity you enter is in the form: <project name>:<username>.


Notice in the above example, the user name is jenkins-ci but the project name is LawnGnomed Production.  The credential is just the password of the user.  We used the RegionOne for the region.  This will probably be the same for most installations.

Once we are attached to the cloud we need to make sure we have a slave that can be used.  The requirements of this slave are that Java is already installed.  CoreOS doesn’t come with Java installed so we have to add it.

5.  The Jenkins Slave Instance

There was a great post I found that describes a method to get Java running on CoreOS as part of a post install script.  Using this I cloned the image and then booted subsequent images from this image.  I also made sure the jenkins user keys were installed so that the jenkins user could log into the instance without any passwords.  This is really all that is required for the slaves.  Once the image was built, I created the plugins to this image in Jenkins:


Note that the place for Jenkins to configure jobs is in /home/core/jenkins.

We also created core credentials so that Jenkins could log into the jenkins slave.


You should be able to now save that and test the cloud instance. Notice here that you can attach to multiple clouds including something like AWS, Digital Ocean, or others by simply using more plugins or configuring other credentials.  There’s a great post by Jessie Frazelle of Docker showing how they use Jenkins to test lots of permutations of code build.  I used to think about all the permutations that we would support in our development environments and there was no way a human could test it all.  A robot like Jenkins, however, could easily do it and keep track of all those permutations of linux distros, etc.

6.  Add Slack to Jenkins

Whenever something builds, finishes building, has an error, etc, we want the whole team to be alerted.


Slack gives us this power.  We simply plugin the integration token we got from Slack’s plugin menus.

7.  Create the Project!

Ok, now that we have configured the global settings of Jenkins, let’s create a project that takes as input a Git push notification and then builds a docker container.

Create a basic Freestyle project:



Now we need to configure it.  We’ll use a lot of the settings we already used from our global configuration.

7.1 Restrict where builds can be done.

Builds will want to run on the master Jenkins server.  By using the label we gave it in the global settings we can make sure that whenever this builds, it has to run on one of our slaves.



7.2. Slack Notifications

If you want slack to notify you on certain conditions, check all that apply!

Screen Shot 2015-06-15 at 10.20.23 AM


7.3 Configure Source Code Management

Screen Shot 2015-06-15 at 10.22.45 AM

There are some non-intuitive settings here, but this is what worked for me.  I also had a build trigger settings appear as below:

Screen Shot 2015-06-15 at 10.24.31 AM

7.4 Build Environment

The build environment is where we specify what type of slave we want to build on.

Screen Shot 2015-06-15 at 10.25.30 AMHere I make sure that each slave is only used once and that I use the correct slave instance.  This is the cool part cause each time a job is submitted this is the setting that will build a new instance on top of Metacloud.

7.5.  Build actions

The last part is what do we want the robot to do.  He’ll now provision an instance when code is pushed, but what do you want him to do once its pushed?  This is where you’d run all your test cases.  But here, I’m just going to build a docker container and put it into my local docker registry.

This assumes you have a Dockerfile in your code you are testing.  In the advanced settings you specify a subdirectory if any of where it is.  Mine is in the rails/ directory.

Screen Shot 2015-06-15 at 10.33.23 AM

Notice that you would do ‘Add build step’ to do more for running tests and things on the container.  I just left it to build the container.  The fun part in that was making the container as prebuilt as possible (e.g: putting all the gems in first) and then running the build.  By pulling from a local registry instance, it makes the build go a lot faster than if I were pulling from Docker Hub every time.

When the build is done, I push to the repository and then do the post build action of ‘Update WebServers’.  This is another Jenkins job that simply goes through and SSH’s to my web servers and swaps out the running container for a new one.


That was a pretty intense ride and I hope I’ve covered most of it.  I demonstrated this at Cisco Live in several sessions that I’ll post on here as they become available.  There are a few things that I think are important to summarize:

1.  I wrote no code to get this environment up and running.  I did do configuration with tools but most of my work was just to configure and integrate.

2.  Most problems we are facing have already been solved or looked at by very smart people.  So look for easy done work instead of trying to reinvent the wheel.

3.  The stack is completely portable to different cloud providers.  I did this on Cisco OpenStack Private Cloud.  This could have worked just as easy on another OpenStack system. All the API calls were the same.

There were several steps I may have left out as it did require a lot of configuring.  The Ansible Scripts can all be found on my Github account in the Cisco Live 2015 repo.  Please let me know if there are any questions via the comments or via Twitter.

Thanks for reading!!!