Ansible playbooks for complex tasks
An Ansible playbook is a YAML file that contains all the instructions
that Ansible should complete during a run. For the purposes of this
exercise, I will not get into more advanced topics such as Roles and
Templates. If you are interested in learning more, the
documentation is a great place to start.
In the previous section, I encouraged you to use the ssh-copy-
id command to propagate your SSH keys; however, this article is
focused on how to accomplish tasks in a consistent, repeatable
manner. Example 4 demonstrates one method for ensuring, in an
idempotent fashion, that an SSH key exists on the target hosts.
Example 4: Ansible playbook "push_ssh_keys.yaml"
---
- hosts: all
gather_facts: false
vars:
ssh_key: '/root/playbooks/files/laptop_ssh_key'
tasks:
- name: copy ssh key
authorized_key:
key: "{{ lookup('file', ssh_key) }}"
user: root
In the playbook from Example 4, all of the critical sections are
highlighted.
The - hosts: line indicates which host groups the playbook should
evaluate. In this particular case, it is going to examine all of the
hosts from our Inventory.
The gather_facts: line instructs Ansible to attempt to find out
detailed information about each host. I will examine this in more
detail later. For now, gather_facts is set to false to save time.
The vars: section, as one might imagine, is used to define variables
that can be used throughout the playbook. In such a short playbook
as the one in Example 4, it is more a convenience rather than a
necessity.
Finally the main section is indicated by tasks:. This is where most of
the instructions are located. Each task should have a - name:. This
is what is displayed as Ansible is carrying out a run, or playbook
execution.
The authorized_key: heading is the name of the Ansible Module
that the playbook is using. Information about Ansible Modules can
be accessed on the command line via ansible-doc -a; however it
may be more convenient to view the documentation in a web
browser. The authorized_key module has plenty of great examples
to get started with. To run the playbook in Example 4, simply use
the ansible-playbook command:
ansible-playbook push_ssh_keys.yaml
If this is the first time adding an SSH key to the box, SSH will prompt
you for a password for the root user.
Now that your servers have SSH keys propagated its time to do
something a little more interesting.
Ansible and gathering facts
Ansible has the ability to gather all kinds of facts about the target
system. This can consume a significant amount of time if you have a
large number of hosts. In my experience, it can take 1 to 2 seconds
per host, and possibly longer; however, there are benefits to fact
gathering. Consider the following playbook used for turning off the
ability for users to log in with a password as the root user:
Example 5: Lock down root SSH account
---
- hosts: all
gather_facts: true
vars:
tasks:
- name: Enabling ssh-key only root access
lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin without-password'
notify:
- restart_sshd
- restart_ssh
handlers:
- name: restart_sshd
service:
name: sshd
state: restarted
enabled: true
when: ansible_distribution == 'RedHat'
- name: restart_ssh
service:
name: ssh
state: restarted
enabled: true
when: ansible_distribution == 'Debian'
In Example 5 the sshd_config file is modified with
the conditional only executes if a distribution match is found. In this
case Red Hat-based distributions name their SSH service different
than Debian-based, which is the purpose for the conditional
statement. Although there are other ways to achieve this same
effect, the example helps demonstrate Ansible facts. If you want to
see all of the facts that Ansible gathers by default, you can run
the setup module on your localhost:
ansible localhost -m setup |less
Any fact that is discovered by Ansible can be used to base decisions
upon much the same way the vars: section that was shown in
Example 4 is used. The difference is Ansible facts are considered to
be built in variables, and thus do not have to be defined by the
administrator.