本文共 19307 字,大约阅读时间需要 64 分钟。
之前我是通过groups['mfw_test'] | map('extract', hostvars, ['ansible_all_ipv4_addresses'])
这种形式, 去一个inventory group下每一个host的ansible_all_ipv4_addresses
ansible_all_ipv4_address是所有网卡上的ip, 包括手动添加的ip(例如vip)
"msg": { "centos-1": { "ansible_all_ipv4_addresses": [ "192.168.124.136", "172.16.120.10" ],
我们可以通过下面的playbook查看hostvars
- debug: msg: "{ { hostvars }}"
上面的情况是没有vip, 也就是
[root@centos-1 ~]# ip a1: lo:mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever2: ens33: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:b2:18:33 brd ff:ff:ff:ff:ff:ff inet 172.16.120.10/24 brd 172.16.120.255 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::e880:2501:cdab:b11d/64 scope link tentative dadfailed valid_lft forever preferred_lft forever inet6 fe80::ada9:2128:e605:334a/64 scope link tentative dadfailed valid_lft forever preferred_lft forever inet6 fe80::2f9b:31f4:73e6:e438/64 scope link tentative dadfailed valid_lft forever preferred_lft forever3: ens37: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:50:56:2c:1a:a8 brd ff:ff:ff:ff:ff:ff inet 192.168.124.166/24 brd 192.168.124.255 scope global dynamic ens37 valid_lft 1452sec preferred_lft 1452sec inet6 fe80::5c28:fb1e:459:1b9/64 scope link valid_lft forever preferred_lft forever
如果有vip则是
"msg": { "centos-1": { "ansible_all_ipv4_addresses": [ "192.168.124.136", "172.16.120.10", "172.16.120.100" ],
之前我为了解决现实服务器网卡名称不统一的问题(现实有叫em2的有叫p6p1的还有team0, eth0等等, 而cmdb中又没有这些信息), 采用了ansible_all_ipv4_addresses
的方法, 取所有ip, 然后根据规则自己过滤(比如过滤掉vip等等). 时间长了就成了这么一坨
{%- for ip_list in (groups[group] | map('extract', hostvars, ['ansible_all_ipv4_addresses'])) -%} {%- if loop.last -%} {%- for ip in ip_list -%} {%- if (ip.startswith('192.168') or ip.startswith('10.163') or ip.startswith('10.152') or ip.startswith('10.132') or ip.startswith('10.133')) and not ip.startswith('192.168.3') and not ip.startswith('192.168.8') and not ip.startswith('192.168.16') and not ip.startswith('10.62') and not ip.startswith('10.32') and not ip.startswith('10.52') and not ip.startswith('10.33') and not (ip.startswith('10.133.1.2') and ip.split('.')[3]|int>=200) -%} { { ip }}:2{ { mysql_port }} {%- endif -%} {%- endfor %} {%- else -%} {%- for ip in ip_list -%} {%- if (ip.startswith('192.168') or ip.startswith('10.163') or ip.startswith('10.152') or ip.startswith('10.132') or ip.startswith('10.133')) and not ip.startswith('192.168.3') and not ip.startswith('192.168.8') and not ip.startswith('192.168.16') and not ip.startswith('10.62') and not ip.startswith('10.32') and not ip.startswith('10.52') and not ip.startswith('10.33') and not (ip.startswith('10.133.1.2') and ip.split('.')[3]|int>=200) -%} { { ip }}:2{ { mysql_port }}, {%- endif -%} {%- endfor -%} {%- endif -%}{%- endfor -%}
写到vars/main.yaml里
group_replication_group_seeds: "{%- for ip_list in (groups[group] | map('extract', hostvars, ['ansible_all_ipv4_addresses'])) -%}{%- if loop.last -%}{%- for ip in ip_list -%}{%- if (ip.startswith('192.168') or ip.startswith('10.163') or ip.startswith('10.152') or ip.startswith('10.132') or ip.startswith('10.133')) and not ip.startswith('192.168.3') and not ip.startswith('192.168.8') and not ip.startswith('192.168.16') and not ip.startswith('10.62') and not ip.startswith('10.32') and not ip.startswith('10.52') and not ip.startswith('10.33') and not (ip.startswith('10.133.1.2') and ip.split('.')[3]|int>=200) -%}{ { ip }}:2{ { mysql_port }}{%- endif -%}{%- endfor %}{%- else -%}{%- for ip in ip_list -%}{%- if (ip.startswith('192.168') or ip.startswith('10.163') or ip.startswith('10.152') or ip.startswith('10.132') or ip.startswith('10.133')) and not ip.startswith('192.168.3') and not ip.startswith('192.168.8') and not ip.startswith('192.168.16') and not ip.startswith('10.62') and not ip.startswith('10.32') and not ip.startswith('10.52') and not ip.startswith('10.33') and not (ip.startswith('10.133.1.2') and ip.split('.')[3]|int>=200) -%}{ { ip }}:2{ { mysql_port }},{%- endif -%}{%- endfor -%}{%- endif -%}{%- endfor -%}"
如果网卡是统一的, 或者我们能知道要部署服务器的网卡叫什么.
一个部署任务的机器网卡名称要一致, 否则下面的方法也用不了
观察hostvars可以发现
ansible_ens33无vip
"msg": { "centos-1": { "ansible_all_ipv4_addresses": [ "192.168.124.136", "172.16.120.10" ], ...省略 "ansible_ens33": { "active": true, "device": "ens33", ...省略 "hw_timestamp_filters": [], "ipv4": { "address": "172.16.120.10", "broadcast": "172.16.120.255", "netmask": "255.255.255.0", "network": "172.16.120.0" }, "ipv6": [ { "address": "fe80::e880:2501:cdab:b11d", "prefix": "64", "scope": "link" } ],
ansible_ens33有vip
"msg": { "centos-1": { "ansible_all_ipv4_addresses": [ "192.168.124.136", "172.16.120.10", "172.16.120.100" ], ...省略 "ansible_ens33": { "active": true, "device": "ens33", ...省略 "hw_timestamp_filters": [], "ipv4": { "address": "172.16.120.10", "broadcast": "172.16.120.255", "netmask": "255.255.255.0", "network": "172.16.120.0" }, "ipv4_secondaries": [ --不知道为什么有俩 { "address": "172.16.120.100", "broadcast": "global", "netmask": "255.255.255.0", "network": "172.16.120.0" }, { "address": "172.16.120.100", "broadcast": "global", "netmask": "255.255.255.0", "network": "172.16.120.0" } ], "ipv6": [ { "address": "fe80::e880:2501:cdab:b11d", "prefix": "64", "scope": "link" } ],
可以这样取map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])
于是
[root@centos-4 ansible]# cat hosts[mysql]172.16.120.10 mysql_repl_role=master172.16.120.11 mysql_repl_role=slave172.16.120.12 mysql_repl_role=slave[mha]172.16.120.13[proxysql]172.16.120.10 weight=100 comment=PRIMARY172.16.120.11 weight=99 comment=SECONDARY172.16.120.12 weight=99 comment=SECONDARY[all:vars]ansible_user=root#ansible_password=vagrantansible_port=22ansible_become=true
playbook
---- name: '测试' hosts: mysql tasks: - name: " groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])|list" debug: msg: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])|list}}"
其中172.16.120.10还是有vip 172.16.120.100的
结果
TASK [groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])|list] *********************************************************************************************************************************************************************ok: [172.16.120.11] => { "msg": [ "172.16.120.10", "172.16.120.11", "172.16.120.12" ]}ok: [172.16.120.10] => { "msg": [ "172.16.120.10", "172.16.120.11", "172.16.120.12" ]}ok: [172.16.120.12] => { "msg": [ "172.16.120.10", "172.16.120.11", "172.16.120.12" ]}
到这一步这是取到了所有ip, 还没完成拼接出group_replication_group_seeds
接下来要用到
拿官方文档的例子
- name: '测试' hosts: 172.16.120.10 tasks: - name: give me list combo of two lists debug: msg: "{ { [1,2,3,4,5] | zip(['a','b','c','d','e','f']) | list }}" - name: give me shortest combo of two lists debug: msg: "{ { [1,2,3] | zip(['a','b','c','d','e','f'], ['!','@','#','$']) | list }}" - name: give me longest combo of three lists , fill with X debug: msg: "{ { [1,2,3] | zip_longest(['a','b','c','d','e','f'], [21, 22, 23], fillvalue='X') | list }}"
结果
TASK [give me list combo of two lists] *************************************************************************************************************************************************************************************************************************ok: [172.16.120.10] => { "msg": [ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ], [ 4, "d" ], [ 5, "e" ] ]}TASK [give me shortest combo of two lists] *********************************************************************************************************************************************************************************************************************ok: [172.16.120.10] => { "msg": [ [ 1, "a", "!" ], [ 2, "b", "@" ], [ 3, "c", "#" ] ]}TASK [give me longest combo of three lists , fill with X] ******************************************************************************************************************************************************************************************************ok: [172.16.120.10] => { "msg": [ [ 1, "a", 21 ], [ 2, "b", 22 ], [ 3, "c", 23 ], [ "X", "d", "X" ], [ "X", "e", "X" ], [ "X", "f", "X" ] ]}
可以看到在这前两个task中, “多余"的会被舍弃掉, 而且可以zip多个list, 最后一个task使用fillvalue取"补齐”
于是我们就可以
- name: " groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=':2'+mysql_port|string) |list" debug: msg: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address']) | list | zip_longest([], fillvalue=':2'+mysql_port|string) |list}}"
这里为了看到结果所以list一下,否则是一个<itertools.izip_longest object at 0x24468e8>
TASK [groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=':2'+mysql_port|string) |list] **********************************************************************************************************ok: [172.16.120.10] => { "msg": [ [ "172.16.120.10", ":23306" ], [ "172.16.120.11", ":23306" ], [ "172.16.120.12", ":23306" ] ]}ok: [172.16.120.11] => { "msg": [ [ "172.16.120.10", ":23306" ], [ "172.16.120.11", ":23306" ], [ "172.16.120.12", ":23306" ] ]}ok: [172.16.120.12] => { "msg": [ [ "172.16.120.10", ":23306" ], [ "172.16.120.11", ":23306" ], [ "172.16.120.12", ":23306" ] ]}
然后使用map(‘join’),就是将列表里的每一个元素使用join拼接
- name: " groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=':2'+mysql_port|string) | map('join')|list " debug: msg: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address']) | list | zip_longest([], fillvalue=':2'+mysql_port|string) | map('join') |list}}"
TASK [groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=':2'+mysql_port|string) | map('join')|list] *********************************************************************************************ok: [172.16.120.11] => { "msg": [ "172.16.120.10:23306", "172.16.120.11:23306", "172.16.120.12:23306" ]}ok: [172.16.120.10] => { "msg": [ "172.16.120.10:23306", "172.16.120.11:23306", "172.16.120.12:23306" ]}ok: [172.16.120.12] => { "msg": [ "172.16.120.10:23306", "172.16.120.11:23306", "172.16.120.12:23306" ]}
最后
---- name: '测试' hosts: mysql vars: mysql_port: 3306 tasks: - name: " groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=':2'+mysql_port|string) | map('join') | join(',')" debug: msg: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address']) | list | zip_longest([], fillvalue=':2'+mysql_port|string) | map('join') | join(',')}}"
TASK [groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=:3306) | map('join') | join(',')] *******************************************************************************************************ok: [172.16.120.10] => { "msg": "172.16.120.10:23306,172.16.120.11:23306,172.16.120.12:23306"}ok: [172.16.120.11] => { "msg": "172.16.120.10:23306,172.16.120.11:23306,172.16.120.12:23306"}ok: [172.16.120.12] => { "msg": "172.16.120.10:23306,172.16.120.11:23306,172.16.120.12:23306"}
使用hostvars[inventory_hostname]
- name: "hostvars[inventory_hostname]['ansible_ens33']['ipv4']['address']:23306" debug: msg: "{ { hostvars[inventory_hostname]['ansible_ens33']['ipv4']['address'] }}:2{ { mysql_port }}"
TASK [hostvars[inventory_hostname]['ansible_ens33']['ipv4']['address']:23306] **********************************************************************************************************************************************************************************ok: [172.16.120.10] => { "msg": "172.16.120.10:23306"}ok: [172.16.120.11] => { "msg": "172.16.120.11:23306"}ok: [172.16.120.12] => { "msg": "172.16.120.12:23306"}
同样, 如果网卡不统一, 只能…
{% for ip in ansible_all_ipv4_addresses -%} {% if (ip.startswith('192.168') or ip.startswith('10.163') or ip.startswith('10.152') or ip.startswith('10.132') or ip.startswith('10.133')) and not ip.startswith('192.168.3') and not ip.startswith('192.168.8') and not ip.startswith('192.168.16') and not ip.startswith('10.62') and not ip.startswith('10.32') and not ip.startswith('10.52') and not ip.startswith('10.33') and not (ip.startswith('10.133.1.2') and ip.split('.')[3]|int>=200) -%} loose-group_replication_local_address = { { ip }}:2{ { mysql_port }} {% endif %} {% endfor %}
网卡不统一
- name: 设置/etc/hosts blockinfile: path: /etc/hosts block: | { { item }} with_items: "{ { etc_hosts }}"
etc_hosts: | {% for ip_list in (groups[group] | map('extract', hostvars, ['ansible_all_ipv4_addresses'])) -%} {% set iploop = loop %} {% for ip in ip_list -%} {% for hostname in (groups[group] | map('extract', hostvars, ['ansible_hostname'])) -%} {% if loop.index == iploop.index -%} {% if (ip.startswith('192.168') or ip.startswith('10.163') or ip.startswith('10.152') or ip.startswith('10.132') or ip.startswith('10.133') ) and not ip.startswith('192.168.3') and not ip.startswith('192.168.8') and not ip.startswith('192.168.16') and not ip.startswith('10.62') and not ip.startswith('10.32') and not ip.startswith('10.52') and not ip.startswith('10.33') and not (ip.startswith('10.133.1.2') and ip.split('.')[3]|int>=200) -%} { { ip }} { { hostname }} {% endif %} {% endif %} {% endfor %} {% endfor %} {% endfor %}
网卡统一
---- name: '测试' hosts: mysql vars: etc_hosts: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address']) | list | zip(groups['mysql']|map('extract', hostvars, ['ansible_hostname'])) | map('join',' ') | join('\n') }}" tasks: - name: " groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip(groups['mysql']|map('extract', hostvars, ['ansible_hostname'])) | map('join',' ') | join('\n') " debug: msg: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address']) | list | zip(groups['mysql']|map('extract', hostvars, ['ansible_hostname'])) | map('join',' ') | join('\n') }}" - name: 设置/etc/hosts blockinfile: path: /tmp/hosts.test block: | { { item }} with_items: "{ { etc_hosts }}"
TASK [groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip(groups['mysql']|map('extract', hostvars, ['ansible_hostname'])) | map('join',' ') | join('')] ***************************************************************ok: [172.16.120.10] => { "msg": "172.16.120.10 centos-1\n172.16.120.11 centos-2\n172.16.120.12 centos-3"}ok: [172.16.120.11] => { "msg": "172.16.120.10 centos-1\n172.16.120.11 centos-2\n172.16.120.12 centos-3"}ok: [172.16.120.12] => { "msg": "172.16.120.10 centos-1\n172.16.120.11 centos-2\n172.16.120.12 centos-3"}[root@centos-1 ~]# cat /tmp/hosts.test # BEGIN ANSIBLE MANAGED BLOCK172.16.120.10 centos-1172.16.120.11 centos-2172.16.120.12 centos-3# END ANSIBLE MANAGED BLOCK
注意hostname要用groups['mysql']|map('extract', hostvars, ['ansible_hostname'])
取, 不能直接ansible_hostname
- name: " groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=' '+ansible_hostname) | map('join')| join('\n') " debug: msg: "{ { groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address']) | list | zip_longest([], fillvalue=' '+ansible_hostname) | map('join') | join('\n')}}"
看输出的结果hostname部分, 每个主机都只取到自己的hostname
TASK [groups['mysql']|map('extract', hostvars, ['ansible_ens33', 'ipv4', 'address'])| list | zip_longest([], fillvalue=' '+ansible_hostname) | map('join')| join('')] ****************************************************************************************ok: [172.16.120.10] => { "msg": "172.16.120.10 centos-1\n172.16.120.11 centos-1\n172.16.120.12 centos-1"}ok: [172.16.120.11] => { "msg": "172.16.120.10 centos-2\n172.16.120.11 centos-2\n172.16.120.12 centos-2"}ok: [172.16.120.12] => { "msg": "172.16.120.10 centos-3\n172.16.120.11 centos-3\n172.16.120.12 centos-3"}
转载地址:http://xkvub.baihongyu.com/