设为首页 收藏本站
查看: 1335|回复: 0

[经验分享] 自动化运维工具Ansible之Playbooks的roles和include

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-7-31 09:23:50 | 显示全部楼层 |阅读模式
当需要对多个远程节点,做很多操作的时候,如果将所有的内容都书写到一个playbooks中,这就会产生一个很大的文件,而且里面的某些内容也很难复用。此时不得不考虑怎么样分隔及组织相关的文件。


最基本的,可以将任务列表单独分隔到一个小文件里,然后在tasks中包含该文件即可。同样的handlers其实也是一个任务列表(里面指定的任务都需要有一个全局唯一的名称),所以也可以在handlers中包含单独定义好的handlers任务文件。

playbooks也可以包含其他playbooks文件。

playbooks中的文件包含使得你在大多数情况下并不需要考虑具体功能的实现细节,只需要复用某些已有的文件即可,类似于编程中的封装概念一样,当某个功能封装并测试OK以后,在需要的地方调用即可,如,一个人会开车,但他并不需要了解发动机的原理是什么。


Ansible中的“角色”就是利用文件包含这个功能来使得文件组织的更加清晰明了,并具有很高的复用性。


任务文件包含和重用

如果想在多个playbooks之间服用任务列表,那么include将会是个很好的方法。

官方示例的一个很小的任务列表文件:


1
2
3
4
5
6
7
8
    ---
    # possibly saved as tasks/foo.yml
     
    - name: placeholder foo
      command: /bin/foo
     
    - name: placeholder bar
      command: /bin/bar



在playbooks中包含该文件:

1
2
3
tasks:
     
      - include: tasks/foo.yml





同时也可以向包含文件内传递参数,称为“参数化包含”。

例如,想要部署多个wordpress,可以将部署操作写到一个文件中,保存为wordpress.yml,然后以下边这样包含文件并传递参数:

1
2
3
4
    tasks:
      - include: wordpress.yml wp_user=timmy
      - include: wordpress.yml wp_user=alice
      - include: wordpress.yml wp_user=bob



在wordpress.yml可以{{ wp_user }}的方式使用变量。

还可以传递一个参数列表:

1
2
    tasks:
     - { include: wordpress.yml, wp_user: timmy, ssh_keys: [ 'keys/one.txt', 'keys/two.txt' ] }



以上两种传递参数都称为显式传参,在vars中定义的变量特可以在被包含文件中使用。


也可以在handlers中包含文件。如,想要定义一个重启apache的handler,这时候只需要为所有的playbooks定义一个handler即可,保存为handlers.yml:
1
2
3
4
     ---
    # this might be in a file like handlers/handlers.yml
    - name: restart apache
      service: name=httpd state=restarted





在playbooks中包含该文件:

1
2
    handlers:
      - include: handlers/handlers.yml





还可以将一个playbooks文件导入到另外一个playbooks中,这样的话,只需要定义一个顶级的且内容为一些较为通用的操作的playbooks文件,然后再文件中包含其他的playbooks即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
     - name: this is a play at the top level of a file
      hosts: all
      remote_user: root
     
      tasks:
     
      - name: say hi
        tags: foo
        shell: echo "hi..."
     
    - include: load_balancers.yml
    - include: webservers.yml
    - include: dbservers.yml




示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[iyunv@web1 ansible]# tree /etc/ansible/
    /etc/ansible/
    ├── handlers
    │   └── restart.yml
    ├── hosts
    ├── main.yml
    ├── tasks
    │   └── apache.yml
    └── templates
        └── httpd.j2
    [iyunv@web1 ansible]# cat tasks/apache.yml
    ---
    - name: config httpd.file
      template: src=templates/httpd.j2 dest=/etc/httpd.conf
    [iyunv@web1 ansible]# cat handlers/restart.yml
    ---
    - name: restart apache
      service: name=httpd state=restarted
    [iyunv@web1 ansible]# cat main.yml
    ---
    - hosts: webservers
      remote_user: root
      vars:
        http_port: 8085
        max_clients: 123
      
      tasks:
        - include: tasks/apache.yml
         
      handlers:
        - include: handlers/restart.yml
    [iyunv@web1 ansible]# ansible-playbook /etc/ansible/main.yml
     
    PLAY [webservers] *************************************************************
     
    GATHERING FACTS ***************************************************************
    ok: [192.168.1.65]
     
    TASK: [config httpd.file] *****************************************************
    changed: [192.168.1.65]
     
    PLAY RECAP ********************************************************************
    192.168.1.65               : ok=2    changed=1    unreachable=0    failed=0




