(7)Ansible之Playbook(下)

一、Playbook中标签的使用

一个playbook文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。

# 编辑playbook
[root@ansible PlayBook]# cat httpd.yml 
---
- hosts: 192.168.1.31
  remote_user: root

  tasks:
    - name: install httpd
      yum: name=httpd state=installed
      tags: inhttpd

    - name: start httpd
      service: name=httpd state=started
      tags: sthttpd

    - name: restart httpd
      service: name=httpd state=restarted
      tags: 
        - rshttpd
        - rs_httpd

# 正常执行的结果
[root@ansible PlayBook]# ansible-playbook httpd.yml 

PLAY [192.168.1.31] **************************************************************************************************************************

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

TASK [install httpd] *************************************************************************************************************************
ok: [192.168.1.31]

TASK [start httpd] ***************************************************************************************************************************
ok: [192.168.1.31]

TASK [restart httpd] *************************************************************************************************************************
changed: [192.168.1.31]

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

1、通过-t选项指定tags进行执行

# 通过-t指定tags名称,多个tags用逗号隔开
[root@ansible PlayBook]# ansible-playbook -t rshttpd httpd.yml 

PLAY [192.168.1.31] **************************************************************************************************************************

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

TASK [restart httpd] *************************************************************************************************************************
changed: [192.168.1.31]

PLAY RECAP ***********************************************************************************************************************************
192.168.1.31               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

2、通过–skip-tags选项排除不执行的tags

[root@ansible PlayBook]# ansible-playbook --skip-tags inhttpd httpd.yml 

PLAY [192.168.1.31] **************************************************************************************************************************

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

TASK [start httpd] ***************************************************************************************************************************
ok: [192.168.1.31]

TASK [restart httpd] *************************************************************************************************************************
changed: [192.168.1.31]

PLAY RECAP ***********************************************************************************************************************************
192.168.1.31               : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

二、Playbook中模板的使用

template模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。
说明:
1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。
2、模板文件后缀名为.j2

循环参考

示例:通过template安装httpd

playbook文件编写

[root@ansible PlayBook]# cat testtmp.yml 
#模板示例
---
- hosts: all
  remote_user: root
  vars:
    - listen_port: 88    #定义变量

  tasks:
    - name: Install Httpd
      yum: name=httpd state=installed
    - name: Config Httpd
      template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf    #使用模板
      notify: Restart Httpd
    - name: Start Httpd
      service: name=httpd state=started
      
  handlers:
    - name: Restart Httpd
      service: name=httpd state=restarted

模板文件准备
httpd配置文件准备,这里配置文件端口使用了变量

[root@ansible PlayBook]# cat templates/httpd.conf.j2 |grep ^Listen
Listen {{ listen_port }}

查看目录结构

# 目录结构
[root@ansible PlayBook]# tree .
.
├── templates
│   └── httpd.conf.j2
└── testtmp.yml

1 directory, 2 files

执行playbook

由于192.168.1.36那台机器是6的系统,模板文件里面的配置文件是7上面默认的httpd配置文件,httpd版本不一样(6默认版本为2.2.15,7默认版本为2.4.6),所以拷贝过去后启动报错。下面使用playbook中的判断语句进行处理;此处先略过

[root@ansible PlayBook]# ansible-playbook testtmp.yml 

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

TASK [Gathering Facts] ******************************************************************************
ok: [192.168.1.36]
ok: [192.168.1.32]
ok: [192.168.1.33]
ok: [192.168.1.31]

TASK [Install Httpd] ********************************************************************************
ok: [192.168.1.36]
ok: [192.168.1.33]
ok: [192.168.1.32]
ok: [192.168.1.31]

TASK [Config Httpd] *********************************************************************************
changed: [192.168.1.31]
changed: [192.168.1.33]
changed: [192.168.1.32]
changed: [192.168.1.36]

TASK [Start Httpd] **********************************************************************************
fatal: [192.168.1.36]: FAILED! => {"changed": false, "msg": "httpd: Syntax error on line 56 of /etc/httpd/conf/httpd.conf: Include directory '/etc/httpd/conf.modules.d' not found\n"}
changed: [192.168.1.32]
changed: [192.168.1.33]
changed: [192.168.1.31]

RUNNING HANDLER [Restart Httpd] *********************************************************************
changed: [192.168.1.31]
changed: [192.168.1.32]
changed: [192.168.1.33]

PLAY RECAP ******************************************************************************************
192.168.1.31               : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.32               : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.33               : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.36               : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

