写点什么

KubeBlocks for MSSQL Always On AG 揭秘

作者:小猿姐
  • 2025-09-05
    浙江
  • 本文字数:5459 字

    阅读完需:约 18 分钟

KubeBlocks for MSSQL Always On AG 揭秘

背景

MSSQL 与 Alway On AG

Microsoft SQL Server(MSSQL)是微软公司开发的企业级关系型数据库管理系统,自 1989 年发布首个版本 SQL Server 1.0 以来,已有超过 30 年的发展历史。根据 DB-Engines 数据库引擎排行榜显示,MSSQL 近十年来始终稳居全球前三位,仅次于 Oracle 和 MySQL,是业界公认的主流数据库产品之一。



在企业级生产环境中,数据库的高可用性是业务连续性的重要保障。MSSQL 的 Always On Availability Group(可用性组,简称 AG)技术通过多副本同步复制和自动故障转移,为企业提供了成熟的高可用解决方案,能够有效防止数据丢失,最大化减少服务中断时间。因此,Always On AG 已成为企业级 MSSQL 部署的标准配置,是关键业务系统不可或缺的数据保障技术。

容器化挑战

随着容器化技术的快速发展,越来越多的企业开始将关键业务系统迁移到容器环境中。MSSQL 从 2017 版本开始正式支持 Linux 平台,这为其容器化部署奠定了基础。然而,如何将成熟的 Always On AG 高可用架构迁移至 K8s 环境,成为企业面临的重大技术挑战。

官方容器化方案的局限性

微软官方虽然提供了在容器Kubernetes 中运行 MSSQL 的部署指导,但其基于 StatefulSet 的部署方案无法胜任对可用性和业务连续性要求较高的企业级场景:


  • 单副本架构限制:仅支持单实例部署,无法实现真正的数据库级高可用

  • 可用性差:可用性主要依赖持久化存储和 Pod 重建机制,故障恢复时间通常需要数分钟,RTO 过长,难以满足关键业务需求

  • 运维复杂度高:缺乏统一的管理界面和自动化运维能力,备份、监控、性能调优等日常运维工作需要大量手工操作

Always On AG 的容器化挑战

虽然 Always On AG 技术在传统环境中已经相当成熟,但将其迁移到容器化的 K8s 环境中却面临着技术层面的根本性挑战:


  • 高可用组件缺失:传统 Always On AG 依赖于操作系统级别的集群组件(WSFC 或 Pacemaker)进行自动故障转移,实现数据库集群高可用,但容器环境的短暂、可替换特性使得这些组件无法满足容器环境的高可用需求。

  • 网络与服务发现复杂:Pod IP 地址动态变化导致 AG 端点配置困难;跨 Pod 通信证书管理和安全通信配置繁琐。

  • 多副本管理复杂:AG 中通常包含多个副本,需要考虑副本的启动顺序、角色分配、配置参数同步、健康状态监控等,任何环节出错都可能导致整个集群服务异常。


在这种背景下,KubeBlocks 为 MSSQL Always On AG 容器化提供了解决思路。本文将介绍如何基于开源 KubeBlocks 实现 MSSQL 容器化,包括 Addon 接入机制、MSSQL Always On AG 的 Addon 实现,最后展示实际部署和运维效果。

KubeBlocks 与 Addon

KubeBlocks 作为开源的、专为有状态应用而设计的 K8s Operator,通过其开放的架构设计,使得开发者可以基于统一的抽象层和自动化运维能力来实现 MSSQL 容器化,KubeBlocks 有如下特点:


  • 开源开放:基于 AGPL 协议的开源项目

  • 云原生设计:深度融合 K8s 生态,充分利用容器编排的原生优势

  • 统一管理:提供一致的数据库运维体验,简化多数据库环境的管理复杂度

  • 可扩展架构:插件化设计,支持开发者自定义接入各类数据库


KubeBlocks 的插件化设计,为我们接入 MSSQL 提供了一组接口,只要实现这些接口,KubeBlocks 就可以在 K8s 上运行和管理 MSSQL 数据库集群。