注:上边文件虽然定义并包含了重启apache的handler,但并没有任务一个任务来触发该handler。所以并没有执行重启操作,即使配置文件发生了改变。

角色


“文件包含”本身只是很简单且很单纯的包含各个子文件,当文件较多的时候,其组织方式也并是好,且需要人为的来指定包含哪些文件。Ansible中的“角色”会基于已知的文件结构来自动加载特定的变量文件、任务文件一级handlers文件,使用角色来组织内容可以更好的实现共享。

官方的一个使用角色组织内容的文件结构:

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    site.yml
    webservers.yml
    fooservers.yml #playbooks文件,最后ansible执行的就是这些文件
    roles/
       common/
         files/
         templates/ #保存操作中所需要的模板文件
         tasks/ #保存任务列表文件
         handlers/ #保存handler文件
         vars/ #保存定义变量的文件
         defaults/ #默认变量文件
         meta/ #角色的依赖关系
       webservers/
         files/
         templates/
         tasks/
         handlers/
         vars/
         defaults/
         meta/





在playbooks中这样书写内容,如上边的webservers.yml文件:

1
2
3
4
5
     ---
     - hosts: webservers
      roles:
         - common
         - webservers





每个角色都会遵循以下原则:

  • - 如果`roles/x/tasks/main.yml`存在,里面的任务列表会被添加到`play`中。
  • - 如果`roles/x/handlers/main.yml`存在,里面的`handlers`会被添加到`play`中。
  • - 如果`roles/x/vars/main.yml`存在,里面的变量会被添加到`play`中。
  • - 如果`roles/x/meta/main.yml`存在,里面的角色依赖会被添加到角色列表中。
  • - `roles/x/files`任务所需要被复制的文件,无需绝对路径或者相对路径都可以引用该文件。
  • - `roles/x/files`中的任务脚本都可以直接使用该文件,无需指定绝对路径或者是相对路径。
  • - `roles/x/templates`中的模板,无需指定绝对路径或者相对路径,都可以直接使用文件名引用该文件。
  • - 需要包含在`roles/x/tasks`中的任务文件时,无需指定绝对路径或者相对路径,可以直接使用文件名包含。


tasks,handlers,vars,meta目录下main.yml中的内容都会被自动调用。

如果某些文件不存在的话,将会自动跳过,所以`vars/`之类的子目录如果用不到的话也可以不创建。

也可以给角色传递参数,在playbooks文件定义:

1
2
3
4
5
6
7
    ---
     
    - hosts: webservers
      roles:
        - common
        - { role: foo_app_instance, dir: '/opt/a',  port: 5000 }
        - { role: foo_app_instance, dir: '/opt/b',  port: 5001 }





有时候也可以给角色添加执行条件:
1
2
3
4
5
    ---
     
    - hosts: webservers
      roles:
        - { role: some_role, when: "ansible_os_family == 'RedHat'" }



当远程节点的操作系统为RedHat的时候才会执行"some_role"中的操作。

如果在某个play中定义了一个tasks任务块,它将会在橘色执行完成后再执行。

定义在角色执行之前或者执行后需要执行的任务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    ---
     
    - hosts: webservers
     
      pre_tasks:
        - shell: echo 'hello'
     
      roles:
        - { role: some_role }
     
      tasks:
        - shell: echo 'still busy'
     
      post_tasks:
        - shell: echo 'goodbye'





