Using Ansible with Heat¶
Brief summary¶
In this tutorial, we will show you how to leverage Ansible via Heat and software config to bootstrap an instance with a fully configured Nginx server.
Pre-reading¶
You should prepare a bootstrapped image according to the Bootstrapping Software Config tutorial as we will be making use of the image pre-configured with all the required agents for software config.
This tutorial borrows heavily from An Ansible Tutorial. Reading this guide will give you a good idea of what we will be installing/configuring so you can focus on how we use Orchestration to integrate with Ansible rather than using Ansible itself.
Following along¶
You will probably want to clone this repository (https://github.com/rackerlabs/rs-heat-docs/) in order to easily follow along. Once
cloned, change to the ansible
directory of the repository.
Otherwise, you may need to modify some of the commands to point to the correct locations
of various templates and/or environments. Full templates can always be found in the
templates
directory.
Basic template¶
As with all Heat templates, we start with the basic version and description sections:
heat_template_version: 2014-10-16
description: |
Deploy Nginx server with Ansible
For the parameters section, we will define a single parameter that will tell Orchestration which image to use for our server. This allows us some flexibility should the image name change or we have several to choose from:
parameters:
image:
type: string
Resources¶
Now for the details. First we create a random password for accessing the server:
server_pw:
type: OS::Heat::RandomString
Next we specify the playbook that will install Nginx:
nginx_config:
type: OS::Heat::SoftwareConfig
properties:
group: ansible
config: |
---
- name: Install and run Nginx
connection: local
hosts: localhost
tasks:
- name: Install Nginx
apt: pkg=nginx state=installed update_cache=true
notify:
- Start Nginx
handlers:
- name: Start Nginx
service: name=nginx state=started
We then use an OS::Heat::SoftwareDeployment
to tell Orchestration we want to run the playbook
on our server (which we will define in awhile):
deploy_nginx:
type: OS::Heat::SoftwareDeployment
properties:
signal_transport: TEMP_URL_SIGNAL
config:
get_resource: nginx_config
server:
get_resource: server
Finally we will define the server the playbook will run on:
server:
type: OS::Nova::Server
properties:
image: { get_param: image }
admin_pass: { get_attr: [ server_pw, value ] }
flavor: 2 GB Performance
software_config_transport: POLL_TEMP_URL
user_data_format: SOFTWARE_CONFIG
Notice that we have to specify the user_data_format
as “SOFTWARE_CONFIG” so that Orchestration
knows to set up the proper signal handling between it and the server. It is good practice
to specify software_config_transport
, and while “POLL_TEMP_URL” is the only value
supported on the Rackspace Cloud, it should also be the default for Cloud Orchestration
and can be safely omitted.
Outputs¶
The outputs defined in this template give us ready access to the results of the deployment
and show off how software config makes it easier to see the state of your configuration,
the results, and any errors or output it may have generated without having to remotely
log into your servers and search through logs. The description
property of these
outputs tells you what each represents.
outputs:
stdout:
description: Ansible Output
value:
get_attr: [ deploy_nginx, deploy_stdout ]
stderr:
description: Ansible Error Output
value:
get_attr: [ deploy_nginx, deploy_stderr ]
status_code:
description: Exit Code
value:
get_attr: [ deploy_nginx, deploy_status_code ]
server_ip:
description: Server IP Address
value:
get_attr: [ server, accessIPv4 ]
server_password:
description: Server Password
value:
get_attr: [ server_pw, value ]
Deploy the basic template¶
Before you deploy, you will need to have created an image that already has the needed agents for software config. The Bootstrapping Software Config walks you through it. Alternatively, you can use the information in that and previous tutorials to add the appropriate bootstrapping to this template.
To deploy this template, simply issue the standard command:
heat stack-create -f templates/software_config_ansible.yaml -P "image=Ubuntu 14.04 LTS (HEAT)" my_nginx_simple
Once the stack is CREATE_COMPLETE
, you can visit your new Nginx homepage by checking
the stack output for the ip and entering that into your web browser:
heat output-show my_nginx_simple server_ip
You can also check the results of the playbook by checking the other outputs:
heat output-show my_nginx_simple status_code # Ansible return code
heat output-show my_nginx_simple stdout # Ansible output
heat output-show my_nginx_simple stderr # Error details (if any; should be empty)
Advanced Template with Roles¶
While the basic template gives a good idea of how Orchestration integrates with Ansible, we will look at a slightly more advanced usage leveraging Ansible roles. We will tweak the previous template a small amount, so make a copy and call it “software_config_ansible_role.yaml”.
The role and its components can be found in this repository (https://github.com/rackerlabs/rs-heat-docs/) under the roles
directory.
New resources¶
We will add two new resources to pull down the role we want to use and put it in a place Ansible can access it:
pull_role_config:
type: OS::Heat::SoftwareConfig
properties:
group: script
config: |
#!/bin/bash
git clone https://github.com/rackerlabs/rs-heat-docs.git
cp -r rs-heat-docs/ansible/roles /etc/ansible/roles
# needed dependency by one of the Ansible modules
apt-get install -y python-pycurl
This is a simple script that clones this repository and copies the role to the right place. It also installs a dependency needed by one of the modules used in the role.
We’ll also deploy that script to the server:
deploy_role:
type: OS::Heat::SoftwareDeployment
properties:
signal_transport: TEMP_URL_SIGNAL
config:
get_resource: pull_role_config
server:
get_resource: server
Modify playbook¶
Since we’re using roles to do all of the heavy lifting, we will modify our nginx_config
resource to simply apply the role:
nginx_config:
type: OS::Heat::SoftwareConfig
properties:
group: ansible
config: |
---
- name: Apply Nginx Role
hosts: localhost
connection: local
roles:
- nginx
We will also need to modify the deployment of the playbook to depend on the deploy_role
resource, since we will need the role installed before we can apply it:
deploy_nginx:
type: OS::Heat::SoftwareDeployment
depends_on: deploy_role
properties:
signal_transport: TEMP_URL_SIGNAL
config:
get_resource: nginx_config
server:
get_resource: server
Modify outputs¶
Our script for pulling the role definition is not very sophisticated. We are not
capturing or writing any output, but we can examine the exit code of our script. We will add
that to the outputs
section so we can check it if we need to:
role_status_code:
description: Exit Code returned from deploying the role to the server
value:
get_attr: [ deploy_role, deploy_status_code ]
Deploy the advanced template¶
Deploying the new template is the same as above, we just change the template name:
heat stack-create -f templates/software_config_ansible_role.yaml -P "image=Ubuntu 14.04 LTS (HEAT)" my_nginx_role
We can also check outputs the same way, by simply changing the stack name:
heat output-show my_nginx_role status_code # Ansible return code
heat output-show my_nginx_role stdout # Ansible output
heat output-show my_nginx_role stderr # Error details (if any; should be empty)
heat output-show my_nginx_role role_status_code # Exit code of the role script