自动化部署 / 扩容openGauss —— Ansible for openGauss
前言
大家好,今天我们为大家推荐一套基于 Ansible 开发的,自动化部署及扩容 openGauss 的脚本工具:Ansible for openGauss(以下简称 AFO)。
通过AFO,我们只需简单修改一些配置文件,即可快速部署多种架构模式的 openGauss,以及对已有架构进行自动化扩容。下面我们就请这套工具的贡献者,上海联空网络科技有限公司(以下简称“联空网络”)的李海滨,给大家讲解它的设计理念和优点。
开发背景
Hi,大家好,我是来自联空网络安全品质中心的运维工程师,李海滨。我是一名 Ansible 爱好者,致力于将运维工作自动化。曾获得 FISCO BCOS 区块链开源社区 2021 年度 MVP 称号。
联空网络成立于 2015 年 8 月,专注于提供医疗+互联网一站式技术和运营解决方案,帮助医疗用户更加轻松的拥抱互联网。目前,公司已经与 800+ 医疗机构用户形成合作关系,其中,百强医院合作 25+,三级医院 300+,上海地区客户覆盖率超 70%,覆盖全国 23 个省市。
当前自主创新、信息技术应用创新等需求日益增长,医疗行业用户十分关注软硬件产品解决方案的自主创新情况,为此联空网络积极响应,投入专业团队,对国内相关软硬件产品适配做可行性研判。
经过对国内数据库的深入了解,我们接触到了海量数据库,并获悉其是基于openGauss开源的商业发行版产品。openGauss 作为一款开源的关系型数据库管理系统,具有高性能、高可用性以及卓越的扩展能力。于是我们开始构想可以为研发团队提供 openGauss 环境,让其可以基于 openGauss 做代码适配。当客户选择使用海量数据库时,我们的软件就可以直接匹配。
为了方便反复部署测试,我拿出了擅长的 Ansible,为 openGauss 写一套自动化部署工具,以简化其安装、配置和管理过程。
完成初版开发后,我与 openGauss 社区取得了联系,表达了希望可以把这套工具贡献给社区,以开源回馈开源的想法。
感谢社区运营梅相如同学的大力支持,很快为我开设了代码仓库。又找来 openGauss 的开发工程师“行尘”同学,解答我在开发过程中遇到的一些问题。在此也很感谢“行尘”同学不厌其烦地回答,你们给予了我很大的帮助!
解决部署痛点
如果你有按照官方文档部署一套 openGauss 的经历,你会发现不论是单点还是集群,均需做不少的前期工作。例如要根据 CPU 和操作系统,下载对应版本的安装包。又需要根据不同的 Linux 操作系统,做一些额外配置。手工部署在这里不仅低效,而且容易有错漏。如果是多节点的部署,手工部署的弱势会被进一步放大。
我开发这套 Ansible 脚本的目标,就是尽可能地覆盖部署前、部署中和部署后的场景,并且把手工部署过程中遇到的一些坑,也通过自动化来解决掉。降低 openGauss 的部署门槛,推动 openGauss 的普及。
例如在 openEuler 20.03 系统里部署 openGauss 5.0,你会遇到 readline-devel 这个依赖包的版本是 8,而 openGauss 5.0 需要的是 libreadline.so.7,导致安装过程失败。我查找到解决方法后,加入到部署流程中,自动帮大家把这个坑给填了。代码在 roles\opengauss\tasks\os\openEuler.yml 里:
# openGauss 5.0.0 依赖 readline 7
# openEuler 20.03 只有 readline 8
- name: Create soft link
ansible.builtin.file:
src: "/lib64/libreadline.so.8"
dest: "/lib64/libreadline.so.7"
state: link
在给未部署 CM 的架构做扩容时,需要在主备之间做一次 switchover 后才能安装 CM。这些我们也加入到自动化流程中,免除了大家遇到这些问题还要花时间查找解决方法的麻烦。代码在 roles\opengauss\tasks\deploy\cluster_manager.yml 里:
- name: Switchover on a standby node
ansible.builtin.command:
gs_ctl switchover -D {{ og_data_path }}/dn
changed_when: false
loop: "{{ dn_nodes | select('search', 'Standby') }}"
loop_control:
loop_var: node
extended: true
when: "ansible_loop.index == 1"
delegate_to: "{{ hostvars[node]['node_ip'] }}"
- name: Switchover back to primary node
ansible.builtin.command:
gs_ctl switchover -D {{ og_data_path }}/dn
changed_when: false
loop: "{{ dn_nodes | select('search', 'Primary') }}"
loop_control:
loop_var: node
delegate_to: "{{ hostvars[node]['node_ip'] }}"
- name: Start any stopped nodes
ansible.builtin.command:
gs_om -t start
changed_when: false
部署过程中,有需要在 root 和 omm 账号之间多次切换的操作,Ansible 里用 become_user 就可以轻松自动切换。这些都是手工部署过程中的痛点。
已实现的功能
总结下来,目前我们这个工具能实现以下功能:
-
提供一个专属的 ansible-docker 子项目,只要控制机可运行 docker,即可运行一个 Ansible 容器,适配 AFO 的执行。对于不熟悉 Ansible 的同学非常友好。
-
自动适配 CPU 架构(条件受限,目前仅测试了 X86 架构)和操作系统(已支持 CentOS 和 openEuler 20.03),自动下载对应的 openGauss 安装包,自动对操作系统做适配修改。
-
实现从单节点到多节点的多种架构模式的一次性部署。
-
使用本工具部署的单点或集群,还能通过添加服务器,再次运行脚本,实现平滑扩容。实测可直接从单主扩容到 1 主 2 备 2 级联。
-
允许用户自定义一些变量,例如指定部署目录,指定 openGauss 版本(5.0 或以上),指定 sysctl 的参数配置。
-
免除手工部署中的问答环节,自动生成相关密码,自动填写。最后生成部署报告。
效率是如何提升的?
以配置网卡 MTU 为例,3 台服务器的执行时间如下:
Saturday 18 November 2023 20:54:50 +0800 (0:00:06.777) 0:01:03.288 *****
TASK [opengauss : Config MTU in /etc/sysconfig/network-scripts/ifcfg-enp0s8] *****************************************************************************************************************
changed: [192.168.56.11]
changed: [192.168.56.14]
changed: [192.168.56.15]
Saturday 18 November 2023 20:54:50 +0800 (0:00:00.517) 0:01:03.807 *****
Ansible 在 0.517 秒的时间内,完成了 3 台服务器的网卡 MTU 修改。因为,它是并行操作的。
以生成 cluster_config.xml 为例
3 台服务器的节点,手工写 cluster_config.xml,需要花费多少时间,各位可以自己计时看看。
而我们利用 Ansible 的模板功能,可以在 1 秒内生成该文件,编排非常清晰,一目了然。
假设服务器的分组配置 inventories/opengauss/hosts.ini 内容如下
[opengauss_primary]
192.168.56.11
; 备机,可设置若干个或留空。
[opengauss_standby]
192.168.56.15
; 级联机,可设置若干个或留空。前提是 opengauss_standby 组不为空。
[opengauss_cascade]
192.168.56.14
; 以上 3 个分组的合并组,勿动。
[opengauss:children]
opengauss_primary
opengauss_standby
opengauss_cascade
; 备节点分组,总数不可大于 8。
[opengauss_replicas:children]
opengauss_standby
opengauss_cascade
; 机器的 SSH 信息,请根据你的实际情况修改。
[opengauss:vars]
; ssh 用户名,如果不是 root 用户,请确保它有 sudo 权限。
ansible_ssh_user=vagrant
; ssh 密码
ansible_ssh_pass=vagrant
; ssh 端口
ansible_ssh_port=22
生成以下配置内容,仅需 1 秒钟。
<?xml version="1.0" encoding="utf-8"?>
<ROOT>
<CLUSTER>
<PARAM name="clusterName" value="openGauss" />
<PARAM name="gaussdbAppPath" value="/opt/openGauss/install/app" />
<PARAM name="gaussdbLogPath" value="/var/log" />
<PARAM name="tmpMppdbPath" value="/opt/openGauss/tmp"/>
<PARAM name="gaussdbToolPath" value="/opt/openGauss/install/om" />
<PARAM name="corePath" value="/opt/openGauss/corefile"/>
<PARAM name="nodeNames" value="og3232249867
,og3232249870
,og3232249871
"/>
<PARAM name="backIp1s" value="192.168.56.11
,192.168.56.14
,192.168.56.15
"/>
</CLUSTER>
<DEVICELIST>
<!-- CLUSTER PRIMARY -->
<DEVICE sn="og3232249867">
<PARAM name="name" value="og3232249867"/>
<PARAM name="instanceId" value="3232249867"/>
<PARAM name="azName" value="AZ1"/>
<PARAM name="azPriority" value="1"/>
<PARAM name="backIp1" value="192.168.56.11"/>
<PARAM name="sshIp1" value="192.168.56.11"/>
<!-- Data Node -->
<PARAM name="dataNum" value="1"/>
<PARAM name="dataPortBase" value="15400"/>
<PARAM name="dataNode1" value="/opt/openGauss/data/dn
,og3232249870,/opt/openGauss/data/dn
,og3232249871,/opt/openGauss/data/dn
"/>
<PARAM name="dataNode1_syncNum" value="0"/>
<!-- CLUSTER MANAGER -->
<PARAM name="cmsNum" value="1"/>
<PARAM name="cmServerPortBase" value="15300"/>
<PARAM name="cmServerlevel" value="1"/>
<PARAM name="cmDir" value="/opt/openGauss/data/cm"/>
<PARAM name="cmServerRelation" value="og3232249867
,og3232249870
,og3232249871
"/>
<PARAM name="cmServerListenIp1" value="192.168.56.11
,192.168.56.14
,192.168.56.15
"/>
<PARAM name="cmServerHaIp1" value="192.168.56.11
,192.168.56.14
,192.168.56.15
"/>
</DEVICE>
<DEVICE sn="og3232249870">
<PARAM name="name" value="og3232249870"/>
<PARAM name="azName" value="AZ1"/>
<PARAM name="azPriority" value="1"/>
<PARAM name="backIp1" value="192.168.56.14"/>
<PARAM name="sshIp1" value="192.168.56.14"/>
<!-- CLUSTER MANAGER -->
<PARAM name="cmServerPortStandby" value="15800"/>
<PARAM name="cmDir" value="/opt/openGauss/data/cm"/>
<!-- CASCADE ROLE -->
<PARAM name="cascadeRole" value="on"/>
</DEVICE>
<DEVICE sn="og3232249871">
<PARAM name="name" value="og3232249871"/>
<PARAM name="azName" value="AZ1"/>
<PARAM name="azPriority" value="1"/>
<PARAM name="backIp1" value="192.168.56.15"/>
<PARAM name="sshIp1" value="192.168.56.15"/>
<!-- CLUSTER MANAGER -->
<PARAM name="cmServerPortStandby" value="15800"/>
<PARAM name="cmDir" value="/opt/openGauss/data/cm"/>
</DEVICE>
</DEVICELIST>
</ROOT>
我们甚至考虑到了在机房里使用小尺寸显示器查看 cluster_config.xml 的场景,对 xml 做了换行处理,避免出现单行过长的问题。
自动化思路
AFO 主要的工作流如下:
-
对部署环境的信息进行采集。
-
将用户自定义的变量和脚本默认变量合并,优先使用自定义变量。
-
检查是否已部署 openGauss,如无,进入初次部署流程。
-
如果已部署 openGauss,则检查用户是否有添加新节点,进入节点扩容流程。
-
节点扩容流程里又分 2 步,先扩容备机节点,再扩容级联节点。因为级联节点只连接备机。
-
如果集群节点数量为 3 或以上,且未部署 CM,则进入 CM 部署流程。
-
最后,检查确认集群已正常运行,生成部署报告。
结果展示
以 3 台 VirtualBox 虚拟机为例,统一 8U+16GB 配置,都在 1 块物理 SATA 盘上读写。
另外,虚拟机都已经提前安装好相关依赖包,openGauss 安装包也已经下载到本地。排除网络下载速度的不确定因素。
单节点,4 分 40 秒(下图右下角)完成部署。
1 主 1 备,7 分 48 秒(下图右下角)完成部署。
从单点数据库,扩容为 1 主 1 备 1 级联,耗时 23 分(下图右下角)完成部署。
扩容模式需要额外的流程,因此耗时比直接部署 3 节点的要多。
最后生成部署报告
项目代码
这套工具已经收录在 openGauss 社区的官方代码库,欢迎大家前往下载试用,并向我们多多提出宝贵意见。
代码地址:https://gitee.com/opengauss/ansible-for-opengauss
使用前,请仔细阅读:https://gitee.com/opengauss/ansible-for-opengauss/blob/master/docs/01-ansible-in-docker.md 开启自动化部署的旅程。
参与贡献
-
欢迎对 Ansible 熟悉的同学,加入我们,改进完善我们的项目。
-
更欢迎大家提交 issue,提出宝贵的意见和建议。
-
也欢迎可以提供测试资源的同学,与我联系。目前我们需要 ARM 平台的测试环境。
TODO
-
增加 openGauss 相关生态软件的自动化部署,例如图形化管理,监控管理。
-
增加 ARM 平台的适配。
-
增加数据库定时备份的配置流程。
-
增加对 1 主 1 备架构的主备自动切换配置。
-
有限度地提供 gs_guc 自动化配置,方便运维人员对数据库参数做修改更新。
-
更多的想法,由你们来补充。
相关文章:

