Ansible Roles

AnsibleAnsibleBeginner
Practice Now

Introduction

In this lab, you will explore Ansible Roles, a powerful feature that allows you to organize and structure your Ansible code in a modular and reusable way. Roles provide a way to automatically load related vars, files, tasks, handlers, and other Ansible artifacts based on a known file structure. By the end of this lab, you'll understand how to create, use, and organize Ansible Roles, which will help you write more maintainable and scalable automation code.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ansible(("`Ansible`")) -.-> ansible/ModuleOperationsGroup(["`Module Operations`"]) ansible(("`Ansible`")) -.-> ansible/PlaybookEssentialsGroup(["`Playbook Essentials`"]) ansible/ModuleOperationsGroup -.-> ansible/template("`Generate Files from Templates`") ansible/ModuleOperationsGroup -.-> ansible/debug("`Test Output`") ansible/PlaybookEssentialsGroup -.-> ansible/playbook("`Execute Playbook`") ansible/PlaybookEssentialsGroup -.-> ansible/roles("`Assign Roles`") subgraph Lab Skills ansible/template -.-> lab-390467{{"`Ansible Roles`"}} ansible/debug -.-> lab-390467{{"`Ansible Roles`"}} ansible/playbook -.-> lab-390467{{"`Ansible Roles`"}} ansible/roles -.-> lab-390467{{"`Ansible Roles`"}} end

Understanding Ansible Roles Structure

Before we start creating our own role, let's understand the structure of an Ansible Role.

An Ansible Role has a defined directory structure with eight main standard directories. Each directory must contain a main.yml file, which contains the relevant content. Here's a brief overview of each directory:

  1. tasks - contains the main list of tasks to be executed by the role.
  2. handlers - contains handlers, which may be used by this role or outside of this role.
  3. defaults - default variables for the role.
  4. vars - other variables for the role.
  5. files - contains files which can be deployed via this role.
  6. templates - contains templates which can be deployed via this role.
  7. meta - defines some meta data for this role.
  8. tests - contains tests for the role.

Let's start by creating a simple role structure. First, navigate to your project directory:

cd ~/project

Now, let's create a directory for our roles:

mkdir -p roles/example_role
cd roles/example_role

The -p flag in the mkdir command creates parent directories as needed.

Now, let's create the basic structure for our role:

mkdir {tasks,handlers,defaults,vars,files,templates,meta}

This command creates all the directories we need for our role in one go. It's a handy shortcut in bash to create multiple directories at once.

Now, let's create a main.yml file in the tasks directory:

nano tasks/main.yml

Add the following content to this file:

---
- name: Print a message
  debug:
    msg: "This is a task from our example role!"

Save and exit the nano editor (Ctrl+X, then Y, then Enter).

We've now created a basic role structure with a simple task. In the next steps, we'll expand on this and learn how to use our role.

Expanding Our Role

Now that we have a basic role structure, let's expand it to include more components of a typical Ansible role. We'll add variables, a handler, and a template.

First, let's add a default variable. Create a main.yml file in the defaults directory:

nano defaults/main.yml

Add the following content:

---
example_variable: "This is a default value"

This sets a default value for example_variable, which can be overridden when the role is used.

Next, let's create a handler. Create a main.yml file in the handlers directory:

nano handlers/main.yml

Add the following content:

---
- name: Restart example service
  debug:
    msg: "This would restart a service in a real scenario"

In a real-world scenario, this handler might restart a service, but for this example, we're just printing a message.

Now, let's create a template. Create a file named example_template.j2 in the templates directory:

nano templates/example_template.j2

Add the following content:

This is an example template.
The value of example_variable is: {{ example_variable }}

This template uses Jinja2 syntax to include the value of our example_variable.

Finally, let's update our tasks/main.yml to use these new components:

nano tasks/main.yml

Replace the existing content with:

---
- name: Print a message
  debug:
    msg: "This is a task from our example role!"

- name: Use our variable
  debug:
    msg: "The value of example_variable is: {{ example_variable }}"

- name: Create a file from our template
  template:
    src: example_template.j2
    dest: /tmp/example_file.txt
  notify: Restart example service

This updated task list now uses our variable, creates a file from our template, and notifies our handler.

Using Our Role in a Playbook

Now that we have created our role, let's use it in a playbook. First, navigate back to the project root:

cd ~/project

Create a new playbook file named use_role.yml:

nano use_role.yml

Add the following content:

---
- name: Use our example role
  hosts: localhost
  roles:
    - example_role

This playbook simply applies our example_role to the localhost.

Now, let's run this playbook:

ansible-playbook -i inventory.ini use_role.yml

You should see output showing the execution of the tasks we defined in our role.

Let's break down what happened:

  1. Ansible looked for a role named example_role in the roles directory.
  2. It found our role and executed the tasks defined in tasks/main.yml.
  3. It used the default value for example_variable that we set in defaults/main.yml.
  4. It created a file in /tmp/example_file.txt using our template.
  5. Finally, it called our handler, which printed a debug message.

This demonstrates how roles allow us to package related tasks, variables, and files together, making our Ansible code more organized and reusable.

Overriding Role Variables

One of the powerful features of Ansible roles is the ability to override default variables. This allows you to create flexible roles that can be used in different scenarios.

Let's create a new playbook that overrides our example_variable. Create a file named override_role_var.yml:

nano override_role_var.yml

Add the following content:

---
- name: Use our example role with a custom variable
  hosts: localhost
  vars:
    example_variable: "This is a custom value"
  roles:
    - example_role

In this playbook, we're setting example_variable to a custom value before applying our role.

Now, let's run this playbook:

ansible-playbook -i inventory.ini override_role_var.yml

