Ansible Playbooks

 Lesson 1: What is an Ansible Playbook?


Ansible Playbooks serve as the foundation for configuration management and automation in Ansible. Think of them as a set of instructions, written in YAML format, that define the desired state of a system. This desired state can include configurations, installations, and various tasks that need to be executed on remote machines.


 Key Components of an Ansible Playbook:

 

  1. Hosts:

   - Specifies the target machines where the playbook should be applied.

   - Can include individual hosts, groups of hosts, or even wildcards for dynamic selections.


    ```yaml

    ---

    - hosts: web_servers

      tasks:

        - name: Ensure Apache is installed

          apt:

            name: apache2

            state: present

    ```


   In this example, the playbook targets the group of hosts labeled as 'web_servers' and ensures that Apache is installed on them.


  1. Tasks:

   - Represent the list of actions or operations to be performed on the specified hosts.

   - Each task is a call to an Ansible module.


    ```yaml

    ---

    - hosts: database_servers

      tasks:

        - name: Ensure PostgreSQL is installed

          apt:

            name: postgresql

            state: present

    ```

   Here, the playbook targets the 'database_servers' group, installing PostgreSQL on those machines.


Importance of Playbooks in Automation


 Advantages of Ansible Playbooks:

  1. Declarative Syntax:

   - Playbooks use YAML, a human-readable data serialization format.

   - Offers a clear and concise way to describe the desired configuration.


    ```yaml

    ---

    - hosts: all

      tasks:

        - name: Ensure Nginx is installed

          apt:

            name: nginx

            state: present

    ```

 

  1. Reusability:

   - Playbooks are modular and can be reused across different projects.

   - Encourages the creation of standardized and reusable automation code.


    ```yaml

    ---

    - hosts: app_servers

      tasks:

        - include_tasks: common_tasks.yml

    ```

   In this example, the playbook includes tasks from an external file, promoting code reuse.


  1. Idempotency:

   - Ansible ensures idempotency, meaning the playbook can be run multiple times without changing the result after the first run.

   - Reduces the risk of unintended side effects during automation.


    ```yaml

    ---

    - hosts: db_servers

      tasks:

        - name: Ensure database is initialized

          command: initialize_db.sh

    ```


   The playbook executes the initialization script only if the database needs to be initialized, maintaining idempotency.


 Use Case: Deploying Web Applications

Consider a scenario where you need to deploy a web application on multiple servers. Instead of manually configuring each server, you can create an Ansible playbook to automate the deployment process.


```yaml

---

- hosts: web_servers

  tasks:

    - name: Ensure Git is installed

      apt:

        name: git

        state: present


    - name: Clone the application repository

      git:

        repo: https://github.com/example/app.git

        dest: /var/www/app


    - name: Install required dependencies

      npm:

        path: /var/www/app

```


In this example, the playbook ensures that Git is installed, clones the application repository, and installs the necessary dependencies. This automation simplifies the deployment process and ensures consistency across all web servers.


 Conclusion

Understanding Ansible Playbooks is crucial for anyone venturing into automation and configuration management. They provide a powerful and flexible framework for defining, organizing, and executing automation tasks. As we delve deeper into subsequent lessons, we'll explore more advanced topics and practical examples to solidify your understanding of Ansible Playbooks.


Ansible Playbook Structure

Understanding the basic structure of Ansible Playbooks is fundamental to harnessing the power of Ansible for automation and configuration management. Ansible Playbooks use YAML (YAML Ain't Markup Language) as their configuration language, offering a human-readable and easy-to-write syntax. Let's break down the basic structure.


 Basic Structure:

A simple Ansible Playbook looks like this:


```yaml

---

- hosts: target_machines

  tasks:

    - name: Task 1

      module_name:

        option1: value1

        option2: value2


    - name: Task 2

      module_name:

        option1: value1

        option2: value2

```


`---`: This indicates the start of YAML content. YAML files start with three dashes.


`hosts`: Specifies the target machines or hosts where the playbook tasks will be executed.


`tasks`: Contains a list of tasks to be performed on the specified hosts.


`name`: Describes the task in a human-readable format for better understanding.


`module_name`: Represents the Ansible module to be executed for the task.


`options`: Parameters or arguments specific to the chosen module.


 Example:


Let's consider a practical example of a basic Ansible Playbook that ensures Nginx is installed on a group of web servers:


```yaml

---

- hosts: web_servers

  tasks:

    - name: Ensure Nginx is installed

      apt:

        name: nginx

        state: present

```


In this example:

- The playbook targets the group of hosts labeled as 'web_servers.'

- The task name is "Ensure Nginx is installed."

- The `apt` module is used to manage packages, and it ensures that Nginx is present on the target servers.


Key Components - Hosts, Tasks, and Modules

Now, let's dive deeper into the key components of an Ansible Playbook: hosts, tasks, and modules.


 Hosts:


The `hosts` section in the playbook specifies the machines or nodes on which the tasks will be executed. It provides flexibility, allowing you to target individual hosts, groups of hosts, or even define dynamic selections.


```yaml

---

- hosts: web_servers

  tasks:

    - name: Task 1

       Module and options go here

```

In this example, the playbook targets the 'web_servers' group. You can replace it with specific hostnames or IP addresses if needed.


 Tasks:

The `tasks` section contains a list of actions or operations to be performed on the specified hosts. Each task involves the execution of a specific Ansible module.


```yaml

---

- hosts: app_servers

  tasks:

    - name: Install dependencies

      npm:

        name: express

        state: present

```


Here, the playbook targets the 'app_servers' group and includes a task named "Install dependencies." The `npm` module is utilized to manage Node.js packages.


 Modules:

Modules are the building blocks of Ansible Playbooks. They are responsible for carrying out specific tasks on target hosts. Ansible provides a rich set of modules for various purposes, such as package management, file operations, service management, and more.


```yaml

---

- hosts: database_servers

  tasks:

    - name: Ensure PostgreSQL is installed

      apt:

        name: postgresql

        state: present

```


In this case, the playbook targets 'database_servers' and uses the `apt` module to ensure that PostgreSQL is installed on the specified hosts.


 Best Practices for Playbook Structure:

  1. Organize Playbooks:

   - Break down complex playbooks into smaller, modular files.

   - Use the `include` or `import` directive to include tasks from external files.


  1. Use Variables:

   - Leverage variables for flexibility and reusability.

   - Store commonly used values in variables for easy maintenance.


  1. Documentation:

   - Add comments and documentation to enhance playbook readability.

   - Clearly describe the purpose of each task for better understanding.


 Example: Organizing Playbooks

Consider a scenario where you have common tasks shared across multiple playbooks. Create a file named `common_tasks.yml`:


```yaml

 common_tasks.yml

- name: Ensure common package is installed

  apt:

    name: common_package

    state: present

```

Now, include these tasks in your main playbook:


```yaml

---

- hosts: app_servers

  tasks:

    - include_tasks: common_tasks.yml


    - name: Install app-specific dependencies

      npm:

        name: my_app_dependency

        state: present

```

This promotes modularization and reusability, making your playbooks more maintainable.


 Conclusion

Mastering the structure of Ansible Playbooks is a crucial step in becoming proficient with Ansible. As we explored, playbooks are composed of hosts, tasks, and modules, and they follow a clear and readable YAML syntax. By understanding these fundamental components, you lay the foundation for creating powerful and effective automation scripts. Stay tuned for more lessons where we'll delve into advanced playbook features and real-world use cases. Happy automating!


Writing Your First Ansible Playbook

Setting Up Your Environment

In this lesson, we'll embark on the journey of writing your first Ansible Playbook. Before we dive into the playbook creation, let's ensure your environment is set up correctly for Ansible. We'll cover the installation process and configuration of hosts for playbook execution.


Installing Ansible

Before you can start creating Ansible Playbooks, you need to install Ansible on your machine. Ansible supports various operating systems, including Linux, macOS, and Windows. Here, we'll focus on the installation process for a Linux environment, specifically Ubuntu.


 Installation Steps:

  1. Update Package Lists:

   Ensure your package lists are updated to get the latest available packages.


   ```bash

   sudo apt update

   ```


  1. Install Ansible:

   Use the package manager to install Ansible.


   ```bash

   sudo apt install ansible

   ```


  1. Verify Installation:

   Confirm that Ansible is installed by checking its version.


   ```bash

   ansible --version

   ```


   This should display information about the installed Ansible version.


 Example:


```bash

ansible 2.9.6

  config file = /etc/ansible/ansible.cfg

  configured module search path = ['/usr/share/ansible/awb/plugins/modules', '/usr/share/ansible/base/plugins/modules']

  ansible python module location = /usr/lib/python3/dist-packages/ansible

  executable location = /usr/bin/ansible

  python version = 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0]

  ```

  

Now that Ansible is installed, let's move on to configuring hosts.


Configuring Hosts for Playbook Execution


Ansible communicates with remote machines through SSH, and it uses an inventory file to manage and organize these machines. The inventory file is where you define the hosts on which Ansible will execute tasks.


 Inventory File Location:


The default location for the inventory file is `/etc/ansible/hosts`. You can use this file or specify a custom location using the `-i` option when running Ansible commands.


 Example Inventory File:


```ini

 /etc/ansible/hosts


[web_servers]

web1 ansible_host=192.168.1.101

web2 ansible_host=192.168.1.102


[db_servers]

db1 ansible_host=192.168.1.201

db2 ansible_host=192.168.1.202

```


In this example:

- `web_servers` and `db_servers` are groups of hosts.

- `ansible_host` specifies the IP address of each host.


 Testing Connectivity:


Ensure Ansible can connect to your hosts using the `ansible` command.


```bash

ansible -m ping -i /etc/ansible/hosts web_servers

```


This command sends a test ping to the hosts in the `web_servers` group.


 Example Output:


```bash

web1 | SUCCESS => {

    "ansible_facts": {

        "discovered_interpreter_python": "/usr/bin/python3"

    },

    "changed": false,

    "ping": "pong"

}

web2 | SUCCESS => {

    "ansible_facts": {

        "discovered_interpreter_python": "/usr/bin/python3"

    },

    "changed": false,

    "ping": "pong"

}

```


If you see `"ping": "pong"`, it means Ansible successfully connected to the hosts.


 Best Practices for Environment Setup:

  1. Use Descriptive Hostnames:

   - Assign meaningful names to your hosts in the inventory file for clarity.


  1. Grouping Hosts:

   - Group hosts based on their roles (e.g., web servers, database servers).


  1. SSH Key Authentication:

   - Set up SSH key authentication for seamless communication between Ansible and hosts.


  1. Dynamic Inventories:

   - Explore dynamic inventory scripts for automatic host discovery in dynamic environments.


 Example: Inventory File with Dynamic Hosts


```ini

 /etc/ansible/hosts


[web_servers]

web1 ansible_host=192.168.1.101

web2 ansible_host=192.168.1.102


[db_servers]

db1 ansible_host=192.168.1.201

db2 ansible_host=192.168.1.202


[dynamic_hosts]

 Additional hosts added dynamically

```

Dynamic inventories can automatically populate the `[dynamic_hosts]` group based on your infrastructure changes.


 Conclusion


Congratulations! You've successfully set up your environment for Ansible Playbook development. In this lesson, we covered the installation of Ansible and the configuration of hosts using an inventory file. With these foundational steps, you're ready to dive into creating powerful automation scripts using Ansible Playbooks. In the next lesson, we'll guide you through writing your first Ansible Playbook and executing it on the configured hosts. Stay tuned and happy automating!


Anatomy of a Playbook


In this lesson, we will delve into the heart of Ansible automation by understanding the anatomy of a playbook. A playbook is where the magic happens, where tasks are defined, and configurations are applied. Let's break down a simple playbook, explore how to write tasks, and understand the crucial concept of defining hosts.


Detailed Breakdown of a Simple Playbook


A playbook is written in YAML (Yet Another Markup Language) and follows a clear structure. YAML is human-readable and easy to understand, making Ansible playbooks accessible to both beginners and seasoned developers.


 Anatomy of a Playbook:


```yaml

---

- name: My First Playbook

  hosts: web_servers

  become: yes

  tasks:

    - name: Ensure Apache is installed

      apt:

        name: apache2

        state: present


    - name: Ensure Apache service is running

      service:

        name: apache2

        state: started

```


Explanation:


- `name`: Descriptive name for the playbook.

- `hosts`: Specifies the group of hosts on which the playbook will run.

- `become`: Enables privilege escalation, allowing tasks to run with elevated permissions.

- `tasks`: List of tasks to be executed sequentially.


 Key Components:


  1. Name:

   - The name of the playbook provides context about its purpose. It should be clear and descriptive.


  1. Hosts:

   - Defines the target hosts or groups of hosts where the playbook tasks will be executed. In this example, tasks will run on hosts in the `web_servers` group.


  1. Become:

   - The `become` keyword is used for privilege escalation. When set to `yes`, tasks will be executed with elevated permissions.


  1. Tasks:

   - Tasks are the building blocks of a playbook. Each task performs a specific action, such as installing software, managing services, or copying files.


 Lesson 2.2.2: Writing Tasks and Defining Hosts


Now, let's break down the tasks in the playbook and understand how to write them.


 Task 1: Ensure Apache is Installed


```yaml

- name: Ensure Apache is installed

  apt:

    name: apache2

    state: present

```


Explanation:


- `name`: Descriptive name for the task.

- `apt`: Ansible module for package management.

- `name: apache2`: Specifies the package (Apache2) to be managed.

- `state: present`: Ensures that the package is present on the system.


 Task 2: Ensure Apache Service is Running


```yaml

- name: Ensure Apache service is running

  service:

    name: apache2

    state: started

```


Explanation:


- `name`: Descriptive name for the task.

- `service`: Ansible module for managing services.

- `name: apache2`: Specifies the service (Apache2) to be managed.

- `state: started`: Ensures that the service is started.


 Best Practices for Writing Tasks:


  1. Use Descriptive Names:

   - Clear and concise names make your playbook and tasks more understandable.


  1. Module Selection:

   - Choose the appropriate Ansible modules for tasks. Ansible provides a wide range of modules for different purposes.


  1. Task Order:

   - Consider the order of tasks. Ensure dependencies are met, and tasks are sequenced logically.


  1. Indentation:

   - YAML relies on indentation. Maintain consistent indentation for readability.


 Executing the Playbook:


  1. Save the Playbook:

   - Save the playbook with a `.yaml` extension (e.g., `first_playbook.yaml`).


  1. Run the Playbook:

   - Execute the playbook using the `ansible-playbook` command.


   ```bash

   ansible-playbook first_playbook.yaml

   ```


   This command will apply the defined tasks to the hosts specified in the playbook.


 Example Output:


```bash

PLAY [My First Playbook] 


TASK [Gathering Facts] 

ok: [web1]

ok: [web2]


TASK [Ensure Apache is installed] 

ok: [web1]

ok: [web2]


TASK [Ensure Apache service is running] 

ok: [web1]

ok: [web2]


PLAY RECAP 

web1                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

web2                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

```


The output shows that the playbook ran successfully on hosts `web1` and `web2`, ensuring Apache is installed and the service is running.


 Conclusion

In this lesson, we dissected the anatomy of an Ansible playbook. We learned how to structure a playbook, define hosts, and write tasks using Ansible modules. Playbooks are the cornerstone of Ansible automation, allowing you to orchestrate complex tasks effortlessly. Armed with this knowledge, you are now ready to create your own Ansible playbooks and automate various aspects of system configuration. In the next lesson, we will explore more advanced features and techniques to enhance your Ansible skills. Happy automating!


Modules