1、template之when

when语句参考

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句执行,在task中使用jinja2的语法格式、
when语句:
task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。

类似这样:

tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped

示例:通过when语句完善上面的httpd配置

准备两个配置文件

一个centos6系统httpd配置文件
一个centos7系统httpd配置文件。

[root@ansible PlayBook]# tree templates/
templates/
├── httpd6.conf.j2     #6系统2.2.15版本httpd配置文件
└── httpd7.conf.j2     #7系统2.4.6版本httpd配置文件

0 directories, 2 files

修改playbook文件

通过setup模块获取系统版本去判断。

[root@ansible PlayBook]# cat testtmp.yml 
#when示例
---
- hosts: all
  remote_user: root
  vars:
    - listen_port: 88

  tasks:
    - name: Install Httpd
      yum: name=httpd state=installed
    - name: Config System6 Httpd
      template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
      when: ansible_distribution_major_version == "6"   #判断系统版本,为6便执行上面的template配置6的配置文件
      notify: Restart Httpd
    - name: Config System7 Httpd
      template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
      when: ansible_distribution_major_version == "7"   #判断系统版本,为7便执行上面的template配置7的配置文件
      notify: Restart Httpd
    - name: Start Httpd
      service: name=httpd state=started

  handlers:
    - name: Restart Httpd
      service: name=httpd state=restarted

执行playbook

[root@ansible PlayBook]# ansible-playbook testtmp.yml

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

TASK [Gathering Facts] ******************************************************************************
ok: [192.168.1.31]
ok: [192.168.1.32]
ok: [192.168.1.33]
ok: [192.168.1.36]

TASK [Install Httpd] ********************************************************************************
ok: [192.168.1.32]
ok: [192.168.1.33]
ok: [192.168.1.31]
ok: [192.168.1.36]

TASK [Config System6 Httpd] *************************************************************************
skipping: [192.168.1.33]
skipping: [192.168.1.31]
skipping: [192.168.1.32]
changed: [192.168.1.36]

TASK [Config System7 Httpd] *************************************************************************
skipping: [192.168.1.36]
changed: [192.168.1.33]
changed: [192.168.1.31]
changed: [192.168.1.32]

TASK [Start Httpd] **********************************************************************************
ok: [192.168.1.36]
ok: [192.168.1.31]
ok: [192.168.1.32]
ok: [192.168.1.33]

RUNNING HANDLER [Restart Httpd] *********************************************************************
changed: [192.168.1.33]
changed: [192.168.1.31]
changed: [192.168.1.32]
changed: [192.168.1.36]

PLAY RECAP ******************************************************************************************
192.168.1.31               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
192.168.1.32               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
192.168.1.33               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
192.168.1.36               : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

2、template之with_items

with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。
对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。
列表格式:
  字符串
  字典

示例1:通过with_items安装多个不同软件

编写playbook

[root@ansible PlayBook]# cat testwith.yml 
# 示例with_items
---
- hosts: all
  remote_user: root

  tasks:
    - name: Install Package
      yum: name={{ item }} state=installed   #引用item获取值
      with_items:     #定义with_items
        - httpd
        - vsftpd
        - nginx

上面tasks写法等同于:

---
- hosts: all
  remote_user: root
  tasks:
    - name: Install Httpd
      yum: name=httpd state=installed
    - name: Install Vsftpd
      yum: name=vsftpd state=installed
    - name: Install Nginx
      yum: name=nginx state=installed

示例2:通过嵌套子变量创建用户并加入不同的组

1)编写playbook

[root@ansible PlayBook]# cat testwith01.yml 
# 示例with_items嵌套子变量
---
- hosts: all
  remote_user: root

  tasks:
    - name: Create New Group
      group: name={{ item }} state=present
      with_items: 
        - group1
        - group2
        - group3 

    - name: Create New User
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - { name: 'user1', group: 'group1' } 
        - { name: 'user2', group: 'group2' } 
        - { name: 'user3', group: 'group3' }

2)执行playbook并验证

# 执行playbook
[root@ansible PlayBook]# ansible-playbook testwith01.yml

# 验证是否成功创建用户及组
[root@ansible PlayBook]# ansible all -m shell -a 'tail -3 /etc/passwd'
192.168.1.36 | CHANGED | rc=0 >>
user1:x:500:500::/home/user1:/bin/bash
user2:x:501:501::/home/user2:/bin/bash
user3:x:502:502::/home/user3:/bin/bash

