生成group_replication_group_seeds值的方法 网卡不统一 之前我是通过groups['mfw_test'] | map('extract', hostvars, ['ansible_all_ipv4_addresses'])
这种形式, 去一个inventory group下每一个host的ansible_all_ipv4_addresses
ansible_all_ipv4_address是所有网卡上的ip, 包括手动添加的ip(例如vip)
1 2 3 4 5 6 "msg" : { "centos-1" : { "ansible_all_ipv4_addresses" : [ "192.168.124.136" , "172.16.120.10" ],
我们可以通过下面的playbook查看hostvars
1 2 - debug: msg: " {{ hostvars }} "
上面的情况是没有vip, 也就是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [root@ centos-1 ~]# ip a 1 : lo: <LOOPBACK,UP,LOWER_UP> 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 forever 2 : ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00 :0 c: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:334 a/64 scope link tentative dadfailed valid_lft forever preferred_lft forever inet6 fe80::2f 9b:31f 4:73e6 :e438/64 scope link tentative dadfailed valid_lft forever preferred_lft forever 3 : ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00 :50 :56 :2 c:1 a: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 1452 sec preferred_lft 1452 sec inet6 fe80::5 c28:fb1e:459 :1 b9/64 scope link valid_lft forever preferred_lft forever
如果有vip则是
1 2 3 4 5 6 7 "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等等). 时间长了就成了这么一坨
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 {%- 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里
1 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 "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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 "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'])
于是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [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=vagrant ansible_port=22 ansible_become=true
playbook
1 2 3 4 5 6 7 --- - 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的
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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
接下来要用到zip_longest
拿官方文档的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 - 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 }}"
结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 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取”补齐”
于是我们就可以
1 2 3 - 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>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 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拼接
1 2 3 - 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}} "
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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" ] }
最后
1 2 3 4 5 6 7 8 9 --- - 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(',' )}} "
1 2 3 4 5 6 7 8 9 10 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" }
附1: 生产group_replication_local_address的方法 使用hostvars[inventory_hostname]
1 2 3 - name: "hostvars[inventory_hostname ]['ansible_ens33' ]['ipv4' ]['address' ]:23306" debug: msg: "{{ hostvars[inventory_hostname]['ansible_ens33']['ipv4']['address'] }}:2{{ mysql_port }}"
1 2 3 4 5 6 7 8 9 10 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" }
同样, 如果网卡不统一, 只能…
1 2 3 4 5 {% 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 %}
附2: /etc/hosts 网卡不统一
1 2 3 4 5 6 - name: 设置/etc/ hosts blockinfile: path: /etc/ hosts block: | {{ item }} with_items: "{{ etc_hosts }}"
1 2 3 4 5 6 7 8 9 10 11 12 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 %}
网卡统一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 --- - 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 }} "
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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 ~] 172.16 .120.10 centos-1 172.16 .120.11 centos-2 172.16 .120.12 centos-3
注意hostname要用groups['mysql']|map('extract', hostvars, ['ansible_hostname'])
取, 不能直接ansible_hostname
1 2 3 - 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
1 2 3 4 5 6 7 8 9 10 11 12 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" }