Ansible Role: A Comprehensive Guide to Structuring Playbooks

nginx-role.yml roles/

└── nginx

├── tasks

│ ├── group.yml # Create group

│ ├── main.yml

│ ├── restart.yml # Restart service

│ ├── start.yml # Start service

│ ├── templ.yml # Copy configuration file

│ ├── user.yml # Create user

│ └── yum.yml # Install service

└── templates

└── nginx.conf.j2 # Configuration file

group.yml (0 kB)

main.yml (0 kB)

nginx-role.yml (0 kB)

restart.yml (0 kB)

start.yml (0 kB)

templ.yml (0 kB)

user.yml (0 kB)

yum.yml (0 kB)

Roles

Roles are a new feature introduced in Ansible version 1.2, used to organize playbooks hierarchically and structurally.

Roles can automatically load variable files, tasks, and handlers based on a hierarchical structure.

To use roles, simply include them in the playbook using the include directive.

In simple terms, roles are a mechanism that allows you to place variables, files, tasks, templates, and handlers in separate directories and easily include them.

Roles are generally used in scenarios where services are built based on hosts, but they can also be used for building daemons and other scenarios.

For complex scenarios, it is recommended to use roles for high code reusability.

Change specified hosts or host groups.

For example, if naming conventions are not standardized, maintenance and inheritance costs are high.

Some functionalities require multiple playbooks, which can be achieved through includes.

Roles: A collection of roles.

roles/

mysql/

httpd/

nginx/

memcached/

Roles can call each other.

Roles directory structure:

playbook.yml Calls roles.

roles/

project/ (Role name)

tasks/

files/

vars/

templates/

handlers/

default/ Not commonly used

meta/ Not commonly used

Roles Directory Functions

/roles/project/: Project name, with the following subdirectories:

files/: Stores files called by copy or script modules.

templates/: Directory where the template module looks for required template files.

tasks/: Defines tasks, the basic elements of a role, and must contain at least one file named main.yml;

Other files need to be included in this file through include.

handlers/: Must contain at least one file named main.yml;

Other files need to be included in this file through include.

vars/: Defines variables, must contain at least one file named main.yml;

Other files need to be included in this file through include.

meta/: Defines special settings and dependencies for the current role, must contain at least one file named main.yml;

Other files need to be included in this file through include.

default/: Used to set default variables with the main.yml file in this directory.

Roles/appname directory structure:

tasks directory: Must contain at least one file named main.yml, which defines the task list for this role;

This file can include other task files located in this directory.

files directory: Stores files called by copy or script modules;

templates directory: The template module will automatically look for Jinja2 template files in this directory.

handlers directory: This directory should contain a main.yml file to define the handlers used by this role;

Other handler files included in the handler should also be located in this directory;

vars directory: Should contain a main.yml file to define the variables used by this role;

meta directory: Should contain a main.yml file to define special settings and dependencies for this role;

Supported in Ansible 1.3 and later versions;

default directory: Used to set default variables for the current role; should contain a main.yml file.

roles/example_role/files/ All files can be stored here.

roles/example_role/templates/ All templates are stored here.

roles/example_role/tasks/main.yml: The main function, all tasks included will be executed.

roles/example_role/handlers/main.yml: All handlers included will be executed.

roles/example_role/vars/main.yml: All variables included will take effect in roles.

roles/example_role/meta/main.yml: All dependencies of roles will be logged correctly.

Steps to create a role:

(1) Create a directory named roles.

(2) In the roles directory, create directories named after each role, such as webservers, etc.

(3) In each role-named directory, create directories for files, handlers, meta, tasks, templates, and vars;

Unused directories can be created as empty directories or not created at all.

(4) In the playbook file, call each role.

Creating the httpd Role

1> Create the roles directory.

mkdir roles/{httpd,mysql,redis}/tasks -pv

mkdir roles/httpd/{handlers,files}

Check the directory structure.

tree roles/

roles/

├── httpd

│ ├── files

│ ├── handlers

│ └── tasks

├── mysql

│ └── tasks

└── redis

└── tasks

2> Create target files.

cd roles/httpd/tasks/

touch install.yml config.yml service.yml

3> vim install.yml

– name: install httpd package

yum: name=httpd

vim config.yml

– name: config file

copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes

notify: restart service httpd

vim service.yml

– name: start service

service: name=httpd state=started enabled=yes

4> Create the main.yml control file, calling the above individual yml files,

main.yml defines the order of execution.

vim main.yml

– include: install.yml

– include: config.yml

– include: service.yml

5> Prepare the httpd.conf file, place it in the httpd separate file directory.

cp /app/ansible/files/httpd.conf ../files/

6> Create a webpage.

vim files/index.html

<h1> welcome to weixiaodong home </h1>

7> Create the yml file for the webpage.

vim tasks/index.yml

– name: index.html

copy: src=index.html dest=/var/www/html

notify: restart service httpd

8> Write the webpage’s yml file into main.yml.

vim main.yml

– include: install.yml

– include: config.yml

– include: index.yml

– include: service.yml

9> Create the handler file main.yml in the handlers directory.

vim handlers/main.yml

– name: restart service httpd

service: name=httpd state=restarted

10> Create a file to call the httpd role.

cd /app/ansible/roles

vim role_httpd.yml

# httpd role

– hosts: appsrvs

remote_user: root

roles: # Call role

– role: httpd

11> Check the directory structure

tree

httpd

├── files

│ ├── httpd.conf

│ └── index.html

├── handlers

│ └── main.yml

└── tasks

├── config.yml