自动化部署 / 扩容openGauss —— Ansible for openGauss
前言 大家好,今天我们为大家推荐一套基于 Ansible 开发的,自动化部署及扩容 openGauss 的脚本工具:Ansible for openGauss(以下简称 AFO)。 通过AFO,我们只需简单修改一些配置文件,即可快速部署…...

Go 实现网络代理
使用 Go 语言开发网络代理服务可以通过以下步骤完成。这里,我们将使用 golang.org/x/net/proxy 包来创建一个简单的 SOCKS5 代理服务作为示例。 步骤 1. 安装 golang.org/x/net/proxy 包 使用以下命令安装 golang.org/x/net 包,该包包含 proxy 子包&am…...

Redis报错:JedisConnectionException: Could not get a resource from the pool
1、问题描述: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 2、简要分析: redis.clients.util.Pool.getResource会从JedisPool实例池中返回一个可用的redis连接。分析源码可知JedisPool 继承了 r…...

【广州华锐互动】Web3D云展编辑器能为展览行业带来哪些便利?
在数字时代中,传统的展览方式正在被全新的技术和工具所颠覆。其中,最具有革新意义的就是Web3D云展编辑器。这种编辑器以其强大的功能和灵活的应用,正在为展览设计带来革命性的变化。 广州华锐互动开发的Web3D云展编辑器是一种专门用于创建、编…...