所谓接口,就像乐高积木的连接点一样:不管是建房子的方块、造车的轮子还是拼机器人的手臂,只要你的凸点和凹槽符合乐高的标准规格,就能与其他积木完美连接,构建出复杂的作品。同样地,KubeBlocks 定义了一套标准的"数据库积木"接口规格,任何数据库只要按照这个规格来"设计连接点",就能无缝融入 KubeBlocks 平台,与其他组件协同工作。


在 KubeBlocks 中,这些接口对应一组 API,也就是一组 K8s CRD 定义,如下图中的 ClusterDefinitionComponentVersionComponentDefinition,只要定义好对应的 CR,即可接入一款数据库引擎,我们也将其称之为 Addon(插件)。具体接口的用途和说明会在下文接入 MSSQL 的具体实现中进行介绍。



MSSQL Addon 实现

本节介绍我们是如何实现 MSSQL 集群管理,高可用,参数配置,备份恢复等功能的。

集群管理

实现如下接口,即可在 KubeBlocks 中实现 MSSQL 集群的基本生命周期管理和运维:


  • ClusterDefinition:定义数据库集群拓扑的接口,比如是集群还是单机,每种拓扑结构包含哪些组件。

  • ComponentDefinition:定义组件的接口,所谓组件,是数据库集群的组成部分,一个集群通常由一个或多个组件构成。如果把数据库集群比作一辆乐高汽车,组件则表示不同的功能部件,比如车灯,车轮,车身等。

  • ComponentVersion:定义组件版本的接口,每个组件通常有很多版本,我们支持哪些大版本,哪些小版本,版本对应的镜像是什么,版本间兼容性如何,都在该接口中定义。


这里主要介绍 ComponentDefinition 的实现。注意,本文介绍的 MSSQL Addon 基于 KubeBlocks 0.9 的 API 实现。


MSSQL 的 ComponentDefinition 主要包括如下几部分:


  • roles:定义 AG 集群中的副本角色,有两种,primarysecondary

  • services:定义两个对外提供服务的 Service,一个指向主副本,提供读写服务,一个指向备副本,提供只读服务。

  • systemAccounts:定义内置系统账号 sakbadmin,及其密码生成策略,KubeBlocks 会将对应账号和密码信息生成到对应 secret 中。

  • scripts:指定脚本的 ConfigMap,KubeBlocks 会将其挂载到容器中的指定目录。

  • vars:定义一些变量,如 MSSQL_SA_USER 表示数据库集群系统管理员账号名称,MSSQL_SERVER_PORT 表示服务端口号等,这些变量最终会以环境变量的形式渲染到 Pod 中。

  • lifecycleActions:定义一些生命周期管理相关的动作,MSSQL 实现了两个 Action:

  • roleProbe:用于探测副本角色

  • memberLeave:用于在集群缩容时调整副本间的拓扑关系

  • runtime:定义容器运行时相关的配置,包括三个容器:

  • init-syncer:拷贝 Syncer 等必要的工具

  • mssql:MSSQL 服务运行容器

  • exporter:用于采集数据库的监控指标


至此,一个基本的 MSSQL 组件就定义完成了。

Always On AG 配置

细心的读者可能不禁要问,那组件是如何启动 MSSQL 服务的呢,组件的多个副本又是如何构成 AG 集群的呢?前文提到的 Always On AG 容器化的难题又是如何克服的呢?


关键的细节和复杂性都在 mssql 容器的启动脚本中。容器启动时,会先启动 MSSQL 进程,然后根据是否已经做过初始化执行不同的流程。初始化时会选择序号最小的 Pod 作为主节点,其余 Pod 作为备节点。


主节点(Primary)的初始化流程包括以下步骤:


  1. 等待所有副本的 MSSQL 进程启动

  2. 创建证书,该证书将会用于 TDE 加密

  3. 创建 Endpoint

  4. 创建包含所有副本的 AG,副本的连接地址使用 Pod 的 FQDN

  5. 将 AG 的操作权限授予管理账号 kbadmin

  6. 开启并配置服务级别和数据库级别审计

  7. 创建用于同步账号和数据库的触发器和存储过程


