Table of Contents

Ansible

General Information

Ansible is a tool for performing remote tasks on systems. (either ad-hoc or via “playbooks”)

You will need to use ansible as a user that has ssh keys setup on systems so you are not prompted for passwords during parallel command operations.


If you already have Ansible installed/configured, playbook downloads can be found here.

Checklist


Install

Ansible comes in many distributions repos already.

CentOS 7

yum install ansible

Configure

Main Ansible config file

Repo Controlled

It is highly recommended to put Ansible playbooks, roles, and inventory into version control. (Example: git or svn)

One suggested directory structure/workflow is:


Model content tree under /ansible/ after Ansible's best practices alternative structure.


Inventory

Inventory setup is the most important configure task.


In order for Ansible to send commands to systems, they must be listed in inventory.


Suggested directory structure (after Ansible's best practices alternative structure)

Auto Generated Inventory

You will not want to introduce a manual inventory process.

Suggested workflow for auto generating your inventory files:


Ansible Commands

Examples of Ansible commands.

Note: All host-patterns check the inventory files for matches ONLY. If a system is not in the inventory file(s), Ansible can't send a command to it.

General Ansible command syntax

ansible <host-pattern> [-m module-name] [-a arguments] [options]

List Hosts

Listing hosts matched by the given pattern and do nothing else.


List hosts in the webservers_nginx group from dev inventory

ansible webservers_nginx -i /ansible/inventories/development/hosts --list-hosts


List all hosts from dev inventory

ansible all -i /ansible/inventories/development/hosts --list-hosts


List all hosts in the “webservers_nginx” group (from any inventory)

ansible webservers_nginx --list-hosts


List all hosts matching “web*” pattern (from any inventory)

ansible "web*" --list-hosts

Test Connection

The module 'ping' is not an ICMP echo command; it tests a remote login (ssh) to the system and verifies a working remote python environment.


Test connection to webservers_nginx in dev inventory only

ansible webservers_nginx -i /ansible/inventories/development/hosts -m ping


Test connection to all systems in dev inventory

ansible all -i /ansible/inventories/development/hosts -m ping


Test connection to all webservers_nginx (from any inventory)

ansible webservers_nginx -m ping


Test connection to all systems in the “webservers_nginx” group (from any inventory)

ansible webservers_nginx -m ping


Test connection to systems matching a pattern (from any inventory)

ansible "web*" -m ping


Test connection to all systems (from any inventory)

ansible all -m ping

Ad-Hoc Commands

Ad-hoc commands are for one off commands that are not saved in a playbook.


Modules: Command and Shell

If no module is specified, the “command” module is used.


Check uptime of the group 'webservers_nginx' from dev only

ansible webservers_nginx -i /ansible/inventories/development/hosts -a 'uptime'


Check uptime of all systems in dev

ansible all -i /ansible/inventories/development/hosts -a 'uptime'


Check uptime of the group 'webservers_nginx' (from any inventory)

ansible webservers_nginx -a 'uptime'


Check the last 10 lines in /var/log/messages (using sudo)

ansible "web*" -a 'tail /var/log/messages' -b

Equivalent command as the above

ansible "web*" -a 'sudo tail /var/log/messages'


Piping example; the shell module must be specified

ansible "web*" -m shell -a 'cat /var/log/messages | grep -i error' -b

Modules: Copy and File

Transferring files over scp using Ansible to multiple servers at once.


Copy a local file (src=) to all systems in the 'webservers_nginx' group (dest=)

ansible webservers_nginx -m copy -a "src=/etc/yum.conf dest=/tmp/yum.conf"


Set a file's ownership and permissions

ansible webservers_nginx -m file -a "dest=/tmp/yum.conf mode=750 owner=root group=root"


Remove a file

ansible webservers_nginx -m file -a "dest=/tmp/yum.conf state=absent"

Modules: Packages

Managing packages with Ansible.


Ensure a package is installed, do not update the package if it is installed

ansible my_group -m yum -a "name=dstat state=present"


Ensure package is the latest version (update if not)

ansible my_group -m yum -a "name=dstat state=latest"


Ensure package is not installed (remove if it is)

ansible my_group -m yum -a "name=dstat state=absent"

Modules: Services

Managing system services with Ansible.

Compatible with SysV and Systemd.


Ensure httpd is started (start if not)

ansible my_group -m service -a "name=httpd state=started"


Restart a service

ansible my_group -m service -a "name=httpd state=restarted"


Ensure a service is stopped

ansible my_group -m service -a "name=httpd state=stopped"

Ansible Playbooks

“Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.”

More Details: http://docs.ansible.com/ansible/playbooks.html


Playbook Directory Structure

Playbooks should be repo controlled.

Following the examples on this page:


Playbooks map ansible groups to roles


Gather a subset of facts

If you do need to gather facts, consider gathering a subset of facts instead of everything in order to keep the fact collection fast.

Available Fact Subsets:


See the Roles section for what happens next.


Roles Directory Structure

Roles contain all of the tasks that will be run when a playbook is executed against it.


Roles should be repo controlled. Top level directory example is:

An example role called “webservers-nginx” is located:

The contents of a role directory are:


Playbook/Role Creation

How to create a new playbook and role.

External References

  1. Navigate to your local copy of the version controlled ansible repo. Example:
    cd ${HOME}/repos/ansible/
  2. Update your local copy of the version controlled ansible repo to the latest version
    #git
    git pull
     
    #svn
    svn update
  3. New Role
    1. Navigate to the roles directory, then copy your role template directory to a new name
      cd roles/
      cp -R template-role/ my-new-role
    2. Modify the role's files as needed to create tasks, files, handlers, etc.
      1. Download zip archive of an example role template.
  4. New Playbook
    1. Navigate to the playbooks directory
      cd ${HOME}/repos/ansible/playbooks/
    2. Copy your playbook template to a new playbook yaml file.
      cp TEMPLATE_PLAYBOOK.yml my_new_playbook.yml
      1. Playbook Template
        TEMPLATE_PLAYBOOK.yml
        # File: TEMPLATE_PLAYBOOK.yml
        # Description: PLAYBOOK DESCRIPTION HERE
        # Last Updated: 2018-03-15
        # Recent Changes:-Initial release
         
        # hosts: group_name or 'all'
        - hosts:
            - group_name_here
         
          # roles: located in ../roles/
          roles:
            # role: role to assign to hosts, tags: tag(s) to give entire role
            - { role: role-name, tags: tag-name }
         
          # Do not gather host facts for this playbook (comment out/remove if you need facts)
          gather_facts: no
    3. Edit the new playbook (vim ansible/playbooks/my_new_playbook.yml)
      - hosts: my_ansible_group
        roles:
          - { role: my-new-role, tags: my-new-role }
      1. In the above example, the playbook “my_new_playbook” states that the group “my_ansible_group” has the role of “my-new-role”, and all tasks in the role “my-new-role” has the tag “my-new-role”
        1. The tag can be anything, but keeping it the same as the role name is useful if you want to limit the execution of a playbook to a specific role using the “tags” command line argument to ansible-playbook
        2. Tags are inherited at all tasks below it.
      2. When the playbook is executed, the tasks defined in the role will be executed against the group
  5. Test Playbook
    1. See the next section for details on testing the playbook before committing changes to a repo.

Playbook Testing

Test your playbook before committing it to a repo.


Playbook Commands

Different methods to run playbooks.


WARNING: If you do NOT specify an inventory file with “-i PATH”, the playbook will run against ALL HOSTS in the group, which is probably not what you want.


NOTE: If you need to use group_vars per inventory type (dev/test/prod), the full path to the inventory file needs to be used. (Example: /ansible/inventories/development/hosts )


Playbook Commands: Syntax Check

After creating a playbook, it is useful to check the syntax before running it to catch obvious errors.

Run a syntax check (will NOT execute the playbook)

ansible-playbook --syntax-check /ansible/playbooks/my_playbook.yml

Playbook Commands: Aliases

Playbook commands can get rather long, some useful aliases to shorten them.

Put in your ~/.bashrc or ~/.zshrc file

# Ansible aliases
alias apd='ansible-playbook -b -i /ansible/inventories/development/hosts'
alias apt='ansible-playbook -b -i /ansible/inventories/systest/hosts'
alias app='ansible-playbook -b -i /ansible/inventories/production/hosts'


Additionally, create a symlink to playbooks

ln -s /ansible/playbooks /playbooks


Now, your playbook commands can look like this

# Dev inventory
apd /playbooks/myplaybook.yml
 
# Test inventory
apt /playbooks/myplaybook.yml
 
# Prod inventory
app /playbooks/myplaybook.yml

Playbook Commands: List

Preparation/sanity check commands to do before running a playbook.


List what hosts the playbook will run against (from dev inventory)

ansible-playbook -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --list-hosts


List what tasks the playbook will execute (from dev inventory)

ansible-playbook -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --list-tasks

Playbook Commands: Run

Commands to actually run a playbook. You SHOULD do the list commands first to make sure what you are about to run is expected.


Run playbook (dev env; all in group) against all system groups defined in playbook from dev inventory using sudo for privilege escalation

ansible-playbook -b -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml


Run playbook (dev env; all in group; only configure) against all groups defined in playbook from dev inventory using sudo for privilege escalation, only execute actions with the matched tags “configure”

ansible-playbook -b -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --tags configure


Run playbook (dev env; range of systems) against all groups defined in playbook from dev inventory using sudo for privilege escalation, further limit to hosts web01-05“

ansible-playbook -b -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --limit "$(echo web{01..05})"


Run playbook (dev env; one system) against all groups defined in playbook from dev inventory, limit to a single hostname (MYHOSTNAME)

ansible-playbook -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --limit MYHOSTNAME