Vue项目实战之一----实现分类弹框效果
效果图 实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"js/vue.js"></script><!-- 引入样式 --><link rel"stylesheet&qu…...

Vue解析器
解析器本质上是一个状态机。但我们也曾提到,正则表达式其实也是一个状态机。因此在编写 parser 的时候,利用正则表达式能够让我们少写不少代码。本章我们将更多地利用正则表达式来实现 HTML 解析器。另外,一个完善的 HTML 解析器远比想象的要…...

Spring Cloud 版本升级遇坑记:OpenFeignClient与Gateway的恩怨情仇
Spring Cloud 版本升级遇坑记:OpenFeignClient与Gateway的恩怨情仇 近日,在对项目中的 Spring Boot、Spring Cloud 以及 Spring Cloud Alibaba 进行版本升级时,遭遇了一个令人头疼的问题:Spring Cloud Gateway 在运行时一直卡住&a…...
面试:Docker相关问题
文章目录 请解释一下什么是 Docker,以及它在云环境中的应用请简述Docker和LXC的区别什么是Docker Compose?请简述其作用和使用场景在使用Docker时,如何为容器创建一个可访问的网络当一个Docker容器运行异常时,如何通过Docker命令查…...
移动端浏览器 jquery 获取 pdf blob文件流 预览pdf
最近遇到一个需求,一个古早的移动端 juery 项目要求做一个页面,从接口获取 pdf 文件流,然后预览出来 这里使用第三方工具:pdf.js 代码如下: // 引入相关文件<script src"../js/pdf.js" type"text…...