备节点的初始化流程类似,区别是不会创建 AG,而是会加入已经由主节点创建好的 AG 中。所有节点都初始化完成并加入同一个 AG 后,就构成了一个 AG 集群。

高可用

然而,AG 集群本身不具备自动故障转移能力,需要依赖外部组件。在 Linux 环境中,传统的自动故障转移通常依赖 Pacemaker 和 Corosync 来实现,但这些组件在容器化环境中配置繁琐,且不完全适配容器环境,导致整体高可用系统维护成本高,稳定性难以保证。为此,我们自主研发了一套轻量级、多数据库引擎支持、面向云原生环境的分布式高可用组件——Syncer。关于 KubeBlocks for MSSQL 的高可用设计、Syncer 具体实现以及如何借助 Chaos Mesh 提升集群可用性等内容,可以参考 KubeBlocks for MSSQL 高可用实现

参数配置

数据库引擎通常都有很多参数和配置,有些需要在初始化时指定,有些需要在配置文件中指定,有些参数修改需要重启才能生效,有些可以动态修改。为了方便接入不同类型,不同格式的数据库参数配置,KubeBlocks 定义了参数配置相关的接口:


  • 参数模板:定义一个参数模板,KubeBlocks 会根据集群资源,自适应地将其渲染为配置文件

  • ConfigConstraint:配置约束,定义配置文件的格式,动态参数和静态参数,以及参数的取值范围、类型等信息


在 MSSQL Addon 中,根据 MSSQL 启动需求,定义参数模板,渲染mssql.conf配置文件,MSSQL 启动时会使用该配置文件。同时定义 ConfigConstraint,指定其支持的配置文件格式为 ini,以及动态参数、静态参数和不可变参数。

备份恢复

备份对于数据库系统的重要性不言而喻,一旦遭遇意外,如误删库表,硬件故障,自然灾害等,都可能导致数据丢失,服务中断,影响在线业务。通过定期备份,并将备份数据保存至不同区域、不同存储介质,可以在极端情况下,通过备份恢复数据。


KubeBlocks 定义了两个接口来实现数据库系统的备份:


  • BackupPolicyTemplate:备份策略模板,用于定义指定组件的备份策略,创建数据库集群时会根据该模板生成集群的备份策略。包括备份方法,默认备份调度周期,默认的备份目标(即,从主节点备份还是备节点备份)。

  • ActionSet:定义具体备份方法对应的实际行为以及备份类型等信息。


我们为 MSSQL Addon 实现了三种备份方法:


  • 全量备份:调用 MSSQL 命令备份所有 database

  • 差异备份:差异备份仅备份自上次全量备份以来的修改,较全量备份效率更高,同样调用 MSSQL 差异备份命令来实现

  • 持续日志备份:定期调用 BACKUP LOG命令上传 database 日志文件,以实现基于时间点的恢复


借助 KubeBlocks 对备份目的地的抽象,即 BackupRepo,可以轻松将以上备份上传至主流云厂商提供的对象存储,包括阿里云,华为云,腾讯云,AWS,谷歌云,微软 Azure,Oracle 云等的对象存储服务,对于线下部署的场景,也支持自行部署的 MinIO,XSKY,NAS 等存储服务。

部署与运维实践

现在,让我们实际部署一个 MSSQL Always On AG 集群,并执行一些运维变更操作。(注意:MSSQL Addon 目前仅在企业版中提供,尚未开源)

部署集群

通过 kubectl 命令 apply 一个 cluster YAML 文件来创建一个三副本的 MSSQL 集群。


