My previous post, An Alternative Approach to DevOps Deployment , details my personal experience using Ansible and its advantages over other tools. In this article, I will give an overview of how to create an Ansible project and application deployment mechanism using Go Pipeline.
Basic Structure of an Ansible Project
As part of the deployment script, we must define the Ansible structure first. In the structure, we need to define staging, production, group_vars, host_vars and roles:
- The staging file will keep all test environments information
- The production file will keep all production and Disaster Recovery (DR) environments information
- All application server details should be mentioned in host_vars
- All variables used in Ansible need to be furnished in group_vars
- All templates, files and tasks are defined in roles
Finally, we need to define a wrapper Ansible playbook to execute the roles. Under one wrapper playbook, the number of roles that will execute depends on developer needs or the project requirements. In the following subsections, I will explain each and every component of an Ansible project (Figure 1).
Figure 1: Basic structure of an Ansible project
Inventory plays an important role in identifying which server we will need to deploy the application using Ansible. As a best practice, it is always good to use a separate inventory for pre-production (i.e. test environments and production environment application server details). As a standard, we use it to maintain Staging and Production Ansible inventory for test and production servers respectively.
Group Variables (group_vars)
Group variables contain all environmental variables as well as common variables. This is the place where we can store all template variables for each environment. While running an Ansible playbook, we will specify a limit, and based on that, Ansible will use the appropriate group variables.
Host Variables (host_vars)
All the application servers’ IP addresses are stored in host_vars. In the runtime based on the inventory and limit environments, Ansible will identify the application server details from host_vars.
Vault is a password-protected file where deployment engineers store all clear text passwords. Vault has the capability to use its own encryption to protect our passwords. These passwords might include a deployment user password, service account password, database password, and a web service password. We can use ansible-vault create or edit for creating and modifying a vault respectively.
The application deployment process always follows a set of sequential instructions. In Ansible, each instruction has been defined under a role by the software engineers. Each role consists of three components: tasks, templates and files.
Tasks mainly perform a set of operations, which completely align with the roles objective. In order to perform the tasks, external files are kept under the files directory, and templates are kept under the templates directory. All operations under a particular task are furnished in the main.yml file.
For each application, all the environments have some common files. Some attributes of those common files are different based on their environment. We use templates to handle different environments with minimal changes. For example, say we have a database connection string defined in a file and that file must be deployed in all environments, but the database name in each environment is different. In that situation, the deployment engineer would create a template and keep the database name as a variable, and that variable defined under each environment group_vars along with their proper database name.
Any type of file used by a task is kept under that task role directory. It may be any executable like .sh, .exe, .dat or a simple .txt file. An example of the basic structure of an Ansible project is illustrated in Figure 2:
Figure 2: Example of an Ansible project file structure
Establishing Connectivity with Various Servers
One of the most important prerequisites of an Ansible deployment is connecting it with other systems like application servers and version control systems (SVN, Bitbucket, Serena Dimension, Visual Source Safe, etc.)
Figure 3: Connectivity with various servers
We need to establish connectivity between the version control server and the Ansible server to get the application components. We also need to deploy those source components into an application server by building connectivity between the Ansible server and the application server. In general, SSH is used for Red Hat Enterprise Linux (RHEL) system connectivity and NTLM or Kerberos is used for Windows systems. An illustration of various server connections is given in Figure 3.
Mechanism to Run an Ansible Playbook
There are many parameters we need to consider while running an Ansible playbook. Consider a case where the developers have developed all the Ansible roles and also created some wrapper .yml files, which contain a set of roles to be executed as part of a particular deployment. The deployment engineer will run the wrapper as per their objective (deploying applications, properties, keystores, etc.)
Here is a generic Ansible playbook run format to use:
ansible-playbook -i <inventory> app-deploy.yml –limit <environment> –extra-vars ‘bitbucket_tagged_version= <version>’ –vault-password-file ~/.vault.app.pwd
In the above run format we need to replace:
- <inventory> with staging or production
- <environment> with DEV, INT or SYS or UAT or PROD (see Figure 4)
- extra-vars with the actual variable name along with the actual value
- vault-password-file with the actual file name
Figure 4: Deployment workflow
For example, assuming we are planning to deploy our application to production, use the below playbook run command for our PROD deployment:
ansible-playbook -i production app-deploy.yml –limit prod –extra-vars ‘bitbucket_tagged_version=master’
In our project, we kept our source properties file in Bitbucket, our application .war file in Nexus and all server properties for each environment were maintained in SVN. Ansible allows us to handle this situation by writing our roles such a way that while executing a deploy app playbook, Ansible will get: the properties from Bitbucket; .war from Nexus; and environment properties from SVN, and deploy them in the actual server. Figure 4 above shows the deployment workflow for such an application.
Procedure to Integrate Ansible with UI Applications
Go Pipeline is an extensively used open-source GUI tool for Ansible deployments. As a Go Pipeline admin, you need to first configure the application in Go Pipeline, and then set up a schedule or run it manually. Any command that can be issued via the Ansible command line can be configured via the UI in Go Pipeline (see Figure 5). For each command, you can explicitly define all the variables in Go Pipeline.
Figure 5: Ansible integration with Go Pipeline
Once configured in Go Pipeline, you just need to click on the play button of test-deploy or prod-deploy in application-pipeline to deploy the application in the application server (Figure 6).
Figure 6: Partial screen of Go Pipeline
I hope this two-part series has helped you gain a basic understanding of DevOps deployment using Ansible and Go Pipeline. Given the advantages Ansible provides over other tools used by leading organisations, I encourage you to learn more about this alternative approach.