At one of our clients, we are using Cloudstack to develop an internal “cloud” infrastructure, and Jenkins as the continuous integration server. In this post I describe how to leverage Cloudstack at Jenkins using the JClouds plugin. This setup allow us to create slaves on demand, get them down automatically when load decreases, and create single-use slaves if needed.
In order to explain how this integration works, we’ll use Twitter’s twitter-text-java project. I chose this project because it is publicly available, displays tests status on its Github page, and does not require any special configuration, making easier to focus on cloud settings.
Configure a Cloudstack image
Before we start with Jenkins configuration, we need to have a Cloudstack template to be used as base image. We created a Cloudstack template with a freshly installed CentOS 6.2.
Since we are cloning a git repository, Jenkins must have the Git Plugin installed and configured. To build the project we need to have Git, a JDK and Maven installed. For this tutorial, we chose to install these tools through Jenkins configuration (when instances are created) instead of installing them on the base image.
Configure Jenkins’ Cloud options
In the following steps we will configure a cloud provider and an instance template, so that Jenkins will know how to launch new instances. We will also enumerate the characteristics these instances should have.
- Go to Jenkins’ configuration page (e.g.
- Scroll down to the
- Set a Cloud profile name, select Cloudstack provider and specify the endpoint URL (e.g.
http://your-cloud-manager:8080/client/api). Identity and credential fields should be completed with Cloudstack’s user API Key and Secret Key respectively.
When providing RSA Private Key and Public Key values, you can just select the “Generate Key Pair” option to generate them automatically. Take into consideration that there is no need for having these keys setup inside the base image use by Jenkins. The JClouds plugin will run a bootstrap script when creating instances to configure a
jenkins user with the provided ssh-keys.
Use the “Test Connection” button to check endpoint url is correct and Jenkins is able to connect to the cloud provider.
In the Cloud Instance Templates section you can configure different instance profiles:
To configure the first one:
- Set a name (avoid whitespaces!) and description
- You may want to specify a label to force jobs to run on Cloudstack slaves and to avoid running on Jenkins master.
- Choose a hardwareId (Cloudstack’s compute offering uuid) and imageId (Cloudstack’s template uuid), and check if these are valid ids. The jClouds plugin will validate that the Cloudstack endpoint URL is correct and that the identity and credential values specified have enough permissions to access the Cloudstack configuration.
At the end of the Image/OS Options there is an “Advanced” button where additional configuration options may be specified.
Click on it and configure the following options:
Jenkins user = jenkins Allow sudo = yes Remote FS Root = /jenkins Admin username = root-username Admin password = root-password
Save your changes.
To leverage cloud configuration we still need to create/edit a Jenkins’ job. For our
twitter-java-text project, we created a Maven job.
If you want this job to be run just on certain nodes (i.e. just on the ones created by the cloud provider), check the “Restrict where this project can be run” option and specify an instance type label.
At the bottom, complete the “Build Environment” options checking the “JClouds Instance Creation” and selecting a cloud name, template and number of instances.
Other configuration options correspond to standard job settings.
To complete the setup of the project, be sure to specify the git repository, mvn clean install goals, add a shell script to be executed as pre-build step with
git submodule init && git submodule update command as specified in the project README.
jClouds plugin enables Jenkins to create build slaves on demand leveraging the cloud provider of your choice. The benefits are:
- better hardware usage
- no more large job queues: if the queue grows, new slaves get created resulting in a higher job throughput
- slaves keep a consistent configuration, since they are all created from same image and renewed periodically
The plugin allows you to create single-use slaves, which could be useful to ensure the slave is correctly setup. Currently we reuse them with a low retention time, avoiding boot times when under heavy load, and get slaves renewed when the load decreases. To speed up boot time we also use a base image with git, JDK, Maven and other tools needed for the build.
You may also condider creating a base image with a Jenkins master install, so that each team can deploy its own Jenkins master with pre-configured plugins and cloud settings. For this approach make sure teams have good reasons to create another Jenkins and ensure that builds from a Jenkins instance do not depend on builds from another.
Sounds interesting? Go and give it a try!