目录

一. 前言

二. include介绍

2.1 include导入tasks

2.2 include时导入变量

2.3 inclued使用tag

2.4 include中使用循环

2.5 include使用条件判断

2.6 include 导入handlers

2.7 include 导入playbook

三. include_tasks介绍

3.1 include_tasks基本使用

3.2 include_tasks中使用tag

3.3 include与include_tasks的区别

四. import_tasks介绍

4.1 import_tasks使用

4.2 import_tasks与include_tasks的区别

4.3 关于import/include handler的说明


一. 前言

我们一直使用一个playbook文件来组织所有的task任务。但是,当我们项目越 来越大,task越来越多的时候,如果还将所有的task都写到一个playbook当中,可读性就会变差,这 个时候我们就需要重新来组织playbook了。

因此可以将一个大的playbook拆成若干个小的playbook文件,在主配置文件中将这些零碎的小文件 引入进来,引进方式就有:include,import,include_task,import_task

二. include介绍

ansible playbook的include功能就是直接使用include的关键字。

2.1 include导入tasks

我们在写大型的playbook的时候,通常多个playbook中会包含一部分相同的tasks,这个时候我们可以把相同的tasks,单独提取到一个yml文件中,然后通过include的方式进行导入。

示例:通过playbook安装lnmp和lamp

安装lamp

# [root@clinet ~]# cat lamp.yml‐ hosts: testgather_facts: notasks:‐ name:installmysqlpackage:name: mysqlstate: present- name: installphp-fpmpackage:name: php‐fpmstate: present- name: install httpdpackage:name: httpdstate: present

安装lnmp

#[root@clinet ~]# cat lnmp.yml‐ hosts: testgather_facts: notasks:‐ name:installmysqlpackage:name: mysqlstate: present- name: installphp-fpmpackage:name: php‐fpmstate: present- name: install httpdpackage:name: nginxstate: present

从上述两个安装方式中我们可以看到相关相同的tasks,分别为install mysql和installphp-fpm。因此我们可以将这两个tasks写入到一个yml文件中

#[root@clinet ~]#catinstall_sq_php.yml‐ name:installmysqlpackage:name: mysqlstate: present- name: installphp-fpmpackage:name: php‐fpmstate: present

使用include的方式

#[root@clinet ~]# cat lnmp.yml‐ hosts: testgather_facts: notasks:‐ name:installmysql and phpinclude:install_sq_php.yml #一般写绝对路径- name: install httpdpackage:name: nginxstate: present#[root@clinet ~]# cat lamp.yml‐ hosts: testgather_facts: notasks:‐ name:installmysql and phpinclude:install_sq_php.yml #一般写绝对路径- name: install httpdpackage:name: httpdstate: present

2.2 include时导入变量

方式一:在include引入yml文件的时候,直接给yml变量中的文件传值

[root@clinet include]# cat user.yml - name: debug user name info debug:msg: my name is '{{ user }}'[root@clinet include]#[root@clinet include]#
[root@clinet include]# cat include_user.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.yml user=xhz- name: include user yaml file2include: /root/ansible_test/ansible_2/yum_file/include/user.yml user=flf- name: include user yaml file2include: /root/ansible_test/ansible_2/yum_file/include/user.yml user=zzzz[root@clinet include]# 

方式二:通过vars的方式定义变量