示例:

   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[iyunv@web1 ~]# tree /etc/ansible/
    /etc/ansible/
    ├── hosts
    ├── roles
    │   └── webservers
    │       ├── defaults
    │       ├── files
    │       ├── handlers
    │       │   ├── main.yml
    │       │   └── restart.yml
    │       ├── meta
    │       ├── tasks
    │       │   ├── apache.yml
    │       │   └── main.yml
    │       ├── templates
    │       │   └── httpd.j2
    │       └── vars
    │           └── main.yml
    └── webservers.yml
     
    [iyunv@web1 ~]# cat /etc/ansible/roles/webservers/tasks/main.yml
    ---
    - include: apache.yml
    [iyunv@web1 ~]# cat /etc/ansible/roles/webservers/tasks/apache.yml
    ---
    - name: config httpd.file
      template: src=httpd.j2 dest=/etc/httpd.conf
      notify:
        - restart apache
    [iyunv@web1 ~]# cat /etc/ansible/roles/webservers/handlers/main.yml
    ---
    - include: restart.yml
    [iyunv@web1 ~]# cat /etc/ansible/roles/webservers/handlers/restart.yml
    ---
    - name: restart apache
      service: name=httpd state=restarted
    [iyunv@web1 ~]# cat /etc/ansible/roles/webservers/vars/main.yml
    ---
    http_port: 8099
    max_clients: 321

    [iyunv@web1 ansible]# ansible-playbook /etc/ansible/webservers.yml
     
    PLAY [webservers] *************************************************************
     
    GATHERING FACTS ***************************************************************
    ok: [192.168.1.65]
     
    TASK: [webservers | config httpd.file] ****************************************
    changed: [192.168.1.65]
     
    NOTIFIED: [webservers | restart apache] ***************************************
    changed: [192.168.1.65]
     
    PLAY RECAP ********************************************************************
    192.168.1.65               : ok=3    changed=2    unreachable=0    failed=0




有些子目录并没有使用到,如meta目录,就可以不用创建。


角色依赖


角色依赖使得当使用某个角色的时候自动将其他角色导入。角色依赖保存在角色目录下的`meta/main.yml`文件中,该文件包含一个角色和参数的列表,这些内容会在某个特定的角色之前插入。即在某个特定的角色执行之前会先执行其依赖。


1
2
3
4
5
     ---
    dependencies:
      - { role: common, some_parameter: 3 }
      - { role: apache, port: 80 }
      - { role: postgres, dbname: blarg, other_parameter: 12 }



也可以以绝对路径的方式定义:
1
2
3
     ---
    dependencies:
       - { role: '/path/to/common/roles/foo', x: 1 }



角色依赖总在包含它们的角色执行之前而执行,而且是递归执行。默认情况下,角色也只能作为一个依赖关系添加一次,如果另一个角色也将它列为一个依赖关系,它将不再运行。但是在`meta/main.yml`设置`allow_duplicates: yes`,可以突破这个限制。如一个称为`car`的角色需要添加一个名为`wheel`的角色作为它的依赖:
1
2
3
4
5
6
    ---
    dependencies:
    - { role: wheel, n: 1 }
    - { role: wheel, n: 2 }
    - { role: wheel, n: 3 }
    - { role: wheel, n: 4 }



meta/main.yml内容:


1
2
3
4
5
    ---
    allow_duplicates: yes
    dependencies:
    - { role: tire }
    - { role: brake }



执行的结果会是类似下边这样:


1
2
3
4
5
6
7
8
    tire(n=1)
    brake(n=1)
    wheel(n=1)
    tire(n=2)
    brake(n=2)
    wheel(n=2)
    ...
    car





总结:
角色和文件包含,在平时的运维工作中会经常使用到,而且使得文件组织更加清晰,复用性较高。可以对远程节点主机进行大量且复杂有序的操作。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-92569-1-1.html 上篇帖子: 自动化运维工具Ansible之Playbooks基础应用 下篇帖子: 自动化运维工具Ansible之Playbooks循环语句 include
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表