使用Ansible自動部署MGR中生成group_replication_group_seeds值的方法
生成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)
"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 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: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 forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> 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=master
172.16.120.11 mysql_repl_role=slave
172.16.120.12 mysql_repl_role=slave
[mha]
172.16.120.13
[proxysql]
172.16.120.10 weight=100 comment=PRIMARY
172.16.120.11 weight=99 comment=SECONDARY
172.16.120.12 weight=99 comment=SECONDARY
[all:vars]
ansible_user=root
#ansible_password=vagrant
ansible_port=22
ansible_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
接下來要用到zip_longest
拿官方文檔的例子
- 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"
}
附1: 生產group_replication_local_address的方法
使用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 %}
附2: /etc/hosts
網卡不統一
- 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 BLOCK
172.16.120.10 centos-1
172.16.120.11 centos-2
172.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"
}