192.168.1.32 | CHANGED | rc=0 >>
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user3:x:1003:1003::/home/user3:/bin/bash

192.168.1.31 | CHANGED | rc=0 >>
user1:x:1002:1003::/home/user1:/bin/bash
user2:x:1003:1004::/home/user2:/bin/bash
user3:x:1004:1005::/home/user3:/bin/bash

192.168.1.33 | CHANGED | rc=0 >>
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user3:x:1003:1003::/home/user3:/bin/bash

3、template之for if

通过使用forif可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。

示例1

1)编写playbook

[root@ansible PlayBook]# cat testfor01.yml 
# template for 示例
---
- hosts: all
  remote_user: root
  vars:
    nginx_vhost_port:
      - 81
      - 82
      - 83

  tasks:
    - name: Templage Nginx Config
      template: src=nginx.conf.j2 dest=/tmp/nginx_test.conf

2)模板文件编写

# 循环playbook文件中定义的变量,依次赋值给port
[root@ansible PlayBook]# cat templates/nginx.conf.j2 
{% for port in nginx_vhost_port %}
server{
     listen: {{ port }};
     server_name: localhost;
}
{% endfor %}

3)执行playbook并查看生成结果

[root@ansible PlayBook]# ansible-playbook testfor01.yml

# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_test.conf 
server{
     listen: 81;
     server_name: localhost;
}
server{
     listen: 82;
     server_name: localhost;
}
server{
     listen: 83;
     server_name: localhost;
}
示例2

1)编写playbook

[root@ansible PlayBook]# cat testfor02.yml 
# template for 示例
---
- hosts: all
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8081
        server_name: "web1.example.com"
        root: "/var/www/nginx/web1"
      - web2:
        listen: 8082
        server_name: "web2.example.com"
        root: "/var/www/nginx/web2"
      - web3:
        listen: 8083
        server_name: "web3.example.com"
        root: "/var/www/nginx/web3"

  tasks:
    - name: Templage Nginx Config
      template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

2)模板文件编写

[root@ansible PlayBook]# cat templates/nginx.conf.j2 
{% for vhost in nginx_vhosts %}
server{
     listen:    {{ vhost.listen }};
     server_name:    {{ vhost.server_name }};
     root:   {{ vhost.root }}; 
}
{% endfor %}

3)执行playbook并查看生成结果

[root@ansible PlayBook]# ansible-playbook testfor02.yml

# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_vhost.conf 
server{
     listen:    8081;
     server_name:    web1.example.com;
     root:   /var/www/nginx/web1; 
}
server{
     listen:    8082;
     server_name:    web2.example.com;
     root:   /var/www/nginx/web2; 
}
server{
     listen:    8083;
     server_name:    web3.example.com;
     root:   /var/www/nginx/web3; 
}
示例3

在for循环中再嵌套if判断,让生成的配置文件更加灵活

1)编写playbook

[root@ansible PlayBook]# cat testfor03.yml 
# template for 示例
---
- hosts: all
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8081
        root: "/var/www/nginx/web1"
      - web2:
        server_name: "web2.example.com"
        root: "/var/www/nginx/web2"
      - web3:
        listen: 8083
        server_name: "web3.example.com"
        root: "/var/www/nginx/web3"

  tasks:
    - name: Templage Nginx Config
      template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

2)模板文件编写

# 说明:这里添加了判断,如果listen没有定义的话,默认端口使用8888,如果server_name有定义,那么生成的配置文件中才有这一项。
[root@ansible PlayBook]# cat templates/nginx.conf.j2 
{% for vhost in nginx_vhosts %}
server{
     {% if vhost.listen is defined %}
     listen:    {{ vhost.listen }};
     {% else %}
     listen: 8888;
     {% endif %}
     {% if vhost.server_name is defined %}
     server_name:    {{ vhost.server_name }};
     {% endif %}
     root:   {{ vhost.root }}; 
}
{% endfor %}

3)执行playbook并查看生成结果

[root@ansible PlayBook]# ansible-playbook testfor03.yml

# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_vhost.conf 
server{
          listen:    8081;
          root:   /var/www/nginx/web1; 
}
server{
          listen: 8888;
          server_name:    web2.example.com;
          root:   /var/www/nginx/web2; 
}
server{
          listen:    8083;
          server_name:    web3.example.com;
          root:   /var/www/nginx/web3; 
}

你可能感兴趣的:(ansible)