Playbooks in Ansible

Ansible is an automation tool that makes it easy to manage configurations, deploy applications, and orchestrate complex tasks. Its main strength lies in the ease of use and high readability of playbooks, which are automation scripts written in YAML.

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:

  1. Padding: YAML uses indentation to determine the level of nesting. Typically spaces are used rather than tabs.

  2. Key-value: each line is a key-value pair separated by a colon.

  3. 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:

  1. Header: Defines general information about the playbook, such as name and target hosts.

  2. Variables: are used to store data that can be reused in the playbook.

  3. Tasks: define specific actions that must be performed on hosts.

  4. Handlers: are performed when the system state changes, for example, restarting a service after a configuration update.

  5. 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.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *