Skip to content

Latest commit

 

History

History
154 lines (110 loc) · 5.62 KB

Playbooks.md

File metadata and controls

154 lines (110 loc) · 5.62 KB

Virtual Machine | Ansible | Playbooks

Although you can run ad-hoc commands in ansible, in practice, you'll largely be expected to create ansible playbooks. Ansible playbooks are essentially files formatted as yaml.

Hello Playbooks

Let's confirm our ansible/node0 VM setup still works.

ansible all -i inventory -m ping

Instead of running this on the command line, we can run this within an ansible playbook (see ping.yml).

---
- hosts: all
  gather_facts: no
  tasks:
  - name: ping all hosts
    ping:

You can run this playbook by running:

ansible-playbook ping.yml -i inventory

Commands/Modules

The simpliest way to get started is to try executing some basic tasks inside of a playbook. In examples folder, execute the commands.yml playbook.

ansible-playbook commands.yml

This will ensure a .ssh directory exists and creates a ssh key. Inspect the directory and ensure it exists. Notice that this runs on your ansible server and not your nodes. That's because the hosts in the playbook is specified as localhost.

  • Run the command again. You should see changes=0.
  • Manually delete the ssk key that was generated. Run the command again.

Variables/Loops

In examples folder, execute the loops.yml playbook. This will install git and print out a list of packages. Instead of running on your localhost, this will run on all servers in the [nodes] group. The -s option will allow the playbook to sudo as root if necessary.

ansible-playbook -i inventory loops.yml -s

Extend the example to run now install all packages defined in the packages variable.

Output/Register/Conditions

When a module is executed, you can save the results of that command using register. Further, you can use conditions to control whether a task is executed with when. You can control whether a command is considered changed, using changed_when.

For example, this command will save the output of echo into the variable out. Its changed status will change depending on whether there is a list item with z.

- action: command echo {{item}}
  register: out
  changed_when: "'z' in out.stdout"
  with_items:
    - hello
    - foo
    - bye

Mixing register, changed_when, and with_items can get tricky. Based on context, sometimes the variable saved in register will change per item during task execution. Othertimes, when all done contain a list of all items and their results. For some more details: see this example.

Ok. Check out results.yml. There is a task that downloads a file. But since it uses the shell command it doesn't know that the task has already been done. It isn't idempotent and it will wastefully download the file over and over again!

  • Change the command so that there is a task that first checks if the file already exists in /tmp. Only download when it doesn't exist by adding a when condition. Note that the it is possible to pass this option to the shell command, however, it there are some limits to this approach: creates={{dest_dir}}/{{exchange_item}}".

Templates

Templates are powerful ways to setup basic configuration settings without hard coding values. When you use a template, it will get the template, fill in any parameters, and then copy the file over to the destination.

For example, a template file, called .my.cnf.j2 containing the following:

[client]
user=root
password={{root_db_password}}
local_infile=1

Templates can be instantiated and copied to a server with the following task.

- name: copy .my.cnf file with mysql root password credentials
  template: src=templates/root/.my.cnf dest={{ ansible_env.HOME}}/.my.cnf owner={{mysql_account}} mode=0600

This can be useful for setting up complex configuration files such as apache, mysql, or jenkins.

See if you can create a new task using a template.

Vaults

It is possible to store secrets encrypted using ansible-vault. This is recommended if you need to store tokens, passwords, or ssh keys.

Content Layout/Roles

Finally, as your playbooks grow more complex in size, you will start to think about ways to organize and seperate out tasks.

Ansible describes some recommended way to organize your playbooks: http://docs.ansible.com/ansible/playbooks_best_practices.html#content-organization

An important part of organization is roles. Roles allow for you to essentially "include" in other playbooks. However, they use a particular layout to organize content.

Folder layout:

- roles/
  - setup/
    - tasks/
      - main.yml
    - templates/
      .my.cnf
- playbook.yml

An example use of roles:

---
- hosts: dbservers
  vars_prompt:
    - name: run_schema_import
      prompt: "Do import of data (schema/import)? Y: Will destory existing data. N: Will skip"
      default: "N"
  # This loads sudo password from encrypted vault
  vars_files:
    - vault/dbservers.vars
  vars: 
    - VersionBotDB: VersionsDB

  roles: 
    - { role: schema, when: run_schema_import == "Y" or run_schema_import == "y" }
    - indexes
    - import
    - users

Everything else

The ansible community supports a wide collection of modules to do amazing things. It is possible to build custom modules or programmatically interface with ansible. Learning ansible will be tricky, but the investiment can be worth it!