Ansible的重用(include和import)

环境

  • 管理节点:Ubuntu 22.04
  • 控制节点:CentOS 8
  • Ansible:2.15.6

重用

Ansible提供四种可重用的工件:

  • variable文件:只包含变量的文件
  • task文件:只包含task的文件
  • playbook:可包含play、变量、task,以及其它内容
  • role:包含一套task、变量、default、handler,甚至module或其它plugin(通过目录/文件树的结构来组织)

重用playbook

可以通过 import_playbook 把多个playbook集成到一个主playbook里。

创建文件 test1.ym 如下:

---
- import_playbook: playbook1.yml
- import_playbook: playbook2.yml

创建文件 playbook1.yml 如下:

---
- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "hello"

创建文件 playbook2.yml 如下:

---
- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "world"

运行结果如下:

PLAY [all] *****************************************************************************************

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

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
    "msg": "hello"
}

PLAY [all] *****************************************************************************************

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

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
    "msg": "world"
}

PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

import_playbook 是静态引入的,也就是说,相当于在主playbook里直接定义 playbook1playbook2 的内容:

---
- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "hello"

- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "world"

下面是一个使用变量的例子。创建文件 test2.yml 如下:

---
- import_playbook: "{{ var1 }}"
  vars:
    var1: "playbook1.yml"
- import_playbook: "{{ var2 }}"

运行时通过命令行的 -e 选项指定变量 var2 ,即: ansible-playbook test2.yml -e var2=playbook2.yml

运行结果如下:

PLAY [all] *****************************************************************************************

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

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
    "msg": "hello"
}

PLAY [all] *****************************************************************************************

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

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
    "msg": "world"
}

PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

可见,可通过两种方式指定变量:

  • vars
  • -e

注意:这两种方式其实也是“静态”定义的变量,也就是在刚开始运行时,值就已经确定的变量。

无法使用动态变量。看下面的例子:

创建文件 test3.yml 如下:

---
- hosts: all
  tasks:
    - name: task1
      set_fact:
        var3: "playbook3.yml"

- import_playbook: playbook3.yml

创建文件 playbook3.yml 如下:

---
- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "{{ var3 }}"

运行结果如下:

TASK [task1] ***************************************************************************************
ok: [192.168.1.55]

PLAY [all] *****************************************************************************************

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

TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
    "msg": "playbook3.yml"
}

可见,通过 set_fact 定义的变量,可以传到 import_playbook 所引入的playbook里。

但是如果改为下面的写法:

---
- hosts: all
  tasks:
    - name: task1
      set_fact:
        var3: "playbook3.yml"

#- import_playbook: playbook3.yml
- import_playbook: "{{ var3 }}"

运行结果如下:

ERROR! 'var3' is undefined. 'var3' is undefined

这是因为, var3 是动态定义的变量, import_playbook 只能使用静态变量(在刚开始运行时就有值)。

使用role

当playbook较复杂时,使用role会好一些。role把default、handler、变量、task存放到不同目录下,以便于理解和维护。

详见关于role的文档。

重用role,task和变量

  • 动态重用( include_* ):
    • include_role
    • include_tasks
    • include_vars
  • 静态重用( import_* ):
    • import_role
    • import_tasks

include_*

一句话总结:在运行到此处时才动态引入。

import_*

一句话总结:在刚开始运行时就替换为引入的内容。

另:文档上说如果要多次import同一个文件,必须传入变量( You can pass variables to imports. You must pass variables if you want to run an imported file more than once in a playbook. ),但我试了一下,不传变量也没问题,是不是我理解有误?

---
- hosts: all
  tasks:
    - import_tasks: task1.yml
    - import_tasks: task1.yml

include和import的区别

Ansible的重用(include和import)_第1张图片

在handler中重用task

在handler里也可以使用include或import。但要注意它们的区别:

  • include:notify的是handler本身(也就是include的文件),会触发其包含的所有task。
  • import:notify的是import的文件里的某些task。

include

创建 test5.yml 如下:

---
- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "I am task1"
      changed_when: true
      notify: handler1

  handlers:
    - name: handler1
      include_tasks: task5.yml

创建 task5.yml 如下:

---
- name: task5_task1
  debug:
    msg: "I am task5_task1"

- name: task5_task2
  debug:
    msg: "I am task5_task2"

运行结果如下:

TASK [task1] ***************************************************************************************
changed: [192.168.1.55] => {
    "msg": "I am task1"
}

RUNNING HANDLER [handler1] *************************************************************************
included: /root/temp/temp1127/task5.yml for 192.168.1.55

RUNNING HANDLER [task5_task1] **********************************************************************
ok: [192.168.1.55] => {
    "msg": "I am task5_task1"
}

RUNNING HANDLER [task5_task2] **********************************************************************
ok: [192.168.1.55] => {
    "msg": "I am task5_task2"
}

可见,notify的是 handler1 ,其代表 task5.yml ,其中所有task都会运行。

import

创建文件 test6.yml 如下:

---
- hosts: all
  tasks:
    - name: task1
      debug:
        msg: "I am task1"
      changed_when: true
      notify: task5_task2

  handlers:
    - name: handler1
      import_tasks: task5.yml

task5.yml 内容不变。

运行结果如下:

TASK [task1] ***************************************************************************************
changed: [192.168.1.55] => {
    "msg": "I am task1"
}

RUNNING HANDLER [task5_task2] **********************************************************************
ok: [192.168.1.55] => {
    "msg": "I am task5_task2"
}

可见,notify的是 task5_task2 ,它是 task5.yml 里的一个task,只有它会运行

参考

  • https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse.html

你可能感兴趣的:(Ansible,ansible)