Reuse Playbooks

Reuse Playbooks

The two reuse mechanisms supported by Ansible are Roles and Includes.

  • RolesIt is a collection of reusable tasks and variables, a concept similar to packages in programming languages.

  • IncludesIt is a method of decomposing a Playbook into multiple files. You can put some commonly used tasks and variables in separate files, and then reference these files in the required Playbook.

include statement

In Ansible, you can use the include keyword to introduce one or more files into a playbook to achieve 重用the purpose of the code. By writing commonly used and common tasks in one file, the codes for these tasks can be included 避免in each Playbook 重复编写, greatly reducing the workload. In addition, using include statements is okay 提高代码的可读性和可理解性because common code is abstracted away 使得Playbook的代码更加简洁清晰,易于维护和更新. At the same time, using the include statement is also helpful 降低代码的耦合性, because abstracting common tasks can make the dependencies between different Playbooks clearer, thereby avoiding the problem of excessive code coupling.

The following is a simple example using the include statement:

Suppose we have an ansible project in which two playbooks are used: web.yaml and db.yaml, which are used to deploy the web server and database server respectively. Now we want to introduce a common task file: common.yaml into the two Playbooks to avoid repeatedly writing the same task code in the two Playbooks.

First, create a folder named tasks in the root directory of the project to store the common task file common.yml. Then create a file named common.yml in the folder with the following content:

  - name: install packages
    remote_user: root
    yum:
     name: git,vim,curl,wget,unzip,zip,net-tools
     state: present

This task is used to install some commonly used software packages, which need to be installed in both web servers and database servers.

Next, we can use the include statement in web.yaml and db.yaml to introduce the file. The code is as follows:

web.yaml file:

- name: Deploy web server
  hosts: test1
  tasks:
  - include: tasks/common.yaml
  - name: install and configure Apache
    yum:
     name: httpd
     state: present
  - service:
     name: httpd
     enabled: true
     state: started

db.yaml file:

- name: Deploy database server
  hosts: test2
  tasks:
  - include: tasks/common.yaml
  - name: install and configure Mysql
    yum:
     name: mariadb-server
     state: present
  - service:
     name: mariadb
     enabled: true
     state: started

In the above code, we use the include statement to introduce the tasks in the tasks/common.yml file. This avoids repeatedly writing task codes for installing common software packages in web.yaml and db.yaml.

How to write role

Role has a more powerful and flexible code reuse and sharing mechanism than include. include is similar to include in programming languages. It reuses a single file and has limited reuse functions.

The role is similar to a "Package" in a programming language, which can reuse a set of files to form a complete function. For example, installing and configuring Apache requires not only tasks to implement the installation package and copy templates, but also template files for httpd.conf and index.html, as well as the restart function implemented by the handler file. These files can be placed in a role for reuse in different Playbook files.

Define the complete directory structure of the role

在Ansible中,通过遵循特定的目录结构,就可以实现对role定义。

So how do you create a role directory?

ansible-galaxy init myrole
# 上述命令会在当前目录下创建一个名为myrole的目录,其默认包含了标准的角色目录结构。

A standard role directory structure is as follows:

image-20230610155911393

If you want to call role in ansible.yaml

---
- hosts: test1
  remote_user: root
  roles:
   - myrole

Ansible does not require the role to contain all the above directories and files. You can add the corresponding directories and files according to the function of the role. Here are the functions of each directory and file:

  • tasks directory: stores role task files, which main.yamlare required. Other task files can be added as needed.
  • templates directory: stores Jinja2 template files used by roles.
  • files directory: stores ordinary files used by characters.
  • vars directory: stores the variable files used by the role, which main.yamlare required. Other variable files can be added as needed.
  • defaults directory: stores the default variables of the role, which main.yamlare required. Other default variable files can be added as needed.
  • meta directory: stores character metadata files, including character name, author, dependencies and other information.
  • handlers directory: stores role handlers, which main.yamlare required, and other handlers can be added as needed.
  • README.md: The description file of the role, including the purpose of the role, how to use it, and other information.
  • The tests directory contains the following files:
    • inventory: The host list file of the role's test case, which defines the host and host group information that needs to be used in the test case.
    • test.yaml: The test case file of the role, which defines the tasks and test methods that need to be performed in the test case.

