• 重用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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这个任务用于安装一些常用的软件包,这些软件包在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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在上面的代码中,我们使用了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的目录,其默认包含了标准的角色目录结构。
    
    • 1
    • 2

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

    image-20230610155911393

    如果ansible.yaml 中要调用 role

    ---
    - hosts: test1
      remote_user: root
      roles:
       - myrole
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    ---
    
    - name: use param
      debug: 
       msg="{{ param }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用带有参数的role

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

    ---
    
    - hosts: test1
      remote_user: root
      roles:
       - role: myrole
         param: 'Test ansible'
       - role: myrole
         param: 'Test ansible2'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    role指定默认的参数

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

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

    main.yaml
      roles
        myrole
          tasks
            main.yaml
          defaults
            main.yaml
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在roles/myrole/defaults/main.yaml 中

    ---
    
    - hosts: test1
      remote_user: root
      roles:
       - role: myrole
       - role: myrole
         param: "I am the value from external"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    在前面的定义中,你会感到好奇,为什么文件夹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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    files下面的文件为

    <!DOCTYPE html>
    <html>
    <head>
    <title>hello world</title>
    </head>
    <body>
     hi I am csq
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    vars下面的文件为

    ---
    # http.conf vars
    http_port: 9999
    
    • 1
    • 2
    • 3

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    执行这个role

    ---
    
    - hosts: test1
      remote_user: root
      roles:
       - myrole
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    使用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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    那么,在 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

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

    dependencies:
    - { role: common }
    
    • 1
    • 2

    common 下面的main.yaml 内容为

    - name: xiugai quanxian
      command: chattr -a csq.txt
    
    • 1
    • 2

    web 下面的main.yaml 内容为

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

    db 下面的main.yaml 内容为

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

    playbook.yaml 内容为

    ---
    
    - hosts: test1
      remote_user: root
      roles:
       - common
       - db
       - web
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    执行结果

    [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   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

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

    [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
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    初识Java
    Vue3切换路由白屏刷新后才显示页面内容
    SpringBoot中Bean的创建过程及扩展操作点 @by_TWJ
    Canvas简历编辑器-我的剪贴板里究竟有什么数据
    百果园再冲刺港交所上市:扩张靠加盟和放贷,余惠勇夫妇为实控人
    为什么做接口测试?
    【网络层】动态路由算法、自治系统AS、IP数据报格式
    SHELL基础编程
    yolov5训练与模型量化
    OSPF协议LSDB同步过程和邻居状态机
  • 原文地址:https://blog.csdn.net/qq_52089863/article/details/131146509