5 minutes
Ansible - Your First Playbook - Part 2
Understanding Playbooks
Playbooks are the heart of Ansible. They are YAML files that define a set of tasks to be executed on specified hosts or groups of hosts. Playbooks provide a reusable, repeatable, and versionable way to orchestrate your infrastructure.
A basic playbook structure looks like this:
---
# my_first_playbook.yml
- name: My first Ansible Playbook
hosts: webservers
become: true # Run tasks with elevated privileges (e.g., sudo)
tasks:
- name: Ensure Apache is installed
ansible.builtin.apt:
name: apache2
state: present
when: ansible_os_family == "Debian"
- name: Ensure Nginx is installed
ansible.builtin.yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
- name: Start and enable Apache service
ansible.builtin.service:
name: apache2
state: started
enabled: true
when: ansible_os_family == "Debian"
- name: Start and enable Nginx service
ansible.builtin.service:
name: nginx
state: started
enabled: true
when: ansible_os_family == "RedHat"
Let’s break down the components:
- —: Denotes the start of a
YAMLfile. - - name: My first Ansible Playbook: A descriptive name for the playbook. Good practice for readability.
- hosts: webservers: Specifies which hosts from your
inventorythis playbook will run against. Can be a group (likewebservers), a single host, or all. - become: true: This is crucial for tasks that require
rootprivileges (like installing packages or managing services). It tells Ansible to usesudo(or equivalent) on the remote host. - tasks:: A list of individual actions Ansible will perform.
- - name: Ensure
Apacheis installed: A descriptive name for the task. - ansible.builtin.apt:: This specifies the module to use. ansible.builtin is the collection where many core Ansible modules reside.
aptis forDebian/Ubuntusystems. - name: apache2: The package name.
- state: present: Ensures the package is installed. Other states include
absent (remove),latest (ensure latest version). - when: ansible_os_family == “Debian”: This is a conditional statement. This task will only run if the
ansible_os_familyfact (gathered automatically by Ansible) is"Debian". This allows forplatform-specifictasks within the same playbook. - ansible.builtin.yum:: The module for
RedHat/CentOS/Fedorasystems. - ansible.builtin.service:: The module for managing system services.
- name: apache2 / nginx: The service name.
- state: started: Ensures the service is running. Other states:
stopped, restarted, reloaded. - enabled: true: Ensures the service starts automatically on boot.
Common Modules
Ansible has hundreds of modules. Here are some commonly used ansible.builtin modules:
- apt, yum, dnf, pacman: For managing packages on various
Linuxdistributions. - service: For managing system services (
start, stop, restart, enable, disable). - copy: For copying files from the
control nodeto themanaged node. - template: For deploying files using
Jinja2templates (useful for configuration files with variables). - file: For managing
filesanddirectories(create, delete, change permissions). - user: For managing user accounts.
- group: For managing groups.
- command, shell: For executing arbitrary commands on the
remote host. (Use these sparingly; prefer dedicated modules when available.) - debug: For printing messages or variable values during
playbookexecution. - ping: For testing connectivity (as seen in Part 1).
Writing Your First Playbook: Installing Nginx
Let’s create a simple playbook to install and start Nginx on your web servers, assuming they are running a RedHat-based distribution (like CentOS, Rocky Linux, AlmaLinux).
- Update your inventory.ini:
Ensure you have at least one host under the [webservers] group that you can SSH into and has sudo privileges.
# inventory.ini
[webservers]
your_webserver_ip_or_hostname
# e.g., web1.example.com or 192.168.1.100
[all:vars]
ansible_user=your_ssh_user
ansible_private_key_file=~/.ssh/id_rsa
- Create the playbook file:
Save the following content as nginx_install.yml in the same directory as your inventory.ini.
---
# nginx_install.yml
- name: Install and configure Nginx web server
hosts: webservers
become: true # Use sudo for elevated privileges
tasks:
- name: Ensure Nginx package is present
ansible.builtin.yum:
name: nginx
state: present
update_cache: true # Ensures package cache is updated before installing
- name: Start Nginx service
ansible.builtin.service:
name: nginx
state: started
enabled: true # Ensure Nginx starts on boot
Explanation of new parameters:
- update_cache: true: For
yum/aptmodules, this ensures that the package manager’s cache is updated, so it can find the latest package information.
Running Your First Playbook
Now, let’s execute the playbook.
- Navigate to your project directory:
cd /path/to/your/ansible/project
- Run the playbook using ansible-playbook:
ansible-playbook -i inventory.ini nginx_install.yml
- ansible-playbook: The command to execute playbooks.
- -i inventory.ini: Specifies your inventory file.
- nginx_install.yml: The playbook file to run.
Expected Output
When you run the playbook, Ansible will connect to your target host(s), gather facts, and then execute each task. You’ll see output similar to this:
PLAY [Install and configure Nginx web server] **********************************
TASK [Gathering Facts] *********************************************************
ok: [your_webserver_ip_or_hostname]
TASK [Ensure Nginx package is present] *****************************************
changed: [your_webserver_ip_or_hostname]
TASK [Start Nginx service] *****************************************************
changed: [your_webserver_ip_or_hostname]
PLAY RECAP *********************************************************************
your_webserver_ip_or_hostname : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Understanding the output:
- PLAY: Indicates the start of a new play defined in your playbook.
- TASK: Shows the execution of each individual task.
- ok: The task completed successfully, and no changes were made to the system (e.g., the package was already installed).
- changed: The task completed successfully, and it made changes to the system (e.g., installed the package, started the service).
- unreachable: Ansible could not connect to the host.
- failed: The task encountered an error.
- PLAY RECAP: A summary of the playbook run for each host, showing the number of ok, changed, unreachable, failed, skipped, rescued, and ignored tasks.
After the playbook completes, you should be able to access Nginx on your web server by navigating to its IP address or hostname in a web browser.
Idempotence
One of Ansible’s core principles is idempotence. This means that running the same playbook multiple times will result in the same system state without causing unintended side effects.
If you run the nginx_install.yml playbook a second time, you’ll notice that the changed count will likely be 0 for the Nginx installation task, as it’s already installed and running. The service task might show ok if it was already running and enabled, or changed if for some reason it wasn’t.
This idempotence is achieved by the modules themselves, which check the current state of the system before attempting to make changes.
Next Steps
In Part 3, we will explore variables and templates, which are essential for creating flexible and reusable playbooks that can adapt to different environments and configurations.