使用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一下,否則是一個<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"
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章