Me. Us. Them.
The story I tell when I explain the various offereings that Red Hat has based on Ansible follow is based on the progression of Me. Us. Them.
Me: Get my playbook working for me on my workstation. For this, I use Ansible Engine.
Us: Share my playbook with my larger team. For this, I use Ansible Tower.
Them: Make a Self service catalog for the larger organization to consume. This is where Ansible integration into other products comes in to play. I typically talk about CloudForms integration here, but Satellite and OpenShift are also capable of making use of Ansible here.
Here is how I have my local setup for doing Ansible based development. This is organized roughly around how Tower will later consume the roles and playbooks I design here.
Table of contents
Git Repositories
Ever since I started doing the majority of my coding on a Linux system, I have kept my working code under my home directory in a sub-directory called “devel.” For my current work, I have two main git repositories under ~/home/devel that contain Ansible work. Rippowam, which I wrote about a while back, is my provisioning and install repository. There are multiple playbooks here, which can provision to OpenStack, Azure, and direct Libvirt. Additional playbooks and roles can:
- Install upstream code like FreeIPA
- Enroll a system with the Red Hat content delivery systems
- Install Red Hat products
My Second repository is a DevOps demo I’ve started working on. It is designed to show off the capabilities of Ansible when talking to people that are involved in development, continuous delivery, and operations. I keep this separate from the Rippowam repo in order to keep it simple and understandable.
~/ansible
I want to organize the code that is used to call the playbook in a similar manner to what I am going to use when I later deploy it to tower.I keep all of the configuration information in a local subdirectory outside of git called ~/ansible. Here is the expanded directory listing
ls ~/ansible/ bin files inventories variables |
~/ansible/bin
I’ve found that the command lines to call a playbook get somewhat large For all but the most trivial of playbooks. An example:
ansible-playbook \ -i ~/ansible/inventories/localhost.ini \ -e @~/ansible/variables/azure.yml \ -e @~/ansible/variables/ghoul.yml \ playbooks/azure.yml |
This call references four distinct variables:
- The inventory file
- the variables for defining the cluster as customized for a specific providers. These are in the azure.yml file. Yes, this could be better named.
- The variables specific to the application I am deploying
- the playbook itself.
To record the parameters used for a specific invocation, I keep these scripts in the bin directory. A naming scheme is starting to emerge:
<cloud>-<intention-<stage>.sh
For example:
azure-ghoul-build.sh
Most of these shell scripts have a minimal amount of boilerplate. For instance, since I keep an ansible.cfg checked in as part of rippowam, I want to change directory to ~/devel/rippowam prior to executing the playbook. So the overall structure looks like this:
#!/bin/sh cd ~/devel/rippowam ansible-playbook -e image_name=rhel-guest-image-7.5-1a \ -e @~/ansible/variables/vault.yml \ -e cloudname=fsi-moc -e @~/.config/openstack/clouds.yaml \ -e @~/ansible/variables/ghoul.yml \ ~/devel/rippowam/playbooks/openstack-provision.yml |
~/ansible/inventories
In the past, my inventory files have been fairly thick, including many of the variables required by the playbooks. As I reuse the inventories more and more, I have been pulling those variables out into separate variables files. Thus, the files under inventories are more simple host lists.
In addition, I’ve been trying to get my code to run against dynamic inventories as much as possible. Both Ansible and OpenStack have external python scripts that build the inventories. These code fragments are also placed in the inventories sub directory.
~/ansible/variables
When I extract variables from either a playbook or an inventory file, I put into a yaml file under the variables sub directory. These files also include any vaults I use for storing credentials
~/ansible/files
Update: I didn’t explain what this is for. Sometimes, I can’t check a file in to git due to licensing or other legal reasons. Sometimes, they are too big, like VM images. This directory is for those kinds of files.
Working with Tower
Each of the files I have above have an analogue in Tower. The shell scripts in ~/ansible/bin become the templates. The inventories become inventories. The git repos become projects. The variables go a few different places: templates, credentials, inventories.
Once the template is configured in Tower, the structure above makes it possible to continue development using my workstation. I can make and test changes locally. When I am satisfied with them, I can push them to git, and run the resync process in Tower. I find this is much more streamlined than editing code, checking it in to git, running it from tower, finding what is broken, and repeating the process. I make heavy use of the Ansible –start-at-task tag, and I would rather add and remove this from a shells script via editor than add-and-remove it from a Template. As I said at the onset, Tower is used for shared code, and I don’t want to share my templates in non-functional form.
s/more more/more/g
Nice writeup.
You also might want to add an “#ansible” tag…