# Ansible integration
Ansible integration into Cycloid pipeline is made easier by a script provided in cycloid/cycloid-toolkit (opens new window) docker image, called ansible-runner
.
Ansible runner is a wrapper of ansible-playbook
command, which can be configured with several environment variables to simplify Ansible's integration into a Pipeline and provide additional functions.
A complete example of usage in a Cycloid pipeline can be found in pipelines-examples
# Standard usage
# Dynamic inventory
The ansible runner script by default will detect which cloud provider dynamic inventory (opens new window) plugins to find servers based on the environment variables you provided.
The script currently support the detection for the following dynamic inventories:
- Amazon EC2 inventory (opens new window)
- GCP inventory (opens new window)
- Azure inventory (opens new window) with ansible >= 2.8
- Azure Resource Manager inventory script (opens new window) with ansible <= 2.7
TIP
More dynamic inventories will be added to the ansible-runner
in the future, but if you need one that is not yet supported, you can:
- Search for existing inventory plugins (opens new window) and scripts (opens new window)
- Develop your own dynamic inventory (opens new window)
Then:
- Add it by extending our
cycloid/cycloid-toolkit
docker image - Add it on the run by customizing the ansible-runner task
- Contribute it to our
ansible-runner
script here (opens new window)
It's up to you to configure your playbook to target your instances based on exclude and include groups (opens new window) that are automatically defined by the dynamic inventory such as the cloud provider name, region or based on tags.
Now if we had to run, for example, ansible-playbook -e project=owl -e env=demo
with this playbook, we could define the following hosts
filter:
- hosts: tag_role_front:&tag_project_{{project}}:&tag_env_{{ env }}:!tag_packer_build_true
...
2
Ansible will run the playbook on instances matching the project=owl
and env=demo
tags but exclude those with the tag packer_build=true
.
If your servers are located in a private network, ansible-runner
can work with the Bastion host (opens new window) approach.
In an Amazon Web Services (AWS) context, a bastion host is defined as "instances that sit within your public subnet and are typically accessed using SSH or RDP. Once remote connectivity has been established with the bastion host, it then acts as a "jump" server, allowing you to use SSH or RDP to log in to other instances (within private subnets) deeper within your VPC. When properly configured through the use of security groups and Network ACLs (NACLs), the bastion essentially acts as a bridge to your private instances via the internet."
If you're interested, you can read more about this concept on AWS documentation:
- https://docs.aws.amazon.com/quickstart/latest/linux-bastion/overview.html (opens new window)
- https://aws.amazon.com/blogs/security/tag/bastion-host/ (opens new window)
TIP
By default the configuration of ansible-runner
will use the private IP address to connect to instances.
If you do not use a bastion server, you might want to add the following configuration environment variables to use public IPs:
- Amazon EC2:
AWS_EC2_COMPOSE_ANSIBLE_HOST=ip_address
- Azure:
AZURE_USE_PRIVATE_IP=False
- GCP:
GCP_USE_PRIVATE_IP=False
You can see more configuration options for the ansible-runner
script here (opens new window).
Tips: If you would like to have a glimpse into how the dynamic inventory plugin or script is organizing your instances into groups, you can use the ansible-inventory
command line:
run:
path: /bin/bash
args:
- '-exc'
- |
/usr/bin/ansible-runner-inventory
# Same way you would run the ansible runner
# /usr/bin/ansible-runner
2
3
4
5
6
7
8
9
# Static inventory file
If you're not using Ansible's dynamic inventory and still want to employ our ansible-runner, you can provide a static inventory file. To do this, simply specify the location of this file using the following environment variable: ANSIBLE_INVENTORY
(opens new window).
You have the flexibility to place the inventory file directly within your stack or configuration Git repository. Alternatively, you can generate it dynamically within the pipeline. Typically, in our stack examples, you'll find the file located under the following directory: ANSIBLE_INVENTORY: inventory
where by default relative path refer to ANSIBLE_PLAYBOOK_PATH
# Use Cycloid credentials variables with Ansible
As described in pipeline variables the easiest way is to pass variables through the pipeline. The public Magento stack gives a good example by providing AWS credentials and SSH key to ansible runner : pipeline.yml (opens new window)
To extend a bit this example, we can create a Cycloid custom credential called mysecret
with a field foo
. And pass it to Ansible as variable :
Then provide an extra Ansible variables called secret_foo
with EXTRA_ANSIBLE_VARS
:
- task: ansible-runner
<<: *run-ansible
params:
SSH_PRIVATE_KEY: ((bastion_private_key_pair))
...
AWS_SECRET_ACCESS_KEY: ((aws_secret_key))
EXTRA_ANSIBLE_VARS:
secret_foo: ((custom_mysecret.foo))
2
3
4
5
6
7
8
# Use Terraform outputs as Ansible variables
This topic is handled in variables-sharing section
# Environments variables of ansible runner
To find out more about all the environments variables you can use to configure ansible-runner, please refer to the README of the repository (opens new window).