jinja2模板、清单管理、并行方式
1、jinja2模板
1.1jinja2介绍
Ansible将jinja2模板系统用于模板文件,Ansible还使用jinja2语法来引用playbook中的变量。jinja2要搭配使用template
模块
{# COMMENT #}: 注释信息,在模板执行时,此内容不会显示
{{ ansible_managed }}: 此信息是提示其他人这个文件是受ansible控制的。不应该手动编辑该文件,因为执行一次play就会发生改变
1.2 jinja2模板的构建及部署、管理模板文件
构建jinja2模板:
jinja2模板由多个元素组成:数据、变量和表达式。在呈现jinja2模板时,这些变量和表达式被替换为对应的值。模板中使用的变量可以在playbook的vars部分中指定。可以将受管主机的事实用作模板中的变量。
使用jinja2模板的时候要搭配使用template
模块,不能使用copy模块,因为copy拷贝模板的时候不会转变变量,原封不动的复制过去,而template会转变完变量后才复制过去
下面将演示一个例子:
[root@localhost ansible]# vim wjm.yml
---
- name: jinja2
hosts: httpd
tasks:
- name:
template: //template拷贝模板文件到对面主机
src: ./wjm.j2
dest: /etc/motd //motd意思是“当天的提示信息”,通常在用户成功登录到Linux后出现,下面有例子!
#ssh连接成功反馈信息:
#连接成功
#"这是一个测试模板文件"
#this system hostanem: wjm1
#this system menmory is: 1800 MB
#Last login: Fri Jul 30 07:14:52 2021 from 192.168.252.1
#[root@wjm1 ~]#
[root@localhost ansible]# vim wjm.j2
"这是一个测试模板文件"
{# 这是一个注释信息,只有在本机才可以看见#}
this system hostanem: {{ ansible_hostname }} //他会自动引用事实变量中的主机名
this system menmory is: {{ ansible_memtotal_mb}} MB //他会自动引用事实中主机总内存关键字
[root@wjm1 etc]# cat motd
"这是一个测试模板文件"
this system hostanem: wjm1 //这个系统的名称是wjm1
this system menmory is: 1800 MB //这个系统的总内存是1800MB,也就2G
1.3 jinja2中使用循环和条件判断
jinja2中的判断
[root@localhost ansible]# cat wjm.j2
{% if ansible_fqdn == "wjm1" %} //if 如果,进行判断
echo "正确"
{% elif ansible_fqdn == "wjm2" %} //elif:否则如果
echo "没有找到wjm1"
{% else %} //else其他的,既不是wjm1 又不是wjm2则输出一下内容
echo "没有找到wjm1"
{% endif% }
//判断主机名,如果判断成功将输出正确,如果判断错误或其则输出“没有找到wjm1”
jinja2中的循环
格式:
{% for 变量 in 变量%}
{{ 变量 }}
{% endfor%}
{% for user in users %}
{{ user }}
{% endfor %}
jinja2使用for语句来提供循环功能。在下例中,name变量替换为names变量中包含的所有值,一行一个值。
[root@localhost ansible]# cat wjm.j2 //模板文件的内容
{% for name in names%}
{{ name }}
{% endfor %}
[root@localhost ansible]# vim wjm.yml
---
- name: jinja2
hosts: httpd
vars_files:
- ./names.yml //定义变量的文件位置
tasks:
- name:
template:
src: ./wjm.j2 //模板文件位置,模板中的内容在上面步骤有显示
dest: /etc/wjm //复制到对面的位置
[root@localhost ansible]# cat names.yml //定义变量文件的位置
names:
- 123
- 456
- 789
[root@wjm1 etc]# pwd
/etc
[root@wjm1 etc]# cat wjm //在对面主机查看复制过来的内容
123
456
789
2、清单管理
清单文件是用来记录哪些主机是受本机的ansible控制的。可以是一台主机,也可以是一组主机。
root@localhost ~]# cat inventory
//主机,这里的主机可以写成ip方式也可以写成主机名方式,但是推荐使用主机名的方式!
web.example.com
data.example.com
//主机组,是多个主机的相同主机的集合。
[lab]
labhost1.example.com //既属于lab组也属于datacenter1组
labhost2.example.com //既属于lab组也属于datacenter2组
[datacenter1]
labhost1.example.com
test1.example.com
[datacenter2]
labhost2.example.com
test2.example.com
//这个主机组又包含上面两个主机组,所以这个组一共有4台服务器
[datacenter:children]
datacenter1
datacenter2
一般解析文件配置在/etc/hosts
这个文件里面,配置上IP地址和对应的主机名即可
2.1 使用组指定主机
当组名称用作主机模式时,它指定Ansible将对属于该组的成员的主机执行操作。
---
- hosts: lab
记住,有一个名为all的特别组,它匹配清单中的所有受管主机。
---
- hosts: all
还有一个名为ungrouped的特别组,它包括清单中不属于任何其他组的所有受管主机:
---
- hosts: ungrouped
使用通配符来匹配多个主机
若要达成与all主机模式相同的目标,另一种方法是使用*通配符,它将匹配任意字符串。如果主机模式只是带引号的星号,则清单中的所有主机都将匹配。
---
- hosts: '*' //和all一样,是用来匹配所有主机的
也可使用*字符匹配包含特定子字符串的受管主机或组。
例如,以下通配符主机模式匹配以.example.com结尾的所有清单名称:
---
- hosts: '*.example.com'
//匹配2.0网段的所有主机
---
- hosts: '192.168.2.*'
//匹配所以以datacenter 开头的主机
---
- hosts: 'datacenter*'
列表
可以通过逻辑列表来引用清单中的多个条目。主机模式的逗号分隔列表匹配符合任何这些主机模式的所有主机。
如果提供受管主机的逗号分隔列表,则所有这些受管主机都将是目标:
//匹配多个主机
---
- hosts: labhost1.example.com,test2.example.com,192.168.2.2
//匹配这两个组的所有主机
---
- hosts: lab,datacenter1
如果列表中的某一项以与符号(&)开头,则主机必须与该项匹配才能匹配主机模式。它的工作方式类似于逻辑AND。
//匹配既属于lab组又属于datacenter组的主机
---
- hosts: lab,&datacenter1
//匹配一个组中除某一台主机其他的所有主机
---
- hosts: datacenter,!test2.example.com
//匹配除了某一个组以外的其他组
---
- hosts: all,!datacenter1
3、配置并行方式(forks、serial)s
3.1并行(forks)
当Ansible处理playbook时,会按顺序运行每个play。确定play的主机列表之后,Ansible将按顺序运行每个任务。通常,所有主机必须在任何主机在play中启动下一个任务之前成功完成任务。
理论上,Ansible可以同时连接到play中的所有主机以执行每项任务。这非常适用于小型主机列表。但如果该play以数百台主机为目标,则可能会给控制节点带来沉重负担。
Ansible所进行的最大同时连接数由Ansible配置文件中的forks
参数控制。默认情况下设为5,这可通过以下方式之一来验证。
[root@localhost ~]# grep forks /etc/ansible/ansible.cfg
#forks = 5 //一次性最多同时执行5台主机的任务
简单的说就是,当forks值为5时,一次性最多同时执行5台主机的任务。如果有10台主机将会被分为2组,当第一组的5个主机执行完第一个任务后,才会执行第二组5个主机的第一个任务,然后再回到第一组主机执行第二个任务完成后再去第二组执行第二个任务,知道play执行结束。
3.2 串行(serial)
通常,当Ansible运行play时,它会确保所有受管主机在启动任何主机进行下一个任务之前已完成每个任务。在所有受管主机完成所有任务后,将运行任何通知的处理程序。
但是,在所有主机上运行所有任务可能会导致意外行为。例如,如果play更新负载均衡Web服务器集群,则可能需要在进行更新时让每个Web服务器停止服务。如果所有服务器都在同一个play中更新,则它们可能全部同时停止服务。
避免此问题的一种方法是使用serial
关键字,通过play批量运行主机。在下一批次启动之前,每批主机将在整个play中运行。
在下面的示例中,Ansible一次在两个受管主机上执行play,直至所有受管主机都已更新。Ansible首先在前两个受管主机上执行play中的任务。如果这两个主机中的任何一个或两个都通知了处理程序,则Ansible将根据这两个主机的需要运行处理程序。在这两个受管主机上执行完play时,Ansible会在接下来的两个受管主机上重复该过程。Ansible继续以这种方式运行play,直到所有受管主机都已更新。
---
- name: Rolling update
hosts: webservers
serial: 2 //在forks基础上,一次最多只能两台主机执行任务且必须要前两台执行成功,重启后开能执行下一个任务。
tasks:
- name: latest apache httpd package is installed
yum:
name: httpd
state: latest
notify: restart apache
handlers:
- name: restart apache
service:
name: httpd
state: restarted
简单的理解就是,当并行设置为5(forks ) ,串行(serial)为2时,此时有10台机器要重启服务。那么就会把这10台主机分成2两组 每一组又5台主机,先在第一组的前两台主机执行第一个任务,当这两个主机执行完成并启动后 才在到第一组的3 4 台主机执行第一个任务,直到第一组执行完成,才会去第二组的前两台主机执行第一个任务
forks
是控制同时可以对几台主机执行任务,而serial
是在并行的基础上控制一次可以让几台主机执行完成任务后才会去执行一下主机任务。