[root@clinet include]# cat user.yml - name: debug user name info debug:msg: my name is '{{ user }}'[root@clinet include]#[root@clinet include]#
[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no vars:user: ehowehtasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.yml[root@clinet include]# [root@clinet include]#

方式三:在include引入task yml文件的时候在通过vars关键字进行定

[root@clinet include]# cat user.yml - name: debug user name info debug:msg: my name is '{{ user }}'[root@clinet include]#[root@clinet include]#
[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlvars:user: xhz123[root@clinet include]# [root@clinet include]# [root@clinet include]# 

2.3 inclued使用tag

include引入的tasks file中存在多个tasks,当我们给include打上标签之后,执行指定标签的include时候,此时针对的是引入的tasks file中的所有task。(即tasks file中的所有task都会被执行)

[root@clinet include]# cat user.yml- name: debug user name info debug:msg: my name is '{{ user }}'- name: debug debug:msg: "{{ user }}"[root@clinet include]# [root@clinet include]#
[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlvars:user: xhz123tags: t1[root@clinet include]# [root@clinet include]# [root@clinet include]# 

2.4 include中使用循环

在include(特殊的tasks)上使用循环和之前的tasks的循环没有区别,只是在include下使用的循环变量是在导入的tasks file中调用的而已。

[root@clinet include]# cat user.yml - name: debug debug:msg: "{{ item.key }} {{ item.value.name }} {{ item.value.passwd }}"loop: "{{user | dict2items }}"[root@clinet include]# [root@clinet include]#
[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlvars:user:xhz1:name: xiaohaizhoupasswd: 123flf:name: fulifangpasswd: 456[root@clinet include]# [root@clinet include]#

在上述示例中,loop循环是卸载include下的,思考一下,当导入的yaml文件中和include下都有loop循环的时候,此时导入的yaml文件中的变量调用是使用哪一个呢?示例如下:

导入的yaml文件:

[root@clinet include]# cat user.yml - name: debug debug:msg: "{{ item }}"loop: ['xhz1','xhz2','xhz3'][root@clinet include]# [root@clinet include]# 

执行的include yaml文件

[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlloop: ['flf1','flf2','flf3'][root@clinet include]# 

执行结果如下;

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.ymlPLAY [test] *********************************************************************************************************************************************************************************************TASK [include user yaml file1] **************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129TASK [debug] ********************************************************************************************************************************************************************************************[WARNING]: The loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions and unexpectedbehavior.ok: [192.168.194.129] => (item=xhz1) => {"msg": "xhz1"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "xhz2"}TASK [debug] ********************************************************************************************************************************************************************************************[WARNING]: The loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions and unexpectedbehavior.ok: [192.168.194.129] => (item=xhz1) => {"msg": "xhz1"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "xhz2"}TASK [debug] ********************************************************************************************************************************************************************************************[WARNING]: The loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions and unexpectedbehavior.ok: [192.168.194.129] => (item=xhz1) => {"msg": "xhz1"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "xhz2"}PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=6changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

结论:

当执行的include yaml文件和被include导入的yaml文件中同时存在loop循环时,变量会使用被include导入的yaml文件中的值。

使用loop_control关键字,让其调用include yaml文件中的变量值

导入的yaml文件:

[root@clinet include]# cat user.yml - name: debug debug:msg: "{{ other_item1 }}"loop: ['xhz1','xhz2','xhz3'][root@clinet include]# [root@clinet include]# 

执行的include文件:

[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlloop: ['flf1','flf2','flf3']loop_control:loop_var: outer_item1[root@clinet include]#

执行结果:

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.ymlPLAY [test] *********************************************************************************************************************************************************************************************TASK [include user yaml file1] **************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129TASK [debug] ********************************************************************************************************************************************************************************************ok: [192.168.194.129] => (item=xhz1) => {"msg": "flf1"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "flf1"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "flf1"}TASK [debug] ********************************************************************************************************************************************************************************************ok: [192.168.194.129] => (item=xhz1) => {"msg": "flf2"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "flf2"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "flf2"}TASK [debug] ********************************************************************************************************************************************************************************************ok: [192.168.194.129] => (item=xhz1) => {"msg": "flf3"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "flf3"}ok: [192.168.194.129] => (item=xhz2) => {"msg": "flf3"}PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=6changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

可以看到, outer_item 中的值正是外层循环中item的值。当出现这个双层循环时,可以在外层循环 中使用 loop_var 选项指定一个变量,这个变量用于替代外层循环中的item变量,以便在内层循环中 获取到外层循环的item的值,从而避免两层循环中item变量名的冲突。

2.5 include使用条件判断

当条件成立的时候,才执行include语句。

[root@clinet include]# cat user.yml - name: debug debug:msg: "{{ item.key }} {{ item.value.name }} {{ item.value.passwd }}"loop: "{{user | dict2items }}"[root@clinet include]# [root@clinet include]#
[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlvars:user:xhz1:name: xiaohaizhoupasswd: 123flf:name: fulifangpasswd: 456when: 1 > 2[root@clinet include]# [root@clinet include]#

2.6 include 导入handlers

handlers include 和tasks include大体一致,就是将hanlers要执行的tasks写入到yaml文件中,然后再handlers下通过include进行导入,示例如下:

[root@clinet include]# cat handler.yml - name: restart apacheservice:name: apachestate: restarted[root@clinet include]# [root@clinet include]#
[root@clinet include]# cat include_handler.yml - hosts: testgather_facts: no tasks:.....handlers:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/handler.yml[root@clinet include]#

2.7 include 导入playbook

通过include将一个playbook导入到另外一个playbook中。

[root@clinet include]# cat include_handler.yml - hosts: testgather_facts: no tasks:- name: includeplaybookinclude: /root/ansible_test/ansible_2/yum_file/include/playbook.yml

三. include_tasks介绍

3.1 include_tasks基本使用

前面我们详细说了include的用法,然而事实上在后续的ansible版本当中,include语法可能会被弃 用。而使用一些新的关键字来代替include的原始用法,include_tasks就是其中之一。
我们知道include可以用于包含tasks,handlers,playbooks等,而include_tasks则专门用于导入包含 tasks的yaml文件的。

[root@clinet include]# cat user.yml - name: debug info1 debug:msg: "task1 in user.yaml"- name: debug info2debug:msg: "task2 in user.yaml"[root@clinet include]# [root@clinet include]#[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: xhz1debug:msg: 'task1'- name: includeinclude_tasks: ./user.yml- name: xhz2debug:msg: 'task2'[root@clinet include]#
include_tasks还可以写成- name: include info include_tasks:file: ./user.yml

执行结果

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.ymlPLAY [test] *********************************************************************************************************************************************************************************************TASK [xhz1] *********************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task1"}TASK [include] ******************************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129TASK [debug info1] **************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task1 in user.yaml"}TASK [debug info2] **************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task2 in user.yaml"}TASK [xhz2] *********************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task2"}PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=5changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

可以看到,当我们使用 include_tasks 时, include_tasks 本身会被当做一个task,这个task会把 include的文件的路径输出在控制台中中, 这就是 include_tasks 和 include 之间的区别。include是 透明的,而 include_tasks 是可见的, include_tasks 更像是一个任务,这个任务包含了其他的一些 任务。

3.2 include_tasks中使用tag

在前面我们提到过,如果为include添加tags,那么tags是对include中所有任务生效的。也就是说, 如果调用include对应的tag,那么include文件中的所有任务都会执行。

但是对 include_tasks 添加tags,则只会对 include_tasks 本身生效, include_tasks 中所有的任务 都不生效。

[root@clinet include]# cat user.yml - name: debug info1 debug:msg: "task1 in user.yaml"- name: debug info2debug:msg: "task2 in user.yaml"[root@clinet include]# [root@clinet include]# [root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: xhz1debug:msg: 'task1'- name: includeinclude_tasks: ./user.ymltags: t1- name: xhz2debug:msg: 'task2'[root@clinet include]# 

执行结果

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.yml --tags=t1PLAY [test] *********************************************************************************************************************************************************************************************TASK [include] ******************************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=1changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

如果想要tags对 include_tasks 中包含的所有任务生效,则需要使用 include_tasks 模块的apply参数 并配合 tags: always 内置tag:

[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: xhz1debug:msg: 'task1'- name: includeinclude_tasks: file: ./user.ymlapply:tags: t1tags: always- name: xhz2debug:msg: 'task2'[root@clinet include]# [root@clinet include]# 

执行结果:

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.yml --tags=t1PLAY [test] *********************************************************************************************************************************************************************************************TASK [include] ******************************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129TASK [debug info1] **************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task1 in user.yaml"}TASK [debug info2] **************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task2 in user.yaml"}PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=3changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

需要说明的是,在这里, tags: always 标签只针对 include_tasks 本身生效,也就是说,如果其他任 务的标签被调用, include_tasks 本身会被调用,而其包含的任务不会被调用。

例如我们直接调用always的标签,include_tasks会被调用,但是其包含的任务还是不会被调用,执行结果如下:

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.yml --tags=alwaysPLAY [test] *********************************************************************************************************************************************************************************************TASK [include] ******************************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=1changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# [root@clinet ansible_2]# 

如果要想其包含的任 务也总是被调用,则需要给apply中加上always的标签,可修改配置如下:

[root@clinet include]# cat include_user2.yml - hosts: testgather_facts: no tasks:- name: xhz1debug:msg: 'task1'- name: includeinclude_tasks: file: ./user.ymlapply:tags: t1,alwaystags: always- name: xhz2debug:msg: 'task2'[root@clinet include]# 

执行结果如下:

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user2.yml --tags=alwaysPLAY [test] *********************************************************************************************************************************************************************************************TASK [include] ******************************************************************************************************************************************************************************************included: /root/ansible_test/ansible_2/yum_file/include/user.yml for 192.168.194.129TASK [debug info1] **************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task1 in user.yaml"}TASK [debug info2] **************************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "task2 in user.yaml"}PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=3changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

3.3 include与include_tasks的区别

1.include是 透明的,不会吧include的文件路径输出在控制台上;而 include_tasks 是可见的,会将文件路径输出在控制台上。

2. 为include添加的tags,那么tags是对include中所有任务生效;而include_tasks不会对include_tasks中的所有任务都生效,需要apply参数和always内置标签的配合。

四. import_tasks介绍

4.1 import_tasks使用

import_tasks与include_tasks的用法类似,只是将关键字修改为import_tasks即可。

[root@clinet include]# cat include_user.yml - hosts: testgather_facts: no tasks:- name: include user yaml file1 include: /root/ansible_test/ansible_2/yum_file/include/user.ymlvars:user: xhz[root@clinet include]# [root@clinet include]# cat user.yml - name: debug user infodebug:msg: "{{ user }}"[root@clinet include]#[root@clinet include]#

执行结果:

[root@clinet ansible_2]# ansible-playbook yum_file/include/include_user.ymlPLAY [test] *********************************************************************************************************************************************************************************************TASK [debug user info] **********************************************************************************************************************************************************************************ok: [192.168.194.129] => {"msg": "xhz"}PLAY RECAP **********************************************************************************************************************************************************************************************192.168.194.129: ok=1changed=0unreachable=0failed=0skipped=0rescued=0ignored=0 [root@clinet ansible_2]# 

可以看到, import_tasks 模块并不会像 include_tasks 模块一样,在控制台输出自身的任务信息,其 相对透明。

4.2 import_tasks与include_tasks的区别

1.import_tasks 模块并不会像 include_tasks 模块一样,在控制台输出自身的任务信息与任务路径等。

2.import_tasks 是静态的,被import的文件在playbook被加载时就预处理了,而 include_tasks 是动态的,被include的文件在playbook被运行时候才开始处理。

3.如果想要对包含的任务列表进行循环操作,则只能使用 include_tasks , import_tasks 不支持循 环操作。也就是说,使用 loop 或者 with_X 对include文件进行循环操作时,只能配合 include_tasks 才能正常使用。

4.当使用when对include文件添加条件判断时, include_tasks 和 import_tasks 有着本质的不 同:

· 当对 include_tasks 使用when时,when对应的条件只会应用于 include_tasks 任务本身,当执 行被包含的任务时,不会对这些被包含的任务重新进行条件判断

· 当对 import_tasks 使用when时,when对应的条件会被应用于被import的文件中的每一个任 务,当执行被import的任务时,会对每一个被包含的任务进行同样的条件判断。

因此我们在纠结到底是使用include还是include_tasks还是import_tasks的时候,直接使用include_tasks就对了,你甚至可以忘记include和import_tasks的存在。

4.3 关于import/include handler的说明

handlers中执行的其实也是任务,只不过是被触发才会运行,所以如果要在handlers中引 入任务,也可直接使用 include_tasks 和 import_tasks 。没有 include_handlers 的说法。因此统一说法:直接使用include_tasks