Playbooks in Ansible
Playbooks in Ansible are the main tool of Ansible. A playbook consists of one or more games (plays), each of which, in turn, contains tasks (tasks). These tasks are performed sequentially, allowing you to create complex but easy to read automation scripts.
In this article we will look at how to work with playbooks in Ansible.
Writing playbooks
We already know that Yaml is used to write playbooks in Ansible. Basic rules of YAML syntax:
Padding: YAML uses indentation to determine the level of nesting. Typically spaces are used rather than tabs.
Key-value: each line is a key-value pair separated by a colon.
Lists: lists of elements are denoted by a hyphen (-).
Example of a basic YAML document:
name: Ivan
age: 30
address:
street: 123 Main St
city: Anytown
state: CA
phone_numbers:
- type: home
number: 123-456-7890
- type: work
number: 987-654-3210
Ansible playbooks consist of the following basic elements:
Header: Defines general information about the playbook, such as name and target hosts.
Variables: are used to store data that can be reused in the playbook.
Tasks: define specific actions that must be performed on hosts.
Handlers: are performed when the system state changes, for example, restarting a service after a configuration update.
Conditionals: allow you to perform tasks only when certain conditions are met.
Let's look at a basic playbook that installs and configures the Apache web server:
---
- name: Установка и настройка Apache
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: Установка Apache
apt:
name: apache2
state: present
- name: Обновление конфигурации Apache
template:
src: templates/apache2.conf.j2
dest: /etc/apache2/apache2.conf
notify:
- Перезапуск Apache
- name: Обеспечение запуска Apache
service:
name: apache2
state: started
enabled: yes
handlers:
- name: Перезапуск Apache
service:
name: apache2
state: restarted
In this playbook:
hosts
specifies target hosts.become: yes
specifies that tasks should be run with superuser privileges.vars
defines the variables used in the playbook.tasks
contains a list of tasks such as installing Apache, updating the configuration, and ensuring the service starts.handlers
contains handlers that are executed when notified, such as restarting Apache after a configuration update.
Conditional Expressions allow you to perform tasks only when certain conditions are met. For example, installing Nginx only on Debian-based systems:
- name: Установка Nginx
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
Example playbook for installing and configuring MySQL:
---
- name: Установка и настройка MySQL
hosts: databases
become: yes
tasks:
- name: Установка MySQL
apt:
name: mysql-server
state: present
- name: Настройка MySQL
template:
src: templates/my.cnf.j2
dest: /etc/mysql/my.cnf
notify:
- Перезапуск MySQL
- name: Обеспечение запуска MySQL
service:
name: mysql
state: started
enabled: yes
handlers:
- name: Перезапуск MySQL
service:
name: mysql
state: restarted
Example playbook for setting up SSH:
---
- name: Настройка SSH
hosts: all
become: yes
tasks:
- name: Обновление конфигурации SSH
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#PermitRootLogin'
line: 'PermitRootLogin no'
notify:
- Перезапуск SSH
handlers:
- name: Перезапуск SSH
service:
name: sshd
state: restarted
Other features
Roles And modules help to structure and simplify playbooks.
Roles allow you to split the playbook into logical parts and reuse them in different projects. A role consists of a set of standard directories and files, including tasks, handlers, variables, templates, and files.
Example role structure:
my_role/
├── defaults
│ └── main.yml
├── files
│ └── my_file.txt
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ └── my_template.j2
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
Example role for installing and configuring Apache:
# tasks/main.yml
---
- name: Установка Apache
apt:
name: apache2
state: present
- name: Обновление конфигурации Apache
template:
src: my_template.j2
dest: /etc/apache2/apache2.conf
notify:
- Перезапуск Apache
- name: Обеспечение запуска Apache
service:
name: apache2
state: started
enabled: yes
Modules are small programs that perform a single task, such as installing packages, managing files, or configuring services. Ansible includes many built-in modules, but also allows you to create your own modules.
An example of using the apt module to install a package:
- name: Установка Apache
apt:
name: apache2
state: present
More details with other modules you can meet here.
Jinja2 Templates allow you to dynamically generate configuration files based on variables. Template files have the extension .j2.
Example Apache configuration template (templates/apache2.conf.j2):
Listen {{ http_port }}
MaxClients {{ max_clients }}
An example of using a template in a task:
- name: Обновление конфигурации Apache
template:
src: templates/apache2.conf.j2
dest: /etc/apache2/apache2.conf
notify:
- Перезапуск Apache
Conditional statements allow you to perform tasks only when certain conditions are met.
Example:
- name: Установка Nginx на Debian
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
For complex deployments it is recommended to split playbooks into logical parts, using roles and inclusions.
Deploying a web application with a database and load balancer:
---
- name: Развертывание веб-приложения
hosts: all
become: yes
roles:
- load_balancer
- web_server
- database
# load_balancer/tasks/main.yml
---
- name: Установка и настройка HAProxy
apt:
name: haproxy
state: present
- name: Обновление конфигурации HAProxy
template:
src: haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
notify:
- Перезапуск HAProxy
- name: Обеспечение запуска HAProxy
service:
name: haproxy
state: started
enabled: yes
# web_server/tasks/main.yml
---
- name: Установка и настройка Apache
apt:
name: apache2
state: present
- name: Обновление конфигурации Apache
template:
src: apache2.conf.j2
dest: /etc/apache2/apache2.conf
notify:
- Перезапуск Apache
- name: Обеспечение запуска Apache
service:
name: apache2
state: started
enabled: yes
# database/tasks/main.yml
---
- name: Установка и настройка MySQL
apt:
name: mysql-server
state: present
- name: Обновление конфигурации MySQL
template:
src: my.cnf.j2
dest: /etc/mysql/my.cnf
notify:
- Перезапуск MySQL
- name: Обеспечение запуска MySQL
service:
name: mysql
state: started
enabled: yes
Testing and debugging playbooks
Check mode or check mode allows you to execute playbooks without making real changes to the target systems.
An example of running a playbook in verification mode:
ansible-playbook my_playbook.yml --check
In verification mode, Ansible simulates the execution of tasks, displaying expected changes on the screen.
Ansible Vault is designed to protect sensitive data. Using Vault, you can encrypt and decrypt configuration and variable files.
Used to encrypt the file ansible-vault encrypt
:
ansible-vault encrypt secrets.yml
To decrypt the file it is used ansible-vault decrypt
:
ansible-vault decrypt secrets.yml
To use encrypted files in playbooks, you need to add the parameter --ask-vault-pass
:
ansible-playbook my_playbook.yml --ask-vault-pass
An example of using an encrypted file with variables:
---
- name: Установка и настройка MySQL
hosts: databases
become: yes
vars_files:
- secrets.yml
tasks:
- name: Установка MySQL
apt:
name: mysql-server
state: present
Ansible-lint is a tool for analyzing playbooks for errors and style inconsistencies. It helps improve code quality.
Installing ansible-lint:
pip install ansible-lint
Running ansible-lint to check the playbook:
ansible-lint my_playbook.yml
Ansible-lint analyzes the playbook and displays warnings and errors, helping to detect problems before the playbook is executed.
To debug playbooks you can use:
Debug module: allows you to display variable values and diagnostic messages.
- name: Отладка переменных debug: var: my_variable
verbosity flag (-v): increases the verbosity level of Ansible output.
ansible-playbook my_playbook.yml -v
assert module: checks conditions and stops execution if they are violated.
- name: Проверка значения переменной assert: that: - my_variable == "expected_value"
You can learn more about Ansible and other tools in the Infrastructure as a code course. For example, today there will be a free webinar about getting to know the popular Terraform tool. Registration is available via this link.