├── index.yml

├── install.yml

├── main.yml

└── service.yml

12> ansible-playbook role_httpd.yml

Creating an Nginx Role

nginx/

├── files # Transfer files

│ └── index.html

├── handlers # Trigger actions

│ └── main.yml

├── tasks # Task set files

│ ├── group.yml

│ ├── install.yml

│ ├── main.yml

│ ├── service.yml

│ └── useradd.yml

├── templates # Template files

│ └── nginx.conf.j2

└── vars # Variable files

└── main.yml

1> Create the nginx role directory.

cd /app/ansible/role

mkdir nginx/{tasks,templates,handlers} -pv

2> Create the tasks directory.

cd tasks/

touch install.yml config.yml service.yml file.yml user.yml

Create the main.yml file to define the order of task execution.

vim main.yml

– include: user.yml

– include: install.yml

– include: config.yml

– include: file.yml

– include: service.yml

3> Prepare configuration files (CentOS 7, 8).

/app/ansible/role/nginx/templates/

nginx7.conf.j2

nginx8.conf.j2

4> Define tasks.

vim tasks/install.yml

– name: install

yum: name=nginx

vim tasks/user.yml

– name: add group nginx

group: name=nginx gid=80

– name: add user nginx

user: name=nginx uid=80 system=yes shell=/sbin/nologin

vim tasks/config.yml

– name: config file

template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf

when: ansible_distribution_major_version==”7″

notify: restart

– name: config file

template: src=nginx8.conf.j2 dest=/etc/nginx/nginx.conf

when: ansible_distribution_major_version==”8″

notify: restart

vim tasks/file.yml # Cross-role call file.yml to achieve file reuse.

– name: index.html

copy: src=roles/httpd/files/index.html dest=/usr/share/nginx/html/ # If the nginx role has a files folder and index.html, then src=index.html

vim tasks/service.yml

– name: start service

service: name=nginx state=started enabled=yes

vim handlers/main.yml

– name: restart

service: name=nginx state=restarted

vim roles/role_nginx.yml

# Test role

– hosts: appsrvs

roles:

– role: nginx

5> Test installation.

ansible-playbook role_nginx.yml

Playbook Calling Roles

Method 1 to call roles:

– hosts: websrvs

remote_user: root

roles:

– mysql

– memcached

– nginx

Method 2:

Pass variables to roles.

– hosts: webservers

remote_user: root

roles:

– mysql

– { role: nginx, username: nginx } # Different roles call different variables

The key role is used to specify the role name.

The subsequent k/v is used to pass variables to the role.

Method 3: Roles can also be called based on conditional tests.

roles:

– { role: nginx, username: nginx, when: ansible_distribution_major_version == ‘7’ }

Passing variables/parameters through roles:

When applying a role to a host, variables can be passed, which can then be used within the role.

Example:

– hosts: webservers

roles:

– common

– { role: foo_app_instance, dir: ‘/web/htdocs/a.com’, port: 8080 }

Conditionally using roles:

– hosts: webservers

roles:

– { role: some_role, when: “ansible_os_family == ‘RedHat'” }

Variable calls:

– hosts: zabbix-proxy

sudo: yes

roles:

– { role: geerlingguy.php-mysql }

– { role: dj-wasabi.zabbix-proxy, zabbix_server_host: 192.168.37.167 }

Using Tags in Roles Playbook

Using tags in roles playbook.

ansible-playbook –tags=”nginx,httpd,mysql” nginx-role.yml to selectively execute tags.

// nginx-role.yml

– hosts: testweb

remote_user: root

roles:

– { role: nginx ,tags: [ ‘nginx’, ‘web’ ] ,when: ansible_distribution_major_version == “6” }

– { role: httpd ,tags: [ ‘httpd’, ‘web’ ] }

– { role: mysql ,tags: [ ‘mysql’, ‘db’ ] }

– { role: mariadb ,tags: [ ‘mysql’, ‘db’ ] }

– { role: php }

Creating the Memcached Role

Memcached is used as a cache, opening a space in memory to act as a cache.

cat /etc/sysconfig/memcached

PORT=”11211″

USER=”memcached”

MAXCONN=”1024″

CACHESIZE=”64″ # Default cache space 64M

OPTIONS=””

1> Create the corresponding directory.

cd /app/ansible

mkdir roles/memcached/{tasks,templates} -pv

2> Copy the memcached configuration file template.

cp /etc/sysconfig/memcached templates/memcached.j2

vim templates/memcached.j2

CACHESIZE=”{{ansible_memtotal_mb//4}}” # Use 1/4 of physical memory as cache.

3> Create the corresponding yml files and make the necessary configurations.

cd tasks/

touch install.yml config.yml service.yml

Create the main.yml file to define the order of task execution.

vim main.yml

– include: install.yml

– include: config.yml

– include: service.yml

vim install.yml

– name: install

yum: name=memcached

vim config.yml

– name: config file

template: src=memcached.j2 dest=/etc/sysconfig/memcached

vim service.yml

– name: service

service: name=memcached state=started enabled=yes

4> Create the file to call the role.

cd /app/ansible/roles/

vim role_memcached.yml

– hosts: appsrvs

roles:

– role: memcached

5> Install.

ansible-playbook role_memcached.yml

Other Functions

Delegation: delegate_to, local_action

delegate_to: In the playbook, when a task needs to be executed on a host that is not in the host group, this is used.

– name: delegate-test

shell: echo 1 >/root/1.txt

delegate_to: 192.168.1.2 # Can also write the hostname

Leave a Comment