使用Ansible自动部署MGR中生成group_replication_group_seeds值的方法

使用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一下,否则是一个

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"
}

你可能感兴趣的:(Ansible,MGR)