Ansible 技巧之场
看到技巧之场,我就想起来被百万氪金王支配的恐惧!
拼接主机与http或其他字符串
有时候我们有一个列表,里面是IP地址。但是有时候我们要将http://
拼接在每个IP地址的开头,可以利用Jinja2语法进行操作。
在模版中:
1 2 3 4 5
| {% set http_hosts=[] %} # 定一个list变量 {% set hosts_list = discovery_seed_hosts | flatten %} # 将列表扁平化,因为这个变量列表里面存在嵌套的情况 {% for host in hosts_list %} {% set _ = http_hosts.append("http://%s:%s" % (host,9200)) %} #使用Python语法进行操作。 {% endfor %}
|
在Plybook中(从网上找到的未经过测试,理论可行):
1 2 3 4 5 6 7 8 9 10 11 12 13
| set_fact: cluster_address: | [ {% set pxc_hosts = groups.pxc %} {% for host in pxc_hosts %} {% set pxc_ip = hostvars[host].inventory_hostname | default(host) %} {% set pxc_port = group_port %} "{{ pxc_ip }}:{{ pxc_port }}" {% endfor -} ]
{{ cluster_address | join(',') }}'
|
对字符串的操作
得益于Python特性,在Ansible中可以使用Python中处理字符串的语法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 你可以对字符串进行取单个字符等操作: {{ vars[2] }}
也可以切片: {{ vars[3:6]}}
判断某些字符是否在字符串中: when: "'haha' in vars"
使用加号连接两个字符串: {{ var1+var2 }}
使用乘号*连续输出字符串: {{ var1*3 / 'la'*nums }}
使用find函数查找:
when: {{ vars.find('test') == -1 }} # 值为
find函数的语法是find(string,begin,end)
when: {{ vars.find('test',5) == -1 }} # 从第5位开始查找
|
任务委派
有时候你想让某一个tasks在指定的某一个受控主机上运行而不是要在Play中指定的组或主机中全部运行这个tasks。
这种情况下可以新写一个Play,然后将hosts和tasks进行指定。但是这样要新建一个Play,有点麻烦。
可以使用delegate_to
关键字来让某一个tasks指定运行在某一台主机上,任务委派时不会去看目标主机是否在inventory主机清单中。可以指定代码块进行任务委派。
1 2 3 4 5 6 7 8 9
| - debug: msg: "only host" delegate_to: 192.168.1.196
---
ok: [192.168.1.39 -> 192.168.1.196] => { "msg": "only host" }
|
仅在主机上执行
如果指向让某一个任务在本主机上运行。你可以使用刚刚的任务委派,来指向Ansible控制节点。也可以尝试connection: local
关键字。
connection关键字也可以用于代码块和任务。
1 2 3 4 5 6
| - block: - systemd: name: elasticsearch state: restarted connection: local
|
仅运行一遍任务
在某些情况下,下载资源到本地时,你只需要下载一次就可以。但是任务却执行和主机清单中相同的次数。得益于Ansible模块幂等性,虽然说任务运行很多次,但只有第一次真正进行了下载,对我们的影响不大。但是能否继续减少性能开支呢。
使用run_once: true
关键字让任务或代码块只运行一次。
1 2 3 4 5 6 7 8 9 10 11 12
| - hosts: all gather_facts: no tasks: - get_url: url: "https://github.com/rofl0r/proxychains-ng/archive/v4.14.tar.gz" dest: "/tmp" connection: local run_once: true - copy: src: "/tmp/v4.14.tar.gz" dest: "/tmp"
|
遇到过的错误…
在when关键字中使用了Jinja2语法
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found:XXX
在when关键字中不应该包含Jinja2语法。在使用循环或者变量时不小心就会顺手把花括号加上。此时会发出警告。
1 2 3 4 5
| 错误用法: when: "'{{item.hosts}}' in group_names"
正确用法: when: item.hosts in group_names
|
没有获取事实就要使用hostvars
获取变量
在主机没有gether facts事实之前,是无法通过hostvars来获取它的事实变量的。这个错误在生成hosts文件时出现过一次,折腾了好久。难受的是没有指向正确的报错位置,这导致我在错误的方向研究了好久都没有解决。
1 2 3 4 5 6 7
| 错误用法: when: "'{{item.hosts}}' in group_names"
---
正确用法: when: item.hosts in group_names
|