目录
一. JinJia2简介
二. JinJia2模板使用
2.1 在play中使用jinjia2
2.2 template模块使用
2.3 jinjia2条件语句
2.4 jinjia2循环语句
2.5 jinjia2过滤器
2.5.1 default过滤器
2.5.2 字符串操作相关过滤器
2.5.3 数字操作相关过滤器
2.5.4 列表操作相关过滤器
2.5.5 应用于文件的过滤器
2.5.6 应用于注册变量的过滤器
一. JinJia2简介
Jinja2是基于python的模板引擎。那么什么是模板?
假设说现在我们需要一次性在10台主机上安装redis,这个通过playbook现在已经很容易实现。默认 情况下,所有的redis安装完成之后,我们可以统一为其分发配置文件。这个时候就面临一个问题,这 些redis需要监听的地址各不相同,我们也不可能为每一个redis单独写一个配置文件。因为这些配置 文件中,绝大部分的配置其实都是相同的。这个时候最好的方式其实就是用一个通用的配置文件来解 决所有的问题。将所有需要修改的地方使用变量替换。这个通用的配置文件就是模板。
二. JinJia2模板使用
2.1 在play中使用jinjia2
以上面的redis为例,我们创建一个redis的模板,模板如下:
[root@clinet ~]# cat /etc/redis.conf |grep -v ^# |grep -v ^$
bind {{ ansible_eth0.ipv4.address }} 127.0.0.1
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
现在我们有了一个模板文件,那么在playbook中如何来使用呢? playbook使用template模块来实现模板文件的分发,其用法与copy模块基本相同,唯一的区别是, copy模块会将原文件原封不动的复制到被控端,而template会将原文件复制到被控端,并且使用变 量的值将文件中的变量替换以生成完整的配置文件。
playbook示例:
[root@clinet yum_file]# cat jinjia2/install_redis.yml
- hosts: testtasks:- name: configure redis max memoryset_fact:redis_mem: "{{ (ansible_memtotal_mb /2) | int }}M"- name: debug memeory debug:msg: - '{{ redis_mem }}'- name: install redis package:name: redisstate: present- name: configure redis.conftemplate:src: /root/ansible_test/ansible_2/template/redis.conf.j2dest: /etc/redis.confnotify:- restart redis- name: start redisservice:name: redisstate: startedenabled: yeshandlers:- name: restart redisservice:name: redisstate: restarted
[root@clinet yum_file]#
2.2 template模块使用
template模块会将原文件复制到被控端,并且使用变 量的值将文件中的变量替换以生成完整的配置文件。
关于template模块的更多参数说明:
· backup:如果原目标文件存在,则先备份目标文件
· dest:目标文件路径
· force:是否强制覆盖,默认为yes
· group:目标文件属组
· mode:目标文件的权限
· owner:目标文件属主
· src:源模板文件路径
· validate:在复制之前通过命令验证目标文件,如果验证通过则复制
2.3 jinjia2条件语句
在上面的示例中,我们直接取了被控节点的ens33网卡的ip作为其监听地址。那么假如有些机器的网卡绑定的,那么网络连接时是bond0,这种做法就会报错。这个时候我们就需要在模板文件中定义条件语句如下:
{% if ansbile_bond is defined %}
bind {{ ansible_bond.ipv4.address }} 127.0.0.1
{% elif ansible_bond is defined % }
bind {{ ansible_ens33.ipv4.address }} 127.0.0.1
{% else %}
bind 0.0.0.0
{% endif %}maxmemory {{ redis_mem }}
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
利用条件语句进一步配置redis主从模式:
{% if ansbile_bond is defined %}
bind {{ ansible_bond.ipv4.address }} 127.0.0.1
{% elif ansible_ens33 is defined %}
bind {{ ansible_ens33.ipv4.address }} 127.0.0.1
{% else %}
bind 0.0.0.0
{% endif %}{% if master_ip is defined %}
slaveof {{ master_ip }} {{ masterport | default(6379) }}
{% endif %}{% if masterpass is defined %}
masterauth {{ masterpass }}
{% endif %}{% if requirepass is defined %}
requirepass {{ requirepass }}
{% endif %}maxmemory {{ redis_mem }}
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
注意:
1. redis主从配置只需要在slave上配置slaveof ip port(master节点不需要任何配置)
2. 注意防火墙
2.4 jinjia2循环语句
以nginx做负载均能,代理到后端httpd的基础实验为例,展示基础的for循环使用。
inventory配置如下:
[proxy]
192.168.194.132[webserver]
192.168.194.130
192.168.194.131
[root@clinet ansible_2]#
playbook如下:
- hosts: proxy:webservergather_facts: yespre_tasks:- name: fireword.serverservice:name: firewalldstate: stoppedenabled: nopost_tasks:- name: message infodebug:msg: 'this playbook finished'tasks:- name: install & configure ngxin blockblock:- name: install nginxpackage:name: nginxstate: present- name: configure nginx.conftemplate:src: /root/ansible_test/ansible_2/template/nginx.conf.j2dest: /etc/nginx/nginx.confbackup: yesnotify: restart nginx- name: start ngixnservice:name: nginxstate: startedenabled: yeswhen: ansible_ens33.ipv4.address in groups['proxy']- name: install & configure httpd blockblock:- name: install httpdpackage:name: httpdstate: present- name: confgure http.conftemplate:src: /root/ansible_test/ansible_2/template/index.html.j2dest: /var/www/html/index.htmlbackup: yesnotify: restart httpd- name: start httpdservice:name: httpdstate: startedenabled: yeswhen: ansible_ens33.ipv4.address in groups['webserver']handlers:- name: restart nginxservice:name: nginxstate: restarted- name: restart httpdservice:name: httpdstate: restarted
总结一:
上述示例中回顾了以下知识点:1. pre_tasks 是在tasks之前执行;而 post_tasks 则在tasks和handlers之后执行;
2. when关键字,playbook中的条件语句
3. hosts: proxy:webserver,ansible的主机匹配规则
4. block和when的配合使用,对整块block语句做判断。等等
总结二:
jinjia2模板中的语法总结:
1. 变量的使用: {{ 变量名 }} (不需要用引号包裹,与playbook中的变量使用的主要区别)
2. 条件语句:
{% if %} ... {% elif %} ... {% else %} ... {% endif %}
3. 循环语句:
{% for %} ... {% endfor %}
(注意:{%%} 是jinjia2模板的语法格式)
2.5 jinjia2过滤器
2.5.1 default过滤器
当指定的变量不存在时,用于设定默认值
示例:
‐ hosts: testgather_facts: falsevars:‐ path: /tmp/testmode: 0400‐ path: /tmp/foo‐ path: /tmp/bartasks:‐ file:path: {{ item.path }}state: touchmode: {{ item.mode|default(omit)}}with_items: "{{ paths }}"
omit表示系统默认的,也可以default(777),当变量不存在的时候,使用777为值。
2.5.2 字符串操作相关过滤器
· upper:将所有字符串转换为大写
· lower:将所有字符串转换为小写
· capitalize:将字符串的首字母大写,其他字母小写
· reverse:将字符串倒序排列
· first:返回字符串的第一个字符
· last:返回字符串的最后一个字符
· trim:将字符串开头和结尾的空格去掉
· center(30):将字符串放在中间,并且字符串两边用空格补齐30位
· length:返回字符串的长度,与count等价
· list:将字符串转换为列表
· shuffle:list将字符串转换为列表,但是顺序排列,shuffle同样将字符串转换为列表,但是会随 机打乱字符串顺序
‐ hosts: testgather_facts: novars:teststr: "abc123ABC"teststr1: " abc "teststr2: "123456789"teststr3: "sfacb1335@#$%"tasks:‐ debug:msg: "{{ teststr | upper }}"‐ debug:msg: "{{ teststr | lower }}"‐ debug:msg: "{{ teststr | capitalize }}"‐ debug:msg: "{{ teststr | reverse }}"‐ debug:msg: "{{ teststr|first }}"‐ debug:msg: "{{ teststr|last }}"‐ debug:msg: "{{ teststr1 | trim }}"‐ debug:msg: "{{ teststr2 | center(30) }}"‐ debug:msg: "{{ teststr2 | length }}"‐ debug:msg: "{{ teststr3 | list }}"‐ debug:msg: "{{ teststr3 | shuffle }}"
2.5.3 数字操作相关过滤器
· int: 将对应的值转换为整数
· float:将对应的值转换为浮点数
· abs:获取绝对值
· round:小数点四舍五入
· random:从一个给定的范围中获取随机值
‐ hosts: testgather_facts: novars:testnum: ‐1tasks:‐ debug:msg: "{{ 8+('8'|int) }}"‐ debug:# 默认情况下,如果无法完成数字转换则返回0# 这里指定如果无法完成数字转换则返回6msg: "{{ 'a'|int(default=6) }}"‐ debug:msg: "{{ '8'|float }}"‐ debug:msg: "{{ 'a'|float(8.88)' }}"‐ debug:msg: "{{ testnum|abs }}"‐ debug:msg: "{{ 12.5|round }}"‐ debug:msg: "{{ 3.1415926 | round(5) }}"‐ debug:# 从0到100中随机返回一个数字msg: "{{ 100|random }}"‐ debug:# 从5到10中随机返回一个数字msg: "{{ 10|random(start=5) }}"‐ debug:# 从4到15中随机返回一个数字,步长为3# 返回的随机数只可能是:4,7,10,13中的一个msg: "{{ 15|random(start=4,step=3) }}"‐ debug:# 从0到15随机返回一个数字,步长为4msg: "{{ 15|random(step=4) }}"
2.5.4 列表操作相关过滤器
· length: 返回列表长度
· first:返回列表的第一个值
· last:返回列表的最后一个值
· min:返回列表中最小的值
· max:返回列表中最大的值
· sort:重新排列列表,默认为升序排列,sort(reverse=true)为降序
· sum:返回纯数字非嵌套列表中所有数字的和
· flatten:如果列表中包含列表,则flatten可拉平嵌套的列表,levels参数可用于指定被拉平的层级
· join:将列表中的元素合并为一个字符串
· random:从列表中随机返回一个元素
· shuffle
· upper
· lower
· union:将两个列表合并,如果元素有重复,则只留下一个
· intersect:获取两个列表的交集
· difference:获取存在于第一个列表中,但不存在于第二个列表中的元素 · symmetric_difference:取出两个列表中各自独立的元素,如果重复则只留一个
2.5.5 应用于文件的过滤器
· basename:返回文件路径中的文件名部分
· dirname:返回文件路径中的目录部分
· expanduser:将文件路径中的~替换为用户目录
· realpath:处理符号链接后的文件实际路径
2.5.6 应用于注册变量的过滤器
正常情况下,当某个task执行失败的时候,ansible会中止运行。此时我们可以通过 ignore_errors 来 捕获异常以让task继续往下执行。然后调用debug模块打印出出错时的内容,拿来错误结果后,主动 失败。
‐ name: Run myprogcommand: /opt/myprogregister: resultignore_errors: True
‐ debug:var: result‐ debug:msg: "Stop running the playbook if myprog failed"failed_when: result|failed
任务返回值过滤器:
· failed: 如果注册变量的值是任务failed则返回True
· changed: 如果注册变量的值是任务changed则返回True
· success:如果注册变量的值是任务succeeded则返回True
· skipped:如果注册变量的值是任务skipped则返回True