Keeping with the “things I haven’t used in a while” theme, this tutorial is a re-visit of the Ansible automation platform. It will cover the basics of how to install and configure Ansible on an Ubuntu 16.04 instance as well as use it to provision a Jenkins master instance based on this previous post.
Background
There are a few major automation frameworks at play these days - specifically (and most major), Puppet, Chef, and Ansible. Each of these technologies touts feature sets that vary from simple SSH-based provisioning to full life-cycle automation and compliance enforcement. As Ansible has been top of mind and mentioned by at least a few individuals I’ve interacted with over the last few months, this post will focus on the installation, configuration, and use of the Ansible automation framework. Specifically, at the end of this post, you will have a fully configured Ansible framework and playbook capable of installing and configuring a Jenkins instance based on this previous post.
Technology Ecosystem
There will be 2 hosts for this tutorial, each provisioned through Vagrant. The first host will serve as the Ansible Controller Machine, and the second host will serve as the target on which we wish to install the Jenkins continuous integration and build server. Specifically, the following setup will be realized:
Ansible VM
- Hostname: ansible.localhost
- OS: Ubuntu 16.04
- CPU: 2
- RAM: 2048MB
- Disk: 50GB
- Network: Private Network
- IP: 10.11.13.15
Jenkins VM
- Hostname: jenkins.localhost
- OS: Ubuntu 16.04
- CPU: 2
- RAM: 2048MB
- Disk: 50GB
- Network: Private Network
- IP: 10.11.13.16
In addition, we will assume the following software versions:
- Ansible: 2.2.1.0
- Jenkins: 2.7.4
Notes
The code blocks included in this tutorial will list, as a comment, the node(s) that the commands following need to be run on. For instance, if required on all nodes, the code will include a comment like so:
If the code block only applies to one of the nodes, it will list the specific node it applies to like so:
All commands assume that your user is vagrant
and the user’s corresponding home directory is
/home/vagrant
for the purposes of running sudo commands.
Install Ansible
Perform the following on the Ansible virtual machine to install the Ansible software:
Configure Ansible User and SSH Key
Once the Ansible software has been installed, create an ansible
user and group on both the Ansible
VM and Jenkins VM. Note that this is helpful when things are being managed by multiple users -
however, if you wish to use a service account in managing your infrastructure, ensure you have
a good audit trail that can trace actions back to a physical human being to ensure you maintain
auditability of actions taken on your infrastructure. In addition, the user ID in the following
commands are just examples and you can utilize whatever mechanism and actual value you wish for
assigning IDs to each item:
In order for Ansible to accurately manage most aspects of a system, it needs to be able to execute
password-less sudo on the target instance. Therefore, we will add an entry to the /etc/sudoers
file
on the jenkins.localhost
VM that will allow passwordless sudo for the Ansible user:
Next, we need to set up the SSH keys for the user. We will create the SSH key on the Ansible host and
copy it to the authorized_keys
file of the ansible
user on the Jenkins host:
To test that the SSH key setup worked as expected, attempt to SSH from the ansible.localhost
host
to the jenkins.localhost
host and run a command using sudo
. If you are able to SSH and run sudo
without any password prompt, your configuration is now complete:
Configure Inventory and Ping
Now that the SSH key and sudo setup are complete, we can start configuring Ansible to understand our current environment. First, edit the host file for Ansible to make it aware of the Jenkins host:
Once the host file contains the Jenkins host IP, run the ansible ping
command as the ansible
user to check that the Jenkins host is reachable by Ansible:
If the above output returns, your Ansible configuration between the hosts is now complete and we can start building the playbook for the Jenkins installation.
Jenkins Playbook
Ansible utilizes what are known as playbooks to specify commands to run to provision hosts. The
playbooks are written in YAML syntax. We will be creating a playbook that corresponds to the steps
required to install the Jenkins service. We will utilize the directory layout specified
here and since
we only have 1 host, we will simply include the playbook for that host in the master site.yml
playbook - create a site.yml
file in the ansible
user’s home directory and ensure it contains
the following:
---
- hosts: all
become: true
vars:
dependencies: [ 'python-software-properties', 'python-pycurl', 'daemon' ]
jenkins_deb: jenkins_2.7.4_all.deb
tasks:
- name: Update Apt Cache
apt:
update_cache: true
- name: Install Dependencies
apt:name={{ item }} state=latest
with_items: "{{ dependencies }}"
- name: Add OpenJDK Repository
apt_repository:
repo: 'ppa:openjdk-r/ppa'
- name: Install OpenJDK
apt: name=openjdk-7-jdk state=latest
- name: Download Jenkins Package
get_url:
url: https://pkg.jenkins.io/debian-stable/binary/{{ jenkins_deb }}
dest: /tmp/{{ jenkins_deb }}
mode: 770
- name: Install Jenkins
apt: deb="/tmp/{{ jekins_deb }}"
One item to note about the above code - this code is very elementary and does not consider situations
such as whether software is already installed, a file is present prior to utilizing it, etc. The point
is, there are many optimizations that can be made to the code (as well as defensive mechanisms), but
for simplicity sake, these items are included in this tutorial. A brief explanation of what the above
site.yml
master playbook accomplishes in the respective order:
- Target all hosts (since we only have 1).
- Run commands as root (using
sudo
). - Update the Apt cache (just in case brand new VM is out of date).
- Install required dependencies and OpenJDK.
- Download and install the Jenkins package.
Now that the playbook is defined, we can run it:
If all went well, you can now visit the Jenkins UI via visiting the following URL in your browser:
If the Jenkins UI pops up, you have successfully completed the Jenkins installation using Ansible!
Summary
There are many other useful things associated with Ansible that were not even considered in this post. I encourage you to look at the Ansible documentation as it is quite complete and understandable, and details the true capabilities of the Ansible automation framework. In addition, having a pattern and standards associated with how to construct Ansible playbooks, share code, audit actions, etc. is essential to ensuring the integrity of your resources and cleanliness of your Ansible code. Organization of your code, grouping of your hosts, and least-privileged access are just some components that will be most critical to mass adoption of the Ansible framework while being able to maintain the integrity of your environments.
Credit
The above tutorial was pieced together with some information from the following sites/resources: