重用Playbook

重用Playbook

Ansible支持的两种重用机制是Roles和Includes。

  • Roles是一种可重用的任务和变量的集合,是一种类似于编程语言中的包的概念

  • Includes则是一种将一个Playbook分解成多个文件的方法,可以将一些常用的任务和变量放在单独的文件中,然后在需要的Playbook中引用这些文件。

include语句

在Ansible中,可以使用include关键字将一个或多个文件引入到一个Playbook中,从而实现代码重用的目的。通过将常用的、通用的任务写在一个文件中,可以避免在每个Playbook中重复编写这些任务的代码,大大减少了工作量。此外,使用include语句还可以提高代码的可读性和可理解性,因为将通用的代码抽象出来,使得Playbook的代码更加简洁清晰,易于维护和更新。同时,使用include语句还有助于降低代码的耦合性,因为将常用的任务抽象出来,可以使得不同的Playbook之间的依赖关系更加清晰明了,从而避免代码耦合度过高的问题。

以下是一个使用include语句的简单案例:

假设我们有一个ansible项目,其中使用了两个Playbook:web.yaml和db.yaml,它们分别用于部署Web服务器和数据库服务器。现在我们想要在这两个Playbook中引入一个共同的任务文件:common.yaml,以避免在两个Playbook中重复编写相同的任务代码。

首先,在项目的根目录下创建一个名为tasks的文件夹,用于存放共同的任务文件common.yml。然后在该文件夹下创建一个名为common.yml的文件,内容如下:

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

这个任务用于安装一些常用的软件包,这些软件包在Web服务器和数据库服务器中都需要安装。

接下来,我们可以在web.yaml和db.yaml中使用include语句来引入该文件,代码如下:

web.yaml文件:

- 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文件:

- 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

在上面的代码中,我们使用了include语句来引入tasks/common.yml文件中的任务,这样就避免了在web.yaml和db.yaml中重复编写安装常用软件包的任务代码。

如何写role

role有比include更强大灵活的代码重用和分享机制。include类似于编程语言中的include,是重用单个文件的,重用的功能有限。

而role类似于编程语言中的 “Package”,可以重用一组文件,形成完整的功能。例如,安装和配置Apache,既需要任务实现安装包和复制模板,也需要httpd.conf 和 index.html 的模板文件,以及handler文件实现的重启功能。这些文件都可以放在一个role里面,以供不同的Playbook文件重用

定义role完整的目录结构

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

那么如何创建角色目录呢?

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

一个标准的角色目录结构如下:

image-20230610155911393

如果ansible.yaml 中要调用 role

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

Ansible 并不要求role包含上述所有的目录及文件,可以根据role的功能,加入对应的目录和文件即可。下面是每个目录和文件的功能:

  • tasks目录:存放角色的任务文件,其中main.yaml是必须的,其他任务文件可按需添加。
  • templates目录:存放角色使用的Jinja2模板文件。
  • files目录:存放角色使用的普通文件。
  • vars目录:存放角色使用的变量文件,其中main.yaml是必须的,其他变量文件可按需添加。
  • defaults目录:存放角色的默认变量,其中main.yaml是必须的,其他默认变量文件可按需添加。
  • meta目录:存放角色的元数据文件,包括角色名称、作者、依赖等信息。
  • handlers目录:存放角色的处理程序,其中main.yaml是必须的,其他处理程序可按需添加。
  • README.md:角色的说明文件,包括角色的用途、使用方法等信息。
  • tests目录,包含了以下文件:
    • inventory:角色的测试用例的主机清单文件,定义了测试用例中需要使用的主机和主机组等信息。
    • test.yaml:角色的测试用例文件,定义了测试用例中需要执行的任务和测试方法等信息。

此外,下面的文件不需要绝对或者是相对路径,和放在同一目录下的文件一样,直接使用即可

copy 或 scipt 使用 roles/x/files/下的文件

template使用roles/x/templates下的文件

include使用roles/x/tasks下的文件

而在写role的时候,一般要包含role入口文件 roles/x/tasks/main.yaml,其他的文件和目录,可以根据自己需求选择是否加入

带参数的role

下面定义了一个带参数的role,名字myrole,其目录结构如下

main.yaml
  roles
    myrole
      tasks
        main.yaml

在roles/myrole/tasks/main.yaml中,使用{ { }}定义的变量就可以了

---

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

使用带有参数的role

在main.yaml中可以用如下的方法使用myrole了

---

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

role指定默认的参数

指定默认的参数后,如果在调用时传参数,那么就使用传入的参数值,如果在调用的时候没有传参数,那么就使用默认的参数值

指定默认的参数很简单,一上面的参数为例

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

在roles/myrole/defaults/main.yaml 中

---

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

默认变量和普通变量的区别

在前面的定义中,你会感到好奇,为什么文件夹default和vars下面的变量都会加到Play中,它们由上面区别吗?

default/main.yaml 中的是默认变量。优先级在所有的变量中是最低的,用于放置一些需要被覆盖的变量

vars/main.yaml 中的变量是role变量,优先级比较高,放置一些不想被覆盖的变量,所以变量在命名的时候一般都加入role的名字作为前缀,放置不小心被Playbook中定义的变量覆盖

tasks/main.yaml 如何使用变量、静态文件和模板

任务是Playbook和role的核心,role是一种组织Playbook的方式,包含任务、模板、变量和文件等资源。在role中,任务文件tasks/main.yaml是入口文件,其中可以使用变量、静态文件和模板等资源。学会如何使用这些资源是编写role的关键。

role中的资源可以分为两类

  • 一类是自动加载的,通常放在x/*/main.yaml中
  • 另一类是需要显式调用的,通常放在x/*/other_but_main.yaml中。

使用x/*/main.yaml中的变量

使用x/*/main.yaml中的变量和handler

像使用同一个Playbook中的资源一样使用x/*/main.yaml中的变量和handler

使用x/{files,template}/下的文件

像使用同一个目录下的文件一样来使用放在这里的变量。需要模块和使用的文件类型要匹配

copy 、script对应files目录下的文件

template对应templates下的文件

比如,role x 的目录如下

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

files下面的文件为

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

vars下面的文件为

---
# http.conf vars
http_port: 9999

tasks下的文件为

---
- 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

执行这个role

---

- hosts: test1
  remote_user: root
  roles:
   - myrole

使用x/*/other_but_main.yaml中的资源

如果 role x 下面的内容比较复杂,需要对任务或者 vars 进一步2分类,可以使用除 main.yaml 以外的文件外。应如何使用其他文件中的任务或者 vars 呢?Ansible 提供了两个关键字:include 和 include_vars ,分别来引入 role 中非 main.yaml 其他文件包含的任务和vars

例如,在下面的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

那么,在 x/*/main.yaml中,通过 include_var来引入httpd的变量后,即可通过include来加载文件install.yaml和configure.yaml中的任务

---
- 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的依赖

安装一个Nginx 需要配置 yum仓库,如果不想在配置Nginx 的Playbook重新实现配置 yum 仓库的功能,那么就可以通过role的依赖来解决。role依赖关系的定义文件是x/meta/main.yaml。如果在 role x定义依赖 role y,那么在Playbook中调用 role x之前会先调用 role y。当多个 role 依赖同一个role时,Ansible会自动进行过滤,避免重复调用相同参数的role

在下面的例子中,role db 和Web都依赖role common。如果在Playbook中调用db和Web,那么Ansible会保证在role db和 Web运行前,先运行 role common ,并且只运行一次

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

在{web,db}/meta/main.yaml中添加

dependencies:
- {
    
     role: common }

common 下面的main.yaml 内容为

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

web 下面的main.yaml 内容为

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

db 下面的main.yaml 内容为

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

playbook.yaml 内容为

---

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

执行结果

[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   

然后查看一下 远程主机内容是否改变,以及隐藏权限是否还在

[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

猜你喜欢

转载自blog.csdn.net/qq_52089863/article/details/131146509