You should see that the tasks now use the custom value for example_variable instead of the default value.

This demonstrates how you can create roles with sensible defaults, but still have the flexibility to customize their behavior when needed.

Role Dependencies

Ansible roles can depend on other roles. This allows you to build more complex roles by combining simpler ones. Let's create a new role that depends on our example_role.

First, create a new role structure:

cd ~/project/roles
mkdir -p dependent_role/{tasks,meta}

Now, let's define the role dependencies. Create a main.yml file in the meta directory:

nano dependent_role/meta/main.yml

Add the following content:

---
dependencies:
  - role: example_role

This specifies that dependent_role depends on example_role.

Now, let's add a task to our dependent_role. Create a main.yml file in the tasks directory:

nano dependent_role/tasks/main.yml

Add the following content:

---
- name: Task from dependent role
  debug:
    msg: "This task is from the dependent role"

Now, let's create a playbook to use our dependent_role. Navigate back to the project root:

cd ~/project
nano use_dependent_role.yml

Add the following content:

---
- name: Use our dependent role
  hosts: localhost
  roles:
    - dependent_role

Finally, let's run this playbook:

ansible-playbook -i inventory.ini use_dependent_role.yml

You should see that both the tasks from example_role and dependent_role are executed. This demonstrates how role dependencies allow you to build more complex automation by combining simpler roles.

Summary

In this lab, you've learned about Ansible Roles, a powerful feature for organizing and structuring your Ansible code. Here are the key takeaways:

  1. Ansible Roles provide a way to automatically load related vars, files, tasks, handlers, and other Ansible artifacts based on a known file structure.
  2. The basic structure of a role includes directories for tasks, handlers, defaults, vars, files, templates, and meta information.
  3. Roles allow you to set default variables that can be overridden when the role is used, providing flexibility and reusability.
  4. You can use templates within roles to generate files with dynamic content.
  5. Roles can be easily included in playbooks, allowing you to apply complex configurations with a single line.
  6. You can override role variables in your playbooks, allowing you to customize the behavior of roles without modifying the role itself.
  7. Roles can depend on other roles, allowing you to build more complex automation by combining simpler roles.

Ansible Roles are a fundamental concept for writing maintainable and reusable Ansible code. They allow you to break down complex automation tasks into smaller, more manageable pieces, and they promote code reuse across your organization. As you continue working with Ansible, you'll find that roles become an essential tool in your automation toolkit, especially for larger and more complex projects.


上方是 'Ansible Roles' 的实验文档,其基本结构说明如下:

  • Title:实验标题
  • Introduction:简介,介绍本实验的目的和内容
  • Steps:实验步骤,包含多个 Step,每个 Step 包含以下内容:
    • 步骤完整内容,包含用户需要执行的命令和操作
    • Verification:检查脚本,用于检查用户是否按照步骤正确执行了操作, 使用 YAML 格式
  • Summary:总结,总结本实验的内容和学习成果

在实验文档中,我们使用了 Markdown 语法,包括标题、段落、代码块、图片、链接等。在实验文档中,我们还添加了 Verification 脚本,用于检查用户是否按照步骤正确执行了操作。

请按照以下要求修订实验文档:

  1. 对实验文档进行润色和校对,确保表达足够地道,没有英文语法错误和不常用句式,避免使用感叹号、疑问句等;
  2. 对实验步骤进行简化、合并、扩展,适合初学者,根据重点操作设计 5~10 个步骤;
  3. 对步骤内容进行修订和优化,确保对 Linux 一无所知的用户也能够顺利完成实验, 步骤中和步骤间的过渡、讲解要详细具体;
  4. Verification 一般在步骤完成后执行检测,请不要检测操作过程,而是检测步骤实验目标是否达成,避免检测脚本过于复杂;
  5. 每个步骤的 Verification 支持多个相同的结构,请拆分 Verification,请确保每个 Verification 只有一个检查点,用户能看到更准确的提示信息;
  6. Verification 中的 grep 避免完整匹配大段文本,而应该采用关键词提升匹配的容错率;
  7. Verification 中的 yaml 使用 yaml 进行标记,而其他 yaml 则只能使用 yml 进行标记进行区分;
  8. 步骤文档中的代码、路径、文件名等需要用行内代码标记,代码块需要指定高亮语言;
  9. LabEx 提供给学生的 Docker VM 默认使用 Ubuntu Linux 系统,默认用户为 labex,具有 sudo 权限,终端默认是 zsh,终端默认路径为 /home/labex/project
  10. 环境已经预先使用 sudo apt install -y ansible 安装了 Ansible 2.10.8,学生可以直接使用,不需要再次安装;
  11. 不能修改文档中已存在的图片和链接,示例输出尽量保留;

此外,实验已经使用下面的 setup.sh 初始化脚本在后台默认初始化了环境,请确保不会出现重复步骤:

#!/bin/bash

## 安装 Ansible
sudo apt update && sudo apt install ansible -y && pip3 install Jinja2==3.0.1

## 写入默认配置避免警告
sudo mkdir -p /etc/ansible && sudo bash -c 'echo -e "[defaults]
interpreter_python = /usr/bin/python3" > /etc/ansible/ansible.cfg'

## 配置本地 SSH
ssh-keygen -t rsa -b 4096 -C "labex@example.com" -f ~/.ssh/id_rsa -N ""
ssh-keyscan -H localhost >> ~/.ssh/known_hosts
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
echo "SSH setup completed successfully."

步骤中的内容讲解要足够丰富,能够从初学者视角对潜在的问题进行解释,避免初学者出现困惑或无法正常操作下去。输出修订后的英文实验文档内容:

Other Ansible Tutorials you may like