Redis并发问题解决方案
目录 前言 1.分布式锁 1.基于单个节点 2.基于多个节点 3.watch(乐观锁) 2.原子操作 1.单命令操作 2.Lua 脚本(多命令操作) 3.事务 1.执行步骤 2.错误处理 3.崩溃处理 总结 前言 在多个客户端并发访问Redis的时候,虽然Redis是单线程执行指令ÿ…...
读取两个文件夹里不同名的文件,处理映射不对应的文件
解决方案:读取两个文件夹里不同名的文件,处理映射不对应的文件 # -*- coding: utf-8 -*- import ospath1 r/home/ubuntu/data/yoloData/images/train2017 path2 r/home/ubuntu/data/yoloData/labels/train2017def read_all_file_name():file_path ./t…...

SpringCloud原理-OpenFeign篇(四、请求原理)
文章目录 前言正文一、书接上回,从代理对象入手二、ReflectiveFeign.FeignInvocationHandler#invoke()三、SynchronousMethodHandler#invoke(...) 的实现原理3.1 invoke(...)源码3.2 executeAndDecode(...) 执行请求并解码 四、如何更换client 的实现 附录附1&#…...

什么是工业物联网(IOT)?这样的IOT平台你需要吗?——青创智通
物联网(IOT)是指在互联网上为传输和共享数据而嵌入传感器和软件的互联设备的广泛性网络。这允许将从物理对象收集的信息(数据)存储在专用服务器或云中。通过分析这些积累的信息,通过提供最优的设备控制和方法,可以实现一个更安全、更方便的社会。在智能家…...
MTK Pump Express 快速充电原理分析
1 MTK PE 1.1 原理 在讲正文之前,我们先看一个例子。 对于一块电池,我们假设它的容量是6000mAh,并且标称电压是3.7V,换算成Wh(瓦时)为单位的值是22.3Wh(6000mAh*3.7V);普通的充电器输出电压电流是5V2A(10W),…...
leetcode刷题记录——1991. 找到数组的中间位置
找到数组的中间位置 给你一个下标从 0 开始的整数数组 nums ,请你找到 最左边 的中间位置 middleIndex (也就是所有可能中间位置下标最小的一个)。 中间位置 middleIndex 是满足 nums[0] nums[1] … nums[middleIndex-1] nums[middleInd…...

跨域攻击分析和防御(上)
点击星标,即时接收最新推文 跨域攻击 在大型公司或大型跨国企业中都拥有自己的内网,跨国公司都有各个子公司一般以建立域林进行共享资源。根据不同职能区分的部门,从逻辑上以主域和子域进行划分以方便统一管理。在物理层使用防火墙将各个子公…...

GEE:梯度提升树(Gradient Boosting Tree)分类教程(样本制作、特征添加、训练、精度、参数优化、贡献度、统计面积)
作者:CSDN @ _养乐多_ 本文将介绍在Google Earth Engine (GEE)平台上进行梯度提升树(Gradient Boosting Tree)分类的方法和代码,其中包括制作样本点教程(本地、在线和本地在线混合制作样本点,合并样本点等),加入特征变量(各种指数、纹理特征、时间序列特征、物候特征…...

ubuntu22.04 arrch64版在线安装redis
脚本 apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32 echo "deb http://archive.ubuntu.com/ubuntu/ trusty main universe restricted multiverse" >…...

篮桥云课-摆玩具
思维好题 一开始掉进了二分的陷阱,发现看看逐个位置的差,我们要分成k段就是要取消k-1个最大的逐差 然后将剩余的加起来就可以了 因为本体保证是从小到大给出的 这一点保证了答案的正确性,自己没想出来 还是太菜了 #include<bits/stdc.h&…...
【python】python进阶知识点
eval函数用法 函数参数:字符串 # 计算表达式 print(eval("12*3")) # 把字符串当成python程序运行 print(eval("random.random()")) # 字符串转成列表 print(type(eval("[1,2,3,4]"))) # 字符串转成字典 print(type(eval("{name…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...

消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...