Ansible Concepts
External
- https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html
- http://docs.ansible.com/ansible/glossary.html
Internal
Overview
Ansible is a configuration management and provisioning tool, similar to Chef, Puppet or Salt. What sets it aside is that it does not require agents on the hosts it configures - it only requires ssh access and sudo. The target hosts are specified in an inventory file, located on the "ansible host", the machine that is use to conduct operations from. Then ansible is executed on that host. During the execution, ansible connects via SSH to the target hosts, gets the context and executes tasks being cognizant of the context. This allows tasks to be idempotent. In the beginning, the inventory can be probed for availability for running a ping module:
ansible -i ./hosts.yaml <group-name|all> -m ping
The idempotence of tasks comes from the idempotence of their components, the modules. Modules are also aware of the facts of the context.
Multiple tasks are grouped together in playbooks. A playbook is executed with the ansible-playbook command.
Inventory File
Ansible works against multiple systems at the same time. It does this by selecting portions of systems listed in Ansible’s inventory file. The default location of the inventory file is /etc/ansible/host, but it can be placed anywhere and referred from the command line with:
-i <path>
The conventional name is hosts.yaml.
Inventory File Structure
host1.example.com [webservers] web1.example.com web2.example.com [dbservers] db1.example.com db2.example.com
Groups
The headings in brackets are group names, which are arbitrary strings used in classifying systems and deciding what systems you are controlling at what times and for what purpose. A host can be part of more than one group.
Default Groups
There are two default groups: "all" and "ungrouped". "all" contains every host. "ungrouped" contains all hosts that don’t have another group aside from "all".
Recursive Groups
Recursive groups are declared with the [<group-name>:children].
[A] host1 host2 [B] host3 host4 [AandB:children] A B [AandB:vars] something=something-else
Dynamic Inventory
Playbook
Playbooks are YAML files that contain one or more "plays" in an ordered list. Each play executes part of the overall goal of the playbook. Each play includes at minimum two things:
- the managed hosts to target.
- at least one task, possible more than one, to be executed against the target hosts.
Optionally, a playbook may include:
- variables, under the "vars." subtree.
- roles, under the "roles." subtree. All roles specified here are are assigned to the configured hosts. If a list of roles is provided in a play, it is said that the roles are used "at the play" level, meaning that their tasks are added to the play.
- remote_users.
- pre_tasks.
- etc.
---
- name: play one
hosts: all
become: yes
become_user: root
vars:
some_var: something
pre_tasks:
- import_tasks: tasks/some_tasks.yml
roles:
- kubernetes-local-storage
tasks:
- name: Install Nginx
apt:
name: nginx
state: installed
update_cache: true
- name: play two
hosts: ...
tasks:
- ...
import_playbook
A playbook can include other playbooks:
---
- import_playbook: some-other-playbook.yml
ansible-playbook
A playbook is executed with "ansible-playbook" command:
ansible-playbook -i ./hosts.yaml <playbook-name>.yaml
Task
A task combines an action (a module and its arguments) with a name and optionally some other keywords like looping directives. Handlers are also tasks, but they do not run unless they are notified by name when a task reports an underlying change on a remote system. Playbooks exist to run tasks.
Ansible tasks are idempotent, they can be safely run repeatedly. Idempotence is achieved by the fact that ansible first gathers the context, which consists of facts, before running the tasks. Ansible "checks the facts" first to decide whether it needs to change anything. If the outcome it seeks is already achieved, the task is not executed.
- name: Create some directories
file:
path: "{{ item }}"
state: directory
owner: ec2-user
when: inventory_hostname in groups['blue']
become: true
with_items:
- "/tmp/a"
- "/tmp/b"
- "{{ some_dir_variable }}"
Task Configuration
name
A task identifier that can be used for documentation.
vars
A map of variables.
become
Boolean that controls if privilege escalation is used or not on task execution. Implemented by the [[ Template:Ansible Privilege Escalation:
- name: Download the latest Amazon Corretto {{ jdk.version }}
get_url:
url: https://corretto.aws/downloads/latest/{{ amazon_corretto_package_name }}
dest: /tmp/{{ amazon_corretto_package_name }}
Registered Variables
Variables can be created from the output of Ansible tasks, which is "registered" as a variable with the task keyword register
. Variables registered as such can be used by any later tasks in the play. Registered variables may be simple variables, list variables, dictionary variables, or complex nested data structures. Registered variables are stored in memory. Registered variables cannot be cached for use in future plays. Registered variables are only valid on the host for the rest of the current playbook run. Registered variables are host-level variables.
Examples:
Host File Variables
Inventory File Variables
Group Variables
Group variables are declared with [<group-name>:vars] in the inventory file. If they are declared this way, the variables apply to an entire group at once.
[group-A] host1 host2 [group-A:vars] something=something-else
Host Variables
Variables that apply to a specific host are declared in the inventory file after the host name:
[group1] host1 http_port=80 maxRequestsPerChild=808 host2 http_port=303 maxRequestsPerChild=909
Filters and Data Manipulation
Ansible file content can be manipulated with filters. TODO: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#manipulating-strings
Fact
Before running any tasks, Ansible will gather information about the system it is provisioning. These are called facts. Facts are pieces of information about remote nodes: system and environment information. Facts are used in playbooks, tasks and templates just like variables, but they are inferred, rather than set, during automatic discovery when running plays, by executing the internal setup module on the remote node. Ansible facts all start with anisble_ and are globally available for use any place variables can be used: variable files, tasks, and templates.
Facts can also be explicitly with the set_fact module.
Directives
notify
register
tasks:
- name: Add Nginx Repository
apt_repository:
repo: ppa:nginx/stable
state: present
register: ppastable
You can register the results of a modules action as well, and use the variable defined in register
to conditionally perform actions when based on the registered variables values. For example, registering the result of the command run via the shell module can let you access the stdout of that command.
when
tasks:
- name: Install Nginx
apt:
pkg: nginx
state: installed
update_cache: true
when: ppastable|success
notify:
- Start Nginx
Template
A template is a file to be installed on the target system after the declared variables are substituted with actual values. Variable values may come from the inventory file, host variables, group variables, or facts. Templates use the Jinja2 template engine and can also include logical constructs like loops and if statements.
Jinja2 Templating
Vault
Privilege Escalation
Keywords: become, sudo, su, root: