-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2191 from rlopez133/aap17_role
Section 1.7 Roles is now Collections
- Loading branch information
Showing
13 changed files
with
283 additions
and
275 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,282 @@ | ||
# Workshop Exercise - Collections: Making Your Playbooks Modular and Scalable | ||
|
||
**Read this in other languages**: | ||
<br> [English](README.md), [日本語](README.ja.md),  [Portugues do Brasil](README.pt-br.md),  [Française](README.fr.md), [Español](README.es.md). | ||
|
||
## Table of Contents | ||
|
||
- [Objective](#objective) | ||
- [Guide](#guide) | ||
- [Step 1 - Understanding Ansible Collections](#step-1---understanding-ansible-collections) | ||
- [Step 2 - Cleaning up the Environment](#step-2---cleaning-up-the-environment) | ||
- [Step 3 - Building an Apache Collection](#step-3---building-an-apache-collection) | ||
- [Step 4 - Using the Collection in a Playbook](#step-4---using-the-collection-in-a-playbook) | ||
- [Step 5 - Collection Execution and Validation](#step-5---collection-execution-and-validation) | ||
- [Step 6 - Verify Apache is Running](#step-6---verify-apache-is-running) | ||
|
||
## Objective | ||
|
||
This exercise builds on your previous experience with Ansible by focusing on **collections**. Collections offer an efficient way to package and distribute automation content, including roles, modules, plugins, and playbooks, all within a single unit. In this exercise, we’ll develop a collection that installs and configures Apache (httpd), demonstrating how to structure content for modular and reusable automation. | ||
|
||
## Guide | ||
|
||
### Step 1 - Understanding Ansible Collections | ||
|
||
**Ansible collections** are the preferred way to **organize, distribute, and reuse automation content**. They group together various components—like roles, modules, and plugins—so developers can manage and share automation resources more efficiently. Collections allow you to store related content in one place and distribute it via **Ansible Galaxy**, **Automation Hub**, or **private Automation Hub** within your organization. | ||
|
||
Each **collection** can include the following components: | ||
|
||
#### Modules | ||
Small programs that perform specific automation tasks on **local machines, APIs, or remote hosts**. Modules are usually written in **Python** and include metadata defining **how, when, and by whom** the task can be executed. Modules can be used across various use cases like **cloud management, networking, and configuration management**. | ||
|
||
**Example modules:** | ||
- **dnf**: Installs or removes packages with the dnf package manager. | ||
- **service**: Manages system services (start, stop, restart). | ||
- **command**: Executes commands on a target system. | ||
|
||
#### Roles | ||
**Roles** are modular bundles of tasks, variables, templates, and handlers. They simplify automation workflows by breaking them into **reusable components**. Roles can be imported into **playbooks** and used across multiple automation scenarios, reducing duplication and improving manageability. | ||
|
||
#### Plugins | ||
**Plugins** extend Ansible’s core functionality by adding **custom connection types, callbacks, or lookup functions**. Unlike modules, which execute actions on managed nodes, plugins **typically run on the control node** to enhance how Ansible operates during execution. | ||
|
||
#### Playbooks | ||
**Playbooks** are **YAML files** that describe **automation workflows**. They contain a series of **plays**—which map tasks to managed hosts—and serve as the blueprint for configuring and managing systems. | ||
|
||
### Step 2 - Cleaning up the Environment | ||
|
||
Before we build the collection, let's clean up any previous Apache installations. | ||
|
||
{% raw %} | ||
|
||
```yaml | ||
--- | ||
- name: Cleanup Environment | ||
hosts: all | ||
become: true | ||
vars: | ||
package_name: httpd | ||
tasks: | ||
- name: Remove Apache from web servers | ||
ansible.builtin.dnf: | ||
name: "{{ package_name }}" | ||
state: absent | ||
when: inventory_hostname in groups['web'] | ||
|
||
- name: Remove firewalld | ||
ansible.builtin.dnf: | ||
name: firewalld | ||
state: absent | ||
|
||
- name: Delete created users | ||
ansible.builtin.user: | ||
name: "{{ item }}" | ||
state: absent | ||
remove: true | ||
loop: | ||
- alice | ||
- bob | ||
- carol | ||
- Roger | ||
|
||
- name: Reset MOTD to an empty message | ||
ansible.builtin.copy: | ||
dest: /etc/motd | ||
content: '' | ||
``` | ||
{% endraw %} | ||
## Step 3 - Building an Apache Collection | ||
1. Create the Collection Structure | ||
Use `ansible-galaxy` to initialize the collection structure: | ||
|
||
```bash | ||
[student@ansible-1 lab_inventory]$ ansible-galaxy collection init webops.apache | ||
``` | ||
|
||
This creates the following structure: | ||
|
||
```bash | ||
├── README.md | ||
├── docs | ||
├── galaxy.yml | ||
├── meta | ||
│ └── runtime.yml | ||
├── plugins | ||
│ └── README.md | ||
├── roles/ | ||
├── playbooks/ | ||
└── tests/ | ||
``` | ||
|
||
2. Define Role Variables: | ||
|
||
Add Apache-specific variables in roles/apache/vars/main.yml: | ||
|
||
```yaml | ||
--- | ||
apache_package_name: httpd | ||
apache_service_name: httpd | ||
``` | ||
|
||
3. Create Role Tasks: | ||
|
||
Add the following tasks to roles/apache/tasks/main.yml to install and configure Apache: | ||
|
||
{% raw %} | ||
|
||
```yaml | ||
--- | ||
- name: Install Apache web server | ||
ansible.builtin.package: | ||
name: "{{ apache_package_name }}" | ||
state: present | ||
- name: Ensure Apache is running and enabled | ||
ansible.builtin.service: | ||
name: "{{ apache_service_name }}" | ||
state: started | ||
enabled: true | ||
- name: Install firewalld | ||
ansible.builtin.dnf: | ||
name: firewalld | ||
state: present | ||
- name: Allow HTTP traffic on web servers | ||
ansible.posix.firewalld: | ||
service: http | ||
permanent: true | ||
state: enabled | ||
when: inventory_hostname in groups['web'] | ||
notify: Reload Firewall | ||
``` | ||
{% endraw %} | ||
|
||
4. Add Handlers: | ||
|
||
Create a handler to reload the firewall in roles/apache/handlers/main.yml: | ||
|
||
{% raw %} | ||
|
||
```yaml | ||
--- | ||
- name: Reload Firewall | ||
ansible.builtin.service: | ||
name: firewalld | ||
state: reloaded | ||
``` | ||
{% endraw %} | ||
|
||
5. Create a Custom Webpage Template: | ||
|
||
Add a Jinja2 template for the web page in roles/apache/templates/index.html.j2: | ||
|
||
{% raw %} | ||
|
||
```html | ||
<html> | ||
<head> | ||
<title>Welcome to {{ ansible_hostname }}</title> | ||
</head> | ||
<body> | ||
<h1>Hello from {{ ansible_hostname }}</h1> | ||
</body> | ||
</html> | ||
``` | ||
|
||
{% endraw %} | ||
|
||
6. Deploy the Template: | ||
|
||
Add the template deployment task to roles/apache/tasks/main.yml: | ||
|
||
```yaml | ||
- name: Deploy custom index.html | ||
ansible.builtin.template: | ||
src: index.html.j2 | ||
dest: /var/www/html/index.html | ||
``` | ||
|
||
## Step 4 - Using the Collection in a Playbook | ||
|
||
Create a playbook named `deploy_apache.yml` inside the `playbooks/`` directory to apply the collection to the `web` group: | ||
|
||
```yaml | ||
--- | ||
- name: Deploy Apache using Collection | ||
hosts: web | ||
become: true | ||
collections: | ||
- webops.apache | ||
- ansible.posix | ||
tasks: | ||
- name: Apply Apache role from the collection | ||
ansible.builtin.include_role: | ||
name: apache | ||
``` | ||
|
||
## Step 5 - Collection Execution and Validation | ||
|
||
Run the playbook using `ansible-navigator`: | ||
|
||
```bash | ||
ansible-navigator run playbooks/deploy_apache.yml -m stdout | ||
``` | ||
```text | ||
PLAY [Deploy Apache using Collection] ***************************************** | ||
TASK [Gathering Facts] ********************************************************* | ||
ok: [node1] | ||
ok: [node2] | ||
ok: [node3] | ||
TASK [Apply Apache role from the collection] *********************************** | ||
changed: [node1] | ||
changed: [node2] | ||
changed: [node3] | ||
RUNNING HANDLER [apache : Reload Firewall] ************************************* | ||
ok: [node1] | ||
ok: [node2] | ||
ok: [node3] | ||
PLAY RECAP ********************************************************************* | ||
node1 : ok=3 changed=2 unreachable=0 failed=0 | ||
node2 : ok=3 changed=2 unreachable=0 failed=0 | ||
node3 : ok=3 changed=2 unreachable=0 failed=0 | ||
``` | ||
|
||
## Step 6 - Verify Apache is Running | ||
|
||
After the playbook runs, verify Apache is active on the web servers: | ||
|
||
```bash | ||
[rhel@control ~]$ ssh node1 "systemctl status httpd" | ||
``` | ||
|
||
You should see output confirming Apache is running. Finally, confirm the web page is served: | ||
|
||
```bash | ||
[student@ansible-1 lab_inventory]$ curl http://node1 | ||
``` | ||
```html | ||
<html> | ||
<head> | ||
<title>Welcome to node1</title> | ||
</head> | ||
<body> | ||
<h1>Hello from node1</h1> | ||
</body> | ||
</html> | ||
``` | ||
--- | ||
**Navigation** | ||
<br> | ||
[Previous Exercise](../1.6-templates) - [Next Exercise](../1.8-troubleshoot) | ||
|
||
[Click here to return to the Ansible for Red Hat Enterprise Linux Workshop](../README.md#section-1---ansible-engine-exercises) |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Oops, something went wrong.