kubectl apply -f - <<EOFapiVersion: apps.kubeblocks.io/v1alpha1kind: Clustermetadata:  name: my-mssql  annotations:    kubeblocks.io/extra-env: '{"MSSQL_PID":"Developer","MSSQL_COLLATION":"SQL_Latin1_General_CP1_CI_AS"}'spec:  terminationPolicy: Delete    clusterDefinitionRef: mssql  componentSpecs:    - name: mssql      serviceVersion: 2022.19.0      replicas: 3            resources:        limits:          cpu: "1"          memory: "2Gi"        requests:          cpu: "1"          memory: "2Gi"      volumeClaimTemplates:        - name: data          spec:            accessModes:              - ReadWriteOnce            resources:              requests:                storage: 20GiEOF
复制代码


查看集群和 pod 的状态:



自动故障转移

通过删除 pod 模拟节点故障,查看角色是否自动切换。如下,删除当前主节点 my-mssql-mssql-0,几秒后,my-mssql-mssql-1 角色变为 primay。



随后,my-mssql-mssql-0 节点的角色变更为 secondary,作为新的备节点加入集群。



垂直扩容

执行如下 OpsRequest 将 cpu/memory 从 1C2G 扩容到 2C4G。


kubectl apply -f - <<EOFapiVersion: apps.kubeblocks.io/v1alpha1kind: OpsRequestmetadata:  name: ops-vertical-scalingspec:  clusterName: my-mssql  type: VerticalScaling  verticalScaling:  - componentName: mssql    requests:      memory: "4Gi"      cpu: "2"    limits:      memory: "4Gi"      cpu: "2"EOF
复制代码


查看集群状态和 Pod 状态,等待变更完成,并查看 Pod 资源。



备份恢复

执行如下命令,创建一个全量备份:


kubectl apply -f - <<EOFapiVersion: dataprotection.kubeblocks.io/v1alpha1kind: Backupmetadata:  name: mssql-cluster-backupspec:  backupMethod: full  backupPolicyName: my-mssql-mssql-backup-policy  deletionPolicy: DeleteEOF
复制代码


查看备份如下:



基于该备份恢复一个全新的集群:


kubectl apply -f - <<EOFapiVersion: apps.kubeblocks.io/v1alpha1kind: OpsRequestmetadata:  name: mssql-cluster-restore-opsspec:  clusterName: my-mssql-restored  force: false  restore:    backupName: mssql-cluster-backup    backupNamespace: demo  type: RestoreEOFopsrequest.apps.kubeblocks.io/mssql-cluster-restore-ops created
复制代码


查看恢复集群的状态:



其他运维操作

以 Addon 形式接入 KubeBlocks 后,天然支持了很多集群运维操作。除上述介绍的自动故障转移、垂直扩容和备份恢复之外,还支持以下运维操作:


  • 水平扩容,增加集群副本数

  • 存储扩容

  • 手动主备切换

  • 集群重启、停止和删除

  • 参数配置,修改集群参数

  • 小版本升级

  • 增量备份

  • 基于时间点的恢复

  • 监控(配置 Prometheus exporter 采集指标)

总结展望

在云原生环境中运行 MSSQL 面临诸多挑战,KubeBlocks 作为开源的、专为有状态应用设计的 K8s Operator,为数据库容器化提供了强有力的支持。本文详细介绍了如何基于开源 KubeBlocks 实现支持 Always On AG 的 MSSQL Addon,并展示了其在容器化部署、高可用、自动化运维等方面的优势。目前,KubBlocks for MSSQL 已经上线 KubeBlocks 企业版, 欢迎感兴趣的读者申请体验。


尽管 KubeBlocks 已经解决了 MSSQL Always On AG 容器化的诸多关键问题,但在企业级应用场景中仍面临一些挑战,如现有工具生态集成、AD 域集成等,我们也正在积极解决和完善。相信通过持续解决这些企业级场景的实际痛点,容器化 MSSQL 将真正成为企业数据管理的可信选择。


用户头像

小猿姐

关注

还未添加个人签名 2022-08-11 加入

每个开发者都想知道的云原生和数据库技术

评论

发布
暂无评论
KubeBlocks for MSSQL Always On AG 揭秘_云原生_小猿姐_InfoQ写作社区