In addition, the following files do not need to be absolute or relative paths. They can be used directly just like files placed in the same directory.

copy or scipt uses files under roles/x/files/

Template uses files under roles/x/templates

include uses files under roles/x/tasks

When writing a role, the role entry file roles/x/tasks/main.yaml should generally be included. Other files and directories can be added according to your own needs.

role with parameters

The following defines a role with parameters, named myrole, and its directory structure is as follows

main.yaml
  roles
    myrole
      tasks
        main.yaml

In roles/myrole/tasks/main.yaml, just use the variables defined by { { }}

---

- name: use param
  debug: 
   msg="{
    
    { param }}"

Use role with parameters

In main.yaml, you can use myrole as follows:

---

- hosts: test1
  remote_user: root
  roles:
   - role: myrole
     param: 'Test ansible'
   - role: myrole
     param: 'Test ansible2'

role specifies default parameters

After specifying the default parameters, if parameters are passed when calling, then the passed parameter values ​​will be used. If no parameters are passed when calling, then the default parameter values ​​will be used.

Specifying default parameters is very simple, take the above parameters as an example

main.yaml
  roles
    myrole
      tasks
        main.yaml
      defaults
        main.yaml

In roles/myrole/defaults/main.yaml

---

- hosts: test1
  remote_user: root
  roles:
   - role: myrole
   - role: myrole
     param: "I am the value from external"

The difference between default variables and ordinary variables

In the previous definition, you may be curious why the variables under the folder default and vars are added to Play. Are they different from the above?

default/main.yaml are default variables. The priority is the lowest among all variables and is used to place some variables that need to be overwritten.

The variables in vars/main.yaml are role variables with relatively high priority. Some variables are placed that do not want to be overwritten. Therefore, the name of the role is generally added as a prefix when naming the variables. If placed, they may be accidentally overwritten by variables defined in the Playbook.

tasks/main.yaml How to use variables, static files and templates

Tasks are the core of Playbooks and roles. Roles are a way to organize Playbooks and include resources such as tasks, templates, variables, and files. In the role, the task file tasks/main.yaml is the entry file, in which resources such as variables, static files, and templates can be used. Learning how to use these resources is the key to writing roles.

The resources in role can be divided into two categories:

  • One class is automatically loaded and usually placed in x/*/main.yaml
  • The other type needs to be called explicitly, usually placed in x/*/other_but_main.yaml.

Use variables in x/*/main.yaml

Use variables and handlers in x/*/main.yaml

Use variables and handlers in x/*/main.yaml just like resources in the same Playbook

Use files under x/{files,template}/

Use variables placed here as if they were files in the same directory. Requires the module and the file type used to match

copy and script correspond to files in the files directory

template corresponds to the file under templates

For example, the directory of role x is as follows

[root@localhost ansible]# tree myrole/
myrole/
├── files
│   └── index.html
├── tasks
│   └── main.yml
├── templates
│   └── httpd.conf.j2
└── vars
    └── main.yml

The files below files are

<!DOCTYPE html>
<html>
<head>
<title>hello world</title>
</head>
<body>
 hi I am csq
</body>
</html>

The files under vars are

---
# http.conf vars
http_port: 9999

The files under tasks are

---
- name: Deploy server web
  yum: 
   name: httpd
   state: present
- name: copy index.html
  copy: 
   src: index.html
   dest: /var/www/html/index.html
- name: copy http.conf
  template:
   src: httpd.conf.j2
   dest: /etc/httpd/conf/httpd.conf
- name: service restart
  service:
   name: httpd
   enabled: true
   state: restarted
- name: Release Port
  firewalld:
   port: 9999/tcp
   permanent: true
   state: enabled

Execute this role

---

- hosts: test1
  remote_user: root
  roles:
   - myrole

Use resources from x/*/other_but_main.yaml

If the content below role x is more complex and you need to further classify tasks or vars, you can use files other than main.yaml. How should I use tasks or vars from other files? Ansible provides two keywords: include and include_vars, which are used to introduce tasks and vars contained in other files other than main.yaml in the role.

For example, in the following role

myrole/
├── tasks
│   └── main.yml
│   └── http_install.yaml
│   └── http_configure.yaml
│   └── mysql_install.yaml
│   └── mysql_configure.yaml
├── templates
│   └── httpd.conf.j2
│   └── mysql.conf.j2
└── vars
    └── httpd.yaml
    └── mysql.yaml

Then, in x/*/main.yaml, after introducing the httpd variables through include_var, you can load the tasks in the files install.yaml and configure.yaml through include.

---
- name: add the os specific varibles
  include_vars: httpd.yaml
- name: install packages
  yum:
   name: {
    
    {
    
    packages}}
   state: present
- include: http_install.yaml
- include: http_configure.yaml

role dependencies

Installing an Nginx requires configuring the yum repository. If you do not want to re-implement the function of configuring the yum repository in the Nginx Playbook, you can solve it through role dependencies. The definition file of role dependency is x/meta/main.yaml. If role x is defined as dependent on role y, role y will be called before role x is called in the Playbook. When multiple roles depend on the same role, Ansible will automatically filter to avoid repeatedly calling roles with the same parameters.

In the following example, both role db and Web depend on role common. If db and Web are called in the Playbook, Ansible will ensure that role common is run first and only once before role db and Web are run.

playbook.yaml
roles
├── common
│   └── tasks
│       └── main.yaml
├── db
│   ├── meta
│   │   └── main.yaml
│   └── tasks
│       └── main.yaml
└── web
    ├── meta
    │   └── main.yaml
    └── tasks
        └── main.yaml

Add in {web,db}/meta/main.yaml

dependencies:
- {
    
     role: common }

The content of main.yaml below common is

- name: xiugai quanxian
  command: chattr -a csq.txt

The content of main.yaml below web is

- name: shuru xinxi
  shell: echo "I am web,hi csq" >> csq.txt
- name: jia quanxian
  command: chattr +a csq.txt

The content of main.yaml below db is

- name: shuru xinxi
  shell: echo "I am db,hi csq" >> csq.txt
- name: jia quanxian
  command: chattr +a csq.txt

The content of playbook.yaml is

---

- hosts: test1
  remote_user: root
  roles:
   - common
   - db
   - web

Results of the

[root@localhost ansible]# ansible-playbook main.yaml 

PLAY [test1] ***********************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************
ok: [192.168.200.30]

TASK [common : xiugai quanxian] ****************************************************************************************************************************
changed: [192.168.200.30]

TASK [db : shuru xinxi] ************************************************************************************************************************************
changed: [192.168.200.30]

TASK [db : jia quanxian] ***********************************************************************************************************************************
changed: [192.168.200.30]

TASK [web : shuru xinxi] ***********************************************************************************************************************************
changed: [192.168.200.30]

TASK [web : jia quanxian] **********************************************************************************************************************************
changed: [192.168.200.30]

PLAY RECAP *************************************************************************************************************************************************
192.168.200.30             : ok=6    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Then check whether the content of the remote host has changed and whether the hidden permissions are still there

[root@localhost ansible]# ansible test1 -m shell -a "cat csq.txt &&  lsattr  csq.txt"
192.168.200.30 | CHANGED | rc=0 >>
I am web,hi csq
I am web,hi csq
-----a---------- csq.txt

Guess you like

Origin blog.csdn.net/qq_52089863/article/details/131146509