新聞中心
背景
openEuler 是什么
openEuler22.03 LTS 是 openEuler 社區(qū)于 2022 年 3 月發(fā)布的開(kāi)源操作系統(tǒng)(從系統(tǒng)版本的命名不難發(fā)現(xiàn)吧)。openEuler 社區(qū)的運(yùn)營(yíng)由華為為主導(dǎo),社區(qū)以全球開(kāi)源貢獻(xiàn)者的合作,構(gòu)建了這個(gè)高效、穩(wěn)定和安全的操作系統(tǒng)?;?Linux 內(nèi)核的 openEuler 操作系統(tǒng),支持 Kunpeng 以及其他處理器,旨在充分發(fā)揮計(jì)算芯片的潛力。它適用于數(shù)據(jù)庫(kù)、大數(shù)據(jù)、云計(jì)算和人工智能等場(chǎng)景。通過(guò)社區(qū)合作,openEuler 構(gòu)建了一個(gè)創(chuàng)新平臺(tái),創(chuàng)建了一個(gè)支持多處理器架構(gòu)的統(tǒng)一開(kāi)放操作系統(tǒng),并推動(dòng)了軟件和硬件應(yīng)用生態(tài)系統(tǒng)的繁榮。

openEuler22.03 LTS 帶來(lái)了一系列關(guān)鍵功能,包括基于 Linux Kernel 5.10 的深度優(yōu)化、新型媒體文件系統(tǒng)、分層內(nèi)存擴(kuò)展、用戶模式協(xié)議棧、云原生調(diào)度增強(qiáng)、QEMU 熱補(bǔ)丁、KubeOS、增強(qiáng)的輕量級(jí)安全容器、增強(qiáng)的 iSulad、雙平面部署、邊緣計(jì)算支持、嵌入式鏡像,以及 secPaver 等。
openEuler22.03 LTS 可以被視為國(guó)產(chǎn)操作系統(tǒng)創(chuàng)新項(xiàng)目的首選系統(tǒng)版本之一。
GreatSQL 是什么
GreatSQL,作為 MySQL 分支 Percona 的延伸,立志成為中國(guó)廣泛受歡迎的開(kāi)源數(shù)據(jù)庫(kù)。其上一版本基于 Percona Server 8.0.25 構(gòu)建,而這次的新版本則使用 Percona Server 8.0.32 作為基礎(chǔ),引入了許多重要特性。新發(fā)布的 GreatSQL 8.0.32-24 版本增加了并行 load data、邏輯和 CLONE 備份加密、MGR 讀寫(xiě)節(jié)點(diǎn)可動(dòng)態(tài)綁定 VIP、SQL 兼容擴(kuò)展、審計(jì)日志增強(qiáng)等重大特性。
GreatSQL 8.0.32-24 可以被視為國(guó)產(chǎn)開(kāi)源數(shù)據(jù)庫(kù)信創(chuàng)項(xiàng)目,并且解決 MySQL5.7 EOL 問(wèn)題的重要替代方案之一。
dbops 是什么
dbops 是一款提供生產(chǎn)級(jí)別 MySQL 部署的 playbook 工具,由芬達(dá)個(gè)人開(kāi)發(fā)。
地址: https://gitee.com/fanderchan/dbops/
GreatSQL 官方并未提供專門針對(duì) openEuler 的編譯安裝包,而我發(fā)現(xiàn)部署 GreatSQL、GreatSQL MGR、GreatSQL HA 等都有許多細(xì)節(jié)需要注意。本文主要講述我如何思考并開(kāi)發(fā) dbops 的新功能,以在 openEuler22 上成功部署 GreatSQL,并運(yùn)行其"MGR 讀寫(xiě)節(jié)點(diǎn)可動(dòng)態(tài)綁定 VIP"功能(以下簡(jiǎn)稱"GreatSQL HA 功能")。
dbops 如何支持 GreatSQL
dbops 本來(lái)就支持 MySQL 和 Percona,所以對(duì) GreatSQL 的支持并不需要大規(guī)模的改動(dòng)。以下大部分是一些針對(duì)部署 GreatSQL 與 MySQL 或 Percona 的不同之處的調(diào)整。
1. 只對(duì) Linux - Generic 包的支持
由于 dbops 的目標(biāo)是支持大量的國(guó)產(chǎn)操作系統(tǒng),與 MySQL 一樣,GreatSQL 提供了針對(duì)各種操作系統(tǒng)的預(yù)編譯二進(jìn)制包,但有一個(gè)是通用的,那就是 Linux - Generic 包。在 dbops 為 MySQL 提供支持以及在實(shí)際生產(chǎn)中,都在使用這個(gè)包。
同時(shí),為了支持更多的 Linux 系統(tǒng),我選擇了基于 glibc2.17 的包,而非 glibc2.28 的包。前者意味著包是在 glibc 公共庫(kù)版本為 2.17 的系統(tǒng)下編譯出來(lái)的,因此,它不會(huì)包含大于 2.17 的庫(kù)函數(shù),兼容性會(huì)更強(qiáng)。
我選擇支持的是 minimal 包,這個(gè)版本剔除了與調(diào)試相關(guān)的二進(jìn)制文件和調(diào)試符號(hào),體積非常小,僅為常規(guī)包的三分之一,我認(rèn)為非 minimal 包并無(wú)優(yōu)勢(shì)。
目前,dbops 僅支持 GreatSQL-8.0.32-24-Linux-glibc2.17-x86_64.tar.xz 的部署。
2. dbops 的 mysql_ansible 的配置文件 common_config.yml 的調(diào)整
dbops 可以很方便的配置執(zhí)行 playbook 的變量,變量設(shè)置非常集中,一般只需要修改兩個(gè)文件,一個(gè)是全局參數(shù)配置文件 common_config.yml,另外一個(gè)是當(dāng)前需要執(zhí)行的 playbook yaml 文件。
- 新增了 db_type 參數(shù),用于判斷待部署的數(shù)據(jù)庫(kù)類型,可選值為 MySQL、Percona、GreatSQL。根據(jù) db_type 的不同,部署流程將有所區(qū)別。
- 將 mysql_base_dir 參數(shù)和 mysql_data_dir_base 參數(shù)設(shè)定為根據(jù) db_type 自動(dòng)生成,這樣可以得到不同的目錄路徑。我希望避免將 MySQL 和 GreatSQL 放置在同一目錄下,以便于區(qū)分。
- 對(duì)于 mysql_package 參數(shù),即安裝包的名稱,如果是 MySQL,會(huì)根據(jù) {{ mysql_version }} 自動(dòng)生成;如果是 GreatSQL,將讀取 greatsql_package 的設(shè)置。
- 新增了 fcs_use_greatsql_ha 開(kāi)關(guān)參數(shù),其默認(rèn)值為 1,即如果部署的是 GreatSQL 并且采用 MGR 架構(gòu)(執(zhí)行的 playbook==mgr.yml),那么默認(rèn)會(huì)部署"MGR 讀寫(xiě)節(jié)點(diǎn)可動(dòng)態(tài)綁定 VIP"的功能插件。
## DB TYPE,suport mysql,percona,greatsql
+ db_type: greatsql
#Directory of MySQL installation package
mysql_packages_dir: ../downloads/
+ greatsql_package: GreatSQL-8.0.32-24-Linux-glibc2.17-x86_64-minimal.tar.xz
+ percona_package: Percona-Server-8.0.29-21-Linux.x86_64.glibc2.17.tar.gz
## do not modify
- mysql_package: "{{ 'mysql-' + mysql_version + '-linux-' + ('glibc2.12' if mysql_version.startswith('5.') else 'glibc2.17') + '-x86_64' + ('.tar.gz' if mysql_version.startswith('5.') else '-minimal.tar.xz') }}"
+ mysql_package: "{% if db_type == 'mysql' %}{{ 'mysql-' + mysql_version + '-linux-' + ('glibc2.12' if mysql_version.startswith('5.') else 'glibc2.17') + '-x86_64' + ('.tar.gz' if mysql_version.startswith('5.') else '-minimal.tar.xz') }}{% elif db_type == 'percona' %}{{ percona_package }}{% elif db_type == 'greatsql' %}{{ greatsql_package }}{% endif %}"
## linux mysql run user name
mysql_user: mysql
mysql_group: mysql
mysql_user_password: Dbops@9999
## mysql install directory
- mysql_base_dir: /database/mysql/base/{{ mysql_version }}
+ mysql_base_dir: /database/{{ db_type }}/base/{{ mysql_version }}
## mysql_data_dir_base define mysql datadir base, real datadir= mysql_data_dir_base + /port
- mysql_data_dir_base: /database/mysql
+ mysql_data_dir_base: /database/{{ db_type }}
+ fcs_use_greatsql_ha: 13. 新增 GreatSQL 專屬 my.cnf 模板,并對(duì) GreatSQL HA 的新參數(shù)支持
在 mgr.yml 這個(gè) playbook 里新增三個(gè)與 GreatSQL HA 相關(guān)的參數(shù)設(shè)置
+ greatsql_vip: 192.168.199.174
+ greatsql_net_work_interface: "ens33"
+ greatsql_netmast: "255.255.255.255"新增了 mysql_ansible/roles/mysql_server/templates/8.0/greatsql-my.cnf.j2 模板,此模板是從 percona-my.cnf.j2 模板克隆而來(lái)。為了支持 GreatSQL HA 的相關(guān)參數(shù)設(shè)置,我使用 jinja2 語(yǔ)法設(shè)置了判斷邏輯,只有滿足以下三個(gè)條件,才會(huì)添加這些參數(shù):
- 數(shù)據(jù)庫(kù)類型為 'greatsql' (在 common_config.yml 中設(shè)置)
- 設(shè)置了 fcs_use_greatsql_ha: 1 開(kāi)關(guān),要求部署 GreatSQL HA 功能(在 common_config.yml 中設(shè)置)
- 在安裝 MGR 時(shí)(運(yùn)行 ansible-playbook mgr.yml 時(shí))
+ {% if db_type == 'greatsql' and fcs_use_greatsql_ha == 1 and make_mgr_role_included is defined and make_mgr_role_included %}
+ #GreatSQL MGR vip
+ plugin-load-add=greatdb_ha.so
+ loose-greatdb_ha_enable_mgr_vip=1
+ loose-greatdb_ha_mgr_vip_ip={{ greatsql_vip }}
+ loose-greatdb_ha_mgr_vip_mask={{ greatsql_netmast }}
+ loose-greatdb_ha_mgr_vip_nic={{ greatsql_net_work_interface }}
+
+ #single-primary mode
+ loose-group_replication_single_primary_mode=1
+ loose-group_replication_enforce_update_everywhere_checks=0
+ {% endif %}前面設(shè)置的三個(gè)參數(shù)值,greatsql_vip、greatsql_netmast、greatsql_net_work_interface 會(huì)對(duì)應(yīng)傳入到 my.cnf 里。
4. 支持自動(dòng)下載 GreatSQL 安裝包
+ - name: Download GreatSQL binary tarball if not found locally and auto download is enabled(local)
+ ansible.builtin.get_url:
+ url: "https://product.greatdb.com/{{ mysql_package[0:18] }}/{{ mysql_package }}"
+ dest: "{{ mysql_packages_dir }}/{{ mysql_package }}"
+ mode: '0644'
+ timeout: 30
+ headers:
+ User-Agent: "Wget/1.21.1"
+ when: not mysql_server__package_file.stat.exists and fcs_auto_download_mysql == 1 and db_type == 'greatsql'
+ delegate_to: 127.0.0.1在正常情況下,您應(yīng)該手動(dòng)上傳 GreatSQL 的包到 downloads/ 文件夾中。如果在 downloads/ 文件夾中沒(méi)有找到對(duì)應(yīng)的包,且在 common_config.yml 文件中設(shè)置了 fcs_auto_download_mysql == 1(允許從互聯(lián)網(wǎng)下載安裝包),并且 db_type == 'greatsql',那么將會(huì)自動(dòng)從互聯(lián)網(wǎng)下載安裝包。
dbops 本身就支持下載 MySQL 安裝包的功能。但由于 GreatSQL 的安裝包下載路徑不同,因此我額外添加了一個(gè)下載鏈接,以實(shí)現(xiàn)相同的下載功能。
5. 修改 GreatSQL 啟動(dòng)服務(wù)
為了讓 GreatSQL HA 支持 mysqld 執(zhí)行通常需要較高權(quán)限才能操作的掛載和卸載 VIP 操作,我們需要進(jìn)行一些特殊設(shè)置。官方原先提供了兩個(gè)方案,但我提出了新的解決方案。
在服務(wù)設(shè)置中,我們加入以下代碼:
[Service]
+ {% if db_type == 'greatsql' and fcs_use_greatsql_ha == 1 and make_mgr_role_included is defined and make_mgr_role_included %}
+ AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
+ {% endif %}只有當(dāng)滿足條件(需要部署 GreatSQL HA)時(shí),系統(tǒng)會(huì)自動(dòng)在啟動(dòng)服務(wù)中配置 "CAP_NET_ADMIN CAP_NET_RAW" 的權(quán)限。
我設(shè)計(jì)的這種方法也得到了官方的采納,成為首選推薦方法。
6. fix 部署 GreatSQL 有可能報(bào)錯(cuò)的問(wèn)題
GreatSQL 在部署后可能在使用 mysqld 初始化時(shí),或者初始化后使用 mysql 登錄時(shí),報(bào)告 libcrypto.so 或 libssl.so 找不到。
[root@192-168-199-171 ~]# /usr/local/mysql/bin/mysqld --defaults-file=/database/mysql/etc/3306/my.cnf --initialize-insecure
/usr/local/mysql/bin/mysqld: error while loading shared libraries: libcrypto.so: cannot open shared object file: No such file or directory
[root@192-168-199-171 lib]# mysql -uroot -p -S /database/mysql/data/3307/mysql.sock
mysql: error while loading shared libraries: libssl.so: cannot open shared object file: No such file or directory針對(duì)此問(wèn)題,我們有兩種解決方案。第一種方法是使用 yum install openssl-devel 安裝,之后系統(tǒng)庫(kù)就會(huì)包含這兩個(gè) so 庫(kù):
/usr/lib64/libcrypto.so
/usr/lib64/libssl.so然而,我們也有第二種解決方法。GreatSQL 的 Generic 包其實(shí)已經(jīng)編譯了這兩個(gè)庫(kù),只是它們被命名為 libcrypto.so.10 和 libssl.so.10,而非 libcrypto.so 和 libssl.so。我們只需在 /usr/local/mysql/lib/private/ 文件夾內(nèi)為這兩個(gè)庫(kù)創(chuàng)建軟鏈接即可。
并且,我認(rèn)為采用第二種方法,使用官方包內(nèi)的 libcrypto.so 和 libssl.so,是最佳的解決方案。
改動(dòng)代碼如下:
mysql_ansible/roles/mysql_server/tasks/fix_greatsql_install.yml
+ - name: Create symbolic links for libssl.so and libcrypto.so
+ file:
+ src: "/usr/local/mysql/lib/private/{{ link.src }}"
+ dest: "/usr/local/mysql/lib/private/{{ link.dest }}"
+ state: link
+ owner: "{{ mysql_user }}"
+ group: "{{ mysql_group }}"
+ loop:
+ - { src: 'libssl.so.10', dest: 'libssl.so' }
+ - { src: 'libcrypto.so.10', dest: 'libcrypto.so' }
+ loop_control:
+ loop_var: linkmysql_ansible/roles/mysql_server/tasks/main.yml
- name: Install mysql to /usr/local/mysql
ansible.builtin.import_tasks: install_mysql.yml
+ - name: Fix libcrypto.so and libssl.so not find by create link if db_type is greatsql
+ ansible.builtin.import_tasks: fix_greatsql_install.yml
+ when: db_type == 'greatsql'
- name: Init mysql datadir
ansible.builtin.import_tasks: initialize_mysql_datadir.yml7. 檢查網(wǎng)卡是否一致
在設(shè)定了 VIP 漂移的三臺(tái)機(jī)器中,與 MHA 架構(gòu)相同,我們可能會(huì)遇到一種狀況:在一開(kāi)始設(shè)置網(wǎng)卡綁定時(shí),主機(jī)管理員可能會(huì)沒(méi)注意,發(fā)生以下情況:
192.168.199.171 網(wǎng)卡名 bond1
192.168.199.172 網(wǎng)卡名 bond1
192.168.199.173 網(wǎng)卡名 bond0你可能已經(jīng)發(fā)現(xiàn)了,第三臺(tái)機(jī)器的網(wǎng)卡名與前兩臺(tái)不一致。因此,如果發(fā)生高可用漂移,MHA 或 MGR 在選擇主機(jī)時(shí),如果選擇了第三臺(tái)作為主機(jī),那么根據(jù) greatsql_net_work_interface: "bond1" 的設(shè)置,漂移操作可能會(huì)失敗。雖然我還沒(méi)有進(jìn)行過(guò)測(cè)試,但這個(gè)問(wèn)題在 MHA 架構(gòu)中肯定會(huì)發(fā)生,而且在 GreatSQL HA 架構(gòu)中也有很大可能發(fā)生!
因此,在運(yùn)行 ansible-playbook 部署 mgr.yml 時(shí),我已在第一步的 pre_check_and_set(檢查和設(shè)置系統(tǒng)參數(shù))中,加入了檢查網(wǎng)卡名是否一致的步驟。如果網(wǎng)卡名不一致,playbook 將報(bào)錯(cuò)并終止運(yùn)行,給出提示。代碼如下:
- name: Add network interface alias to a temporary file
ansible.builtin.lineinfile:
path: "/tmp/net_aliases.txt"
line: "{{ ansible_default_ipv4.alias }}"
create: true
mode: '0644'
- name: Fetch copy
ansible.builtin.fetch:
src: /tmp/net_aliases.txt
dest: /tmp/ssh
- name: Append file /tmp/net_aliases.txt (delegate to 127.0.0.1)
ansible.builtin.shell: set -o pipefail && find /tmp/ssh/ -name "*.txt" -type f -exec sh -c 'cat {}' \; | sort | uniq | wc -l
register: pre_check_and_set__shell_output
changed_when: false
run_once: true
delegate_to: 127.0.0.1
- name: Check if shell output is 1
ansible.builtin.assert:
that: pre_check_and_set__shell_output.stdout | int == 1
fail_msg: "Network card names are different!"
run_once: true
delegate_to: 127.0.0.1
- name: Delete /tmp/net_aliases.txt
ansible.builtin.file:
path: /tmp/net_aliases.txt
state: absent
- name: Delete /tmp/ssh/ (delegate to 127.0.0.1)
ansible.builtin.file:
path: /tmp/ssh/
state: absent
run_once: true
delegate_to: 127.0.0.18. 支持使用 jemalloc 內(nèi)存分配器
GreatSQL 和 Percona 官方都推薦使用 jemalloc 替代默認(rèn)的 malloc,我至今沒(méi)有發(fā)現(xiàn) MySQL 官方的類似建議。然而,在實(shí)踐中,我曾經(jīng)通過(guò)替換 malloc 為 jemalloc 內(nèi)存管理器來(lái)解決內(nèi)存泄露問(wèn)題,盡管根本原因仍不清楚。因此,我之前已經(jīng)在我的 dbops 工具中加入了在部署時(shí)選擇使用 jemalloc 內(nèi)存分配器的功能,它是在 systemd 服務(wù)中實(shí)現(xiàn)的。
以下是涉及的代碼:
mysql_ansible/playbooks/common_config.yml
# 配置文件中提供一個(gè)開(kāi)關(guān),決定是否使用 jemalloc 內(nèi)存分配器,其默認(rèn)值為 0,即不修改內(nèi)存分配器
fcs_mysql_use_jemalloc: 1mysql_ansible/roles/mysql_server/tasks/install_mysql_dependents.yml
- name: Install libaio and numactl
ansible.builtin.yum:
name: "{{ package.name }}"
state: present
loop:
- { name: 'libaio' }
- { name: 'numactl' }
loop_control:
loop_var: package
tags:
- dependents
- name: Install jemalloc
when: fcs_mysql_use_jemalloc == 1
tags:
- dependents
block:
- name: Install jemalloc using yum
ansible.builtin.yum:
name: jemalloc
state: present
register: mysql_server__jemalloc_install_result
ignore_errors: true
- name: Set jemalloc rpm file name based on OS
ansible.builtin.set_fact:
mysql_server__jemalloc_rpm_file: "{{ 'jemalloc-3.6.0-1.el8.x86_64.rpm' if os_type in ['openEuler22', 'openEuler20', 'CentOS8', 'BigCloud8', 'Anolis OS8'] else 'jemalloc-3.6.0-1.el7.x86_64.rpm' }}"
- name: Copy jemalloc rpm to target server
ansible.builtin.copy:
src: "../files/{{ mysql_server__jemalloc_rpm_file }}"
dest: "/tmp/{{ mysql_server__jemalloc_rpm_file }}"
mode: '0755'
when: mysql_server__jemalloc_install_result.failed
- name: Install jemalloc from local file
ansible.builtin.yum:
name: "/tmp/{{ mysql_server__jemalloc_rpm_file }}"
state: present
disable_gpg_check: true
register: mysql_server__jemalloc_local_install_result
when: mysql_server__jemalloc_install_result.failed
ignore_errors: true
- name: Check if jemalloc installation failed
ansible.builtin.fail:
msg: "Failed to install jemalloc"
when: mysql_server__jemalloc_install_result.failed and mysql_server__jemalloc_local_install_result.failed這段代碼主要是用于安裝 mysql_server 的依賴包,如果你在配置中設(shè)置了 fcs_mysql_use_jemalloc: 1,那么將會(huì)安裝 jemalloc。默認(rèn)情況下,它會(huì)嘗試使用 yum 來(lái)安裝。如果 yum 安裝失敗,那么它會(huì)嘗試使用 dbops 自帶的 jemalloc 包。
原因是,預(yù)備的 jemalloc 包只有兩個(gè)版本:一個(gè)是針對(duì) EL7,一個(gè)是針對(duì) EL8。并沒(méi)有專門為國(guó)產(chǎn)操作系統(tǒng)準(zhǔn)備的專用包。在國(guó)產(chǎn)操作系統(tǒng)上,你應(yīng)該優(yōu)先使用 yum 來(lái)安裝適合該系統(tǒng)的包。如果使用 yum 安裝失敗,你可以考慮使用 EL7 或者 EL8 的 jemalloc 包來(lái)進(jìn)行兼容性安裝。
mysql_ansible/roles/mysql_server/templates/mysql.service.j2
[Service]
...
{% if fcs_mysql_use_jemalloc == 1 %}
{% if os_type in ['openEuler22','openEuler20'] %}
Envirnotallow="LD_PRELOAD=/usr/lib64/libjemalloc.so.2"
{% else %}
Envirnotallow="LD_PRELOAD=/usr/lib64/libjemalloc.so.1"
{% endif %}
{% endif %}根據(jù) yum 或者 rpm 包方式安裝 libjemalloc 后,不同操作系統(tǒng)的 libjemalloc.so 路徑可能會(huì)不同,我在服務(wù)配置里會(huì)做判斷和正確加載。
芬達(dá),《芬達(dá)的數(shù)據(jù)庫(kù)學(xué)習(xí)筆記》公眾號(hào)作者,開(kāi)源愛(ài)好者,擅長(zhǎng) MySQL、ansible。
分享題目:OpenEuler22+GreatSQL+Dbops玩轉(zhuǎn)MGR
文章來(lái)源:http://fisionsoft.com.cn/article/djjpgsc.html


咨詢
建站咨詢
