Ansible is very flexible automation tools with many benefits. The free version is command-line based and here is an example to set it up.
Environment setup
- Ansible 2.8 is required or some command may not work.
- Ansible files (including playbooks, tasks and inventory files) are all located in /home/glowing/ansible
- Default inventory file needs to be referenced in Ansible configuration /etc/ansible/ansible.cfg. This ensures ansible or ansible-playbook command can pick up hosts or host patterns without requiring inventory file through -i on every execution. Here is what the inventory config looks like in ansible.cfg:
[defaults]
# some basic default values...
inventory = /etc/ansible/hosts,/home/glowing/ansible/inventories/glowing_inventory.yml
host_key_checking = False
- As best practice, servers involved should be able to ssh to each other on RSA key authentication. This can be achieved by adding a separate authorized keys file and reference it from /etc/ssh/sshd_config, at the line starting with AuthorizedKeysFile, and separated with the file name of existing authorized keys with a space. In this way, you may keep public keys of human user in one authorized key file and the public keys of machines in the other.
- Build inventory file in ~/ansible/inventories/glowing_inventory.yml. The inventory file can declare some variables to use across hosts. If password is involved (e.g. synchronize module still requires password), it can be stored here with base64 encoded. Here is an example of glowing_inventory.yml
---
all:
vars:
ansible_user: glowing
gh_sudo_pass: qGS0bWVuu3Jr
gh_dir: /opt/glowing/etc
tmp_dir: /tmp
children:
dc1_front_end:
hosts:
e9a-ghfe01:
e9a-ghfe03:
e9a-ghfe05:
e9a-ghfe07:
e9a-ghfe09:
dc2_front_end:
hosts:
e9a-ghfe02:
e9a-ghfe04:
e9a-ghfe06:
e9a-ghfe08:
e9a-ghfe10:
dc1_back_end:
hosts:
e9a-ghbe01:
e9a-ghbe03:
e9a-ghbe05:
dc2_back_end:
hosts:
e9a-ghbe02:
e9a-ghbe04:
e9a-ghbe06:
dc1_database:
hosts:
e9a-ghdb01:
e9a-ghdb03:
e9a-ghdb05:
dc2_database:
hosts:
e9a-ghdb02:
e9a-ghdb04:
e9a-ghdb06:
That is the basic steps to set up Ansible. Now we can run adhoc commands. The command below allows me to copy a file from executing server to all destination servers that match a pattern:
# ansible 'dc*_back_end:!'`hostname -s` -e "file_name={{gh_dir}}/test.zip" -m copy -a "src={{file_name}} dest={{file_name}}"
In this command:
- variable {{gh_dir}} is declared in the inventory file. It must be referenced by placing variable name between double curly bracket;
- An extra variable {{file_name}} is declared at run time because this is the dynamic part of the command;
- This adhoc ansible command uses copy module. With copy module, the src anddest files are in the same absolute path here so we use this variable to save some typing;
- reference to the host support wildcard such as dc*_back_end;
hostname -s
returns the host name of the server where the adhoc command is run- :! excluds the running host from being matched as destination server. this is in case that running machine is already in the dc*_back_end group, where copy source and destination are identical
Here is another example for deleting a file from destination servers:
# ansible dc2_database -e "fn=/tmp/file_to_delete" -m file -a "path={{fn}} state=absent"
If we can run adhoc command, then we can start writing some playbook and roles. Below is a simple playbook test-conn.yml to ping each server:
---
- name: measure mint retrieval time from {{ ansible_limit }}
hosts: '{{ ansible_limit }}'
serial: 1
order: sorted
gather_facts: no
ignore_errors: yes
tasks:
- name: measure time
command: curl -s -XGET http://{{ inventory_hostname }}:8080/index.html -o /dev/null
delegate_to: localhost
register: curlout
no_log: true
- name: display result
debug:
msg: "Time to load webpage from {{ inventory_hostname }} is {{ curlout.delta }}."
Then you can run that playbook with the following command:
# ansible-playbook -l dc2_front_end test-conn.yml
Ansible automation is essentially editing yaml files for playbooks. Writing playbook involves a lot of module interaction and one needs to follow best practices. Understanding Ansible roles can help reuse some code.
In addition here are some common playbook keywords you should be familiar with:
- serial
- order
- gather_facts
- ignore_errors
- when
- run_once
- local_action
- register
Here are common modules to know
- set_fact
- state
- touch
- fail
- synchoronize
- lineinfile