Ansible Playbooks are written in YAML. They describe the entire process of automation in a human-readable language. This article will delve into the fundamental core of Playbooks, further mastering the clever uses of Ansible scripts.
YAML Syntax
1. Indentation Rules
<span>YAML</span> uses spaces for indentation to represent hierarchical relationships, which is its most basic syntax rule. It is important to note that: the Tab key cannot be used, only spaces should be used. This is because the display width of <span>Tab</span> may vary across different editors, leading to parsing errors in <span>yaml</span>.
---
- name: Correct play
hosts: webservers # Correct
- name: Incorrect play
hosts: webservers # Incorrect indentation
2. Key-Value Pairs
Key-value pairs are the basic building blocks of YAML, formatted as <span>key: value</span>. There must be a space after the colon, followed by the value.
name: Install nginx # Correct
name:Install nginx # Incorrect
3. Lists (Arrays)
Format: Use a hyphen <span>- </span>(followed by a space) to indicate list items. All list items must have the same indentation.
fruits:
- Apple
- Orange
- Banana
Inline Format: You can also use square brackets <span>[]</span> for inline representation, suitable for shorter lists.<span>fruits: [Apple, Orange, Banana]</span>
4. Dictionaries
Format: Use indentation to represent multiple key-value pairs in a dictionary. In simple terms, it is a collection of key-value pairs.
user:
name: xiaoyv
uid: 1001
shell: /bin/bash
Inline Format: Use curly braces <span>{}</span> for inline representation.<span>user: {name: john, uid: 1000, shell: /bin/bash}</span>
5. Strings
Strings usually do not require quotes, but if the string contains special characters (such as <span>:</span>,<span>{</span>,<span>}</span>,<span>[</span>,<span>]</span>,<span>,</span>,<span>&</span>,<span>*</span>,<span>#</span>,<span>?</span>,<span>|</span>,<span>-</span>,<span><</span>,<span>></span>,<span>=</span>,<span>!</span>,<span>%</span>,<span>@</span>,<span>\</span>), they must be enclosed in single quotes <span>'</span> or double quotes <span>"</span>.
A small detail:
- Single quotes
<span>'</span>: Strong strings, any special characters inside will be escaped as ordinary characters. For example:<span>path: '/usr/local/binβ</span> - Double quotes
<span>"</span>: Weak strings, support escaping using<span>\</span>. For example:<span>msg: "This is a line.\nThis is another line."
</span>
Multi-line Strings:
<span>|</span>: Preserves line breaks. Suitable for writing configuration file blocks.<span>></span>: Collapses line breaks into spaces but preserves empty lines between paragraphs. Suitable for writing long commands or descriptions.
# Output will preserve line breaks and indentation.
content: |
server {
listen 80;
server_name example.com;
}
# Parsed will become one line:
# yum clean all && yum makecache
command: >
yum clean all
&& yum makecache
Playbook File Structure
A Playbook is like a blueprint for a project, defining which machines to execute tasks on, in what order, and what tasks need to be performed.
Basic Structure Example
---
# 1. Beginning of the script, YAML file identifier (optional but recommended)
- name: Description of the first Play # 2. Define a Play
hosts: group1 # 3. Core element of the Play: target hosts
vars: # 4. Core element of the Play: variables
http_port: 80
tasks: # 5. Core element of the Play: task list
- name: Install nginx # 6. A Task
ansible.builtin.package: # 7. Core of the Task: module and its parameters
name: nginx
state: present
- name: Description of the second Play
hosts: group2
tasks:
-...
Core Elements
The execution order of Playbook file elements is linear and top-down, with Ansible executing each Play in order. Within a Play, the execution order is: <span>Process hosts</span> -> <span>Gather facts</span> -> <span>Load vars</span> -> <span>Run tasks</span> -> <span>Run handlers</span>.
1. Play
A Play is a set of instructions in a Playbook targeting a specific group of hosts. A Playbook can contain multiple Plays. It includes the following core elements:
<span>hosts</span>: Target hosts/groups.<span>name</span>: Description of the Play. This description will be output by Ansible during YAML execution.<span>vars</span>/<span>vars_files</span>: Define variables or load variables from external files.<span>vars_prompt</span>: Prompt the user for variable input at runtime.<span>tasks</span>: Sequence of tasks to be executed. This is also the main body of the Play.<span>handlers</span>: Operations notified by tasks. Commonly used for restarting services, reloading configurations, etc.<span>roles</span>: Referenced roles. A way to organize tasks, variables, files, etc., grouping content by roles for reuse.<span>gather_facts</span>: Boolean value, determining whether to collect information about target hosts (such as OS, IP, hostname, etc.) at the start of the Play.
2. Task
A Task is an operation that calls a module in Ansible. In simple terms, it is Ansible’s workshop.
Core Structure of a Task:
<span>- name: </span>: Description of the task. Each value of<span>- name</span>will be output in the execution log.<span>module: parameter=value ...</span>: Module and parameters.<span>when</span>: Conditional statement. The task will only execute if the condition is met.<span>when: ansible_os_family == "Debian"</span><span>loop</span>or<span>with_<lookup_plugin></span>: Loop statement. Used to repeatedly execute a module but pass different values.
- name: Add multiple users
ansible.builtin.user:
name: "{{ item }}"
state: present
loop:
- db_user
- web_user
- app_user
<span>register</span>: Capture the output (return value) of a task and store it in a variable for use in subsequent tasks.
- name: Check the status of /etc/nginx/nginx.conf file
ansible.builtin.stat:
path: /etc/nginx/nginx.conf
register: nginx_conf_result # Assign the result returned by the module to {nginx_conf_result} variable
- name: Report status
ansible.builtin.debug:
msg: "Nginx configuration file exists!"
when: nginx_conf_result.stat.exists # Check if the file exists, if true execute debug module
3. Handler
A Handler is a special task that only executes when notified by other tasks, commonly used for service restarts and configuration reloads.
tasks:
- name: Update nginx configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/conf/nginx.conf
notify: Restart Nginx # Notify handler
handlers:
- name: Restart Nginx
ansible.builtin.service:
name: nginx
state: restarted
Small Reminder:
- The notify statement triggers the name of the handler, not the task itself. The name of the handler must be unique.
- Even if notified multiple times, it will only execute once, after all normal tasks are completed.
Logic of Ansible’s Operation
The execution order of Ansible is linear and top-down:
- Execute each Play in order
- Within a single Play:
- Process
<span>hosts</span><span> to determine target hosts</span> - Collect
<span>gather_facts</span><span> (if set to true)</span> - Load
<span>vars</span><span> variables</span> - Run
<span>tasks</span> - Finally run notified
<span>handlers</span>
Conclusion
Writing a playbook can be likened to a carefully choreographed performance. Mastering the standard YAML syntax, understanding the core elements of Playbooks, and the linear execution order will help you better navigate Ansible.
More valuable content will be continuously updated, feel free to like π, bookmark π, and share π€, thank you for your support!