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