写点什么

KubeBlocks for Oracle 容器化之路

作者:小猿姐
  • 2025-08-17
    浙江
  • 本文字数:6083 字

    阅读完需:约 20 分钟

KubeBlocks for Oracle 容器化之路

引言

Oracle Data Guard

Oracle Data Guard (简称 DG) 是 Oracle 提供的一种高可用性和灾难恢复解决方案。它提供一整套服务,用于维护、管理和监控一个或多个备用数据库,使 Oracle 数据库能够抵御灾难和数据损坏。DG 将这些备用数据库作为生产数据库的副本进行维护。当生产数据库因计划内或计划外中断而不可用时,DG 可将任一备用数据库切换至生产角色,从而最大限度地减少中断导致的停机时间。

KubeBlocks

KubeBlocks 是一款支持多引擎管理的开源 Operator,通过统一的代码和 API 集成在 K8s 上运行并管理多种数据库引擎,只需编写 KubeBlocks 的 Addon 即可为其添加新引擎。KubeBlocks 的核心是一个 K8s Operator,定义了一组 CR 来抽象各类数据库引擎的通用属性,并利用这些抽象来管理引擎的生命周期及日常运维操作。

容器化现状与挑战

Oracle 官方在容器化方向已经做出了一些努力,提供了从 11g 到 23ai free 版本的镜像,同时还开源了官方的 Oracle Database Operator。然而其在 K8s 上的部署和管理仍然存在一些局限性:


  1. 功能支持不完善:相较于传统物理机环境,Oracle 在容器化环境中支持的功能有限,例如备份恢复、日志管理,配置变更、监控告警等功能支持并不完善。

  2. 运维复杂度高:缺乏统一的运维工具和管理界面,使得运维人员需要在多个工具之间切换,大量运维工作需要手动完成,增加了运维的复杂度。

  3. 版本支持有限:目前官方提供的镜像版本有限,且许多 Feature 都只针对新版本进行开发和测试验证,对仍有大量用户使用的老版本支持不足。


以 Oracle 12c 版本为例,尽管其在传统环境中的部署和运维已经相当成熟,但迁移到容器化环境中仍需克服诸多问题:


  1. 集群拓扑:DG 集群拓扑相对复杂,涉及到 Oracle 和 Observer 多个节点之间的通信和数据同步,这在容器化环境中需要特别注意网络配置和持久化存储。

  2. 多副本管理:DG 集群中通常包含一主多备多个数据库副本,副本间的数据同步,启动顺序,角色切换等各个环节都会影响集群的正常服务,在容器化环境中需要确保这些副本能够正确运行至关重要。

  3. 配置管理:传统环境中,Oracle 会通过感知物理机的资源来调整配置,而在容器化环境中,老版本 Oracle 可能无法感知容器的资源限制,导致配置不合理。

  4. 故障转移:容器化环境中,故障转移的策略和传统环境有所不同,需要确保在容器可能发生故障的各个场景下,能够快速、准确地进行故障转移,保证服务的连续性。


针对上述现状与挑战,本文将依托 KubeBlocks 提供的能力,展示 KubeBlocks 如何解决这些使用上的痛点,并探讨 Oracle 数据库容器化过程中的一些细节,理解 KubeBlocks 以及 Addon 的设计思路和实现机制。

部署与运维示例

首先用一个实际操作示例,本文会展示创建一个 Oracle 12c DG 集群以及一些运维操作的过程,示例集群架构如下:


创建集群

使用 kubectl apply 如下的 Cluster yaml 即可创建一个一主两备加上两个 Observer 节点的集群:


kubectl apply -f - <<EOFapiVersion: apps.kubeblocks.io/v1alpha1kind: Clustermetadata:  name: my-oracle  labels:    helm.sh/chart: oracle-cluster-0.9.0    app.kubernetes.io/name: oracle-cluster    app.kubernetes.io/instance: my-oracle    app.kubernetes.io/version: "12.2.0.1"    app.kubernetes.io/managed-by: Helmspec:  clusterDefinitionRef: oracle  terminationPolicy: Delete  topology: replication  affinity:    podAntiAffinity: Preferred    topologyKeys:      - kubernetes.io/hostname    tenancy: SharedNode  componentSpecs:    - name: oracle      replicas: 3      componentDef: oracle-12c      monitor: true      disableExporter: false      serviceVersion: 12.2.0      resources:        limits:          cpu: "2"          memory: "4Gi"        requests:          cpu: "1"          memory: "1Gi"      volumeClaimTemplates:        - name: data          spec:            accessModes:              - ReadWriteOnce            resources:              requests:                storage: 20Gi        - name: fra          spec:            accessModes:              - ReadWriteOnce            resources:              requests:                storage: 10Gi    - name: observer      replicas: 2      componentDef: oracle-observer-12c      serviceVersion: 12.2.0
resources: limits: cpu: "1" memory: "1Gi" requests: cpu: "0.5" memory: "0.5Gi"EOF
复制代码


可以看到上述 Cluster 中,指定了这个集群的组成部分以及一些相关定义,相信即使是之前没有了解过 KubeBlocks 的读者也能通过 API 字面表述对创建的这个集群的有一个较为直观的印象(后文会对部分关键 API 字段做出详细解析)。在应用后一个完整的 Oracle 12c DG 集群就被创建出来了,查看集群和 pod 的状态:



可以发现,observer 相关的 pod 没有角色,而 oracle 相关的 pod 被设置成 primary 或者 secondary。角色在 KubeBlocks 管理的有状态集群中非常重要,其不仅代表数据库实例之间的复制关系,也代表着 KubeBlocks 对这种关系的一种抽象,这种关系会直接影响 KubeBlocks 在各类运维操作中的行为预期。

配置变更

使用 sqlplus 查看 Oracle 参数open_cursors,发现值为 300



使用 kubectl apply 应用如下 OpsRequest 的 yaml:


kubectl apply -f - <<EOFapiVersion: apps.kubeblocks.io/v1alpha1kind: OpsRequestmetadata:  name: my-oracle-reconfiguring  namespace: defaultspec:  clusterName: my-oracle  force: false  reconfigure:    componentName: oracle    configurations:    - keys:      - key: init.ora        parameters:        - key: open_cursors          value: '301'      name: oracle-config  preConditionDeadlineSeconds: 0  type: ReconfiguringEOF
复制代码


再次查看参数open_cursors,发现值成功改为 301



Fast-Start Failover

Oracle 的 Fast-Start Failover 特性允许在主库故障的情况下自动故障转移到备库,以便快速可靠地恢复业务。通过删除 pod 模拟节点故障,查看 Oracle 备节点是否自动提升为主节点。例如删除当前主节点 my-oracle-oracle-0,几秒后,my-oracle-oracle-1 角色变为 primay,而 my-oracle-oracle-0 以 secondary 的角色重新加入集群。



在这个过程中,KubeBlocks 会持续保持对 Oracle 的角色探测,以保证服务集群状态快速恢复并正常对外服务。


除此之外,KubeBlocks 还为支持的数据库借助 Chaos Mesh 设计多种不同的异常场景,以验证数据库的高可用性,具体可参见:通过 Chaos Mesh 验证 KubeBlocks Addon 可用性的实践

备份恢复

备份是保障数据的关键。在 KubeBlocks 中,通过预先定义的备份方法,只需应用如下 yaml,即可创建一个全量备份:


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


这将会调用 Oracle 的 rman 工具对当前集群进行全量备份,并将得到的备份上传到指定的存储中。


查看备份如下:



得到这个完整的备份后,可基于该备份恢复一个全新的集群,同样只需一个简单的 yaml:


kubectl apply -f - <<EOFapiVersion: apps.kubeblocks.io/v1alpha1kind: OpsRequestmetadata:  name: my-oracle-cluster-restorespec:  clusterName: my-oracle-restored  force: false  restore:    backupName: my-oracle-cluster-backup    backupNamespace: default  type: RestoreEOF
复制代码


查看恢复集群的状态:



这样就可以完成备份恢复操作,同时还可以定义备份的频率,时间等策略。

其他运维操作

接入 KubeBlocks 后,Oracle Addon 还天然支持了很多其他的运维操作。除上述介绍的自动故障转移、配置变更和备份恢复之外,还支持以下运维操作:


  • Observer 水平扩容,可以增加或减少 Observer 节点的数量

  • 垂直扩容

  • 存储扩容

  • 手动主备切换(switchover)

  • 集群重启、停止和删除

  • 小版本升级

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

Oracle Addon 实现

这样一个完整的 Addon 是如何实现的呢?下面将会详细介绍部分 API,帮助理解原理以及设计思路,读者可以结合这部分与运维示例一起阅读,更详细的 API 解读可以直接查看 KubeBlocks 源码中的 API 注释部分。

KubeBlocks 与 Addon 机制

KubeBlocks 通过 Addon 机制,可以方便地扩展其功能,支持多种数据库和中间件。详细文档可以参考:KubeBlocks Addon文档

Oracle Addon

KubeBlocks 提供了一组抽象的 API,用于定义和管理数据库实例。Oracle Addon 则是基于这些 API,为 Oracle DG 集群提供了一套完整的解决方案。

集群管理

Oracle Addon 主要通过 3 个 CR 来定义集群纬度的生命周期管理和运维:


  • ComponentDefinition:简称 CMPD,用于定义数据库集群中一个基本组成部分。在 KubeBlocks 管理的数据库集群中,通常会把集群中的各个基本组件称为 Component。例如在 Oracle DG 集群中,就可以分为 Oracle 和 Observer 两个基本组件,因此需要借助两个 CMPD 来定义这两个组件。

  • ComponentVersion:简称 CMPV,用于定义 Component 的具体版本,例如 Oracle-12c 和 Oracle-19c 等。

  • ClusterDefinition:简称 CD,用于定义数据库集群的拓扑结构和组件之间的关系。比如在 Oracle DG 集群中,单机集群只需要 Oracle 一个组件,而主备集群则需要 Oracle 和 Observer 两个组件,因此需要借助 CD 来定义集群的拓扑结构。


在上述 3 个 CR 中,最重要也是最复杂的 CR 是 CMPD,就像使用乐高积木搭建模型一样,只要有了基本的积木(Component),就可以搭建出各种复杂的模型(Cluster)。


Oracle 的 CMPD 主要包括以下几个部分:


  • roles:定义了 Oracle 的角色,例如主库(Primary)和备库(Secondary)以及角色对应的读写能力。

  • service:定义了 Oracle 的对外提供服务的方式,可以通过 roles 区分只读服务和读写服务,实现读写分离。

  • systemAccounts:定义了 Oracle 的系统账户和初始密码,在 systemAccounts 中,可以自定义密码的生成策略,包括长度,复杂度等,Kubeblocks 会将生成的账号密码存入到 Secret 中,供 Oracle 引用。

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

  • vars: 用于引用一些跟实例相关的动态资源和信息,例如 systemAccounts 中定义的账号ORACLE_SYS_USER,密码ORACLE_SYS_PASSWORD,以及整个集群中 Oracle 所有副本的连接串ALL_ORACLE_FQDN。基于上述 vars,就可以完成 Oracle 的 TNS 以及监听器等相关配置。

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

  • roleProbe:用于探测副本角色

  • postProvision:用于在实例初始化完成后执行一些自定义脚本,例如 Oracle 主备实例都创建完成以后执行 DG Broker 的配置。

  • switchover:用于执行主备切换操作。

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

  • oracle-init-container:完成 Oracle 的数据目录的权限设置

  • oracle:Oracle 服务运行容器

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


除上述显式定义的容器外,KubeBlocks 还会为每个 Pod 注入两个 sidecar 容器,即 lorry:用于执行 roleProbe 等部分 lifecycleActions;config-manager:用于管理配置文件和执行配置变更。


在完成上述核心配置以及一些相关配置后,一个完整的 Oracle 组件就定义完成了。对于 Observer 组件,同样按照上述方式定义即可。在两个组件都定义完成后,就可以通过 CD 完成整个集群的完整拓扑。

DG 配置

在 Oracle Addon 中如何完成 DG 集群中主备节点间的配置呢。其中,节点自身初始化相关的逻辑都在 Oracle 的启动脚本中完成。一开始会先根据集群的规格,配置等信息执行一些通用的初始化操作,例如调整根据实例规格调整内核参数,设置监听,配置 TNS 等。接着会根据节点的角色执行不同的操作: 如果是主节点,会使用 DBCA 工具创建数据库,而如果是备节点,则会使用 RMAN 工具从主节点恢复数据库。


在主备节点都设置完成后,则会依托前文提到的 postProvision 这个 lifecycleAction 来完成主备节点间的 DG Broker 配置,创建并启用 DG Broker 的 Configuration,此时 Oracle 这个 Component 就已经搭建完成了。


最后 KubeBlocks 会根据在 CD 中配置的 Order 创建 Observer 这个 Component,为集群配置 Fast-Start Failover(FSFO),整个集群才算创建完成。


此时集群就具备了高可用性,当主节点发生故障时,Observer 会发现异常并触发 Failover,将备节点提升为主节点,从而保证业务的连续性。

参数配置

KubeBlocks 为了方便对各种数据库的参数进行管理,定义了参数配置相关的 API:


  • 参数模板:定义一个参数模板, 这个模板中可以定义具体的参数数值,也可以根据 Go Template 和 KubeBlocks 提供的内置函数配置参数的计算规则,从而根据实例规格动态计算出最适合的参数值,

  • ConfigConstraint:即参数的约束,参数的约束主要包含三部分:

  • 支持的配置文件格式:例如 yaml, toml, ini 等。

  • 参数的类型和取值范围: KubeBlocks 使用 CUE 文件来描述参数的类型和取值范围。

  • 参数的生效范围:参数可以被划分为动态参数、静态参数和不可变参数。动态参数可以被修改并立即生效,静态参数需要重启实例才能生效,不可变参数一旦设置就不能被修改。


Oracle 主要使用 pfile 和 spfile 来配置数据库参数,为了方便用户进行配置,Oracle Addon 将 pfile 中的部分参数设置到 KubeBlocks 的参数模板中,在实例启动后,会根据这个动态渲染出的 pfile 再生成 spfile。

备份恢复

备份恢复是数据库运维中的重要环节,KubeBlocks 为各种数据库提供了灵活的备份相关 API 以实现不同的备份恢复机制,包括全量备份、增量备份、基于时间点恢复等。Addon 只需实现以下两个 API:


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

  • ActionSet:定义不同数据库使用的具体备份方法,可以在这个 API 中实现实际的备份行为。


以 Oracle Addon 中实现的全量备份为例,定义了一个名为oracle-rman的 ActionSet,该 ActionSet 的 backupType 为Full,表示这是一个全量备份。接着定义了一个名为oracle-backup-policy-template的 BackupPolicyTemplate,该模板指定了使用oracle-rman ActionSet 进行全量备份,并通过 Cron 表达式设置了默认的备份调度周期。借助这些定义,KubeBlocks 能够自动化地执行备份,并将这些备份上传到指定的存储位置,这些目的存储位置可以是本地存储,也可以是云存储服务,如 AWS S3 等。

总结展望

在 K8s 环境中想要稳定高效地运行 Oracle 集群不是一件简单的事,但是 KubeBlocks 为其提供了一条见解且行之有效的路径。本文详细介绍了基于 KubeBlocks 这个 Operator 支持 Oracle Addon 的细节,并介绍了其支持的功能和优势,目前,KubBlocks for Oracle 已经上线 KubeBlocks 企业版,欢迎感兴趣的读者申请体验。


之后我们会持续优化迭代 KubBlocks for Oracle,以支持更多功能并提升稳定性,同时还会增加支持的 Oracle 版本,使 KubBlocks for Oracle 成为更多企业级用户的不二之选。


用户头像

小猿姐

关注

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

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

评论

发布
暂无评论
KubeBlocks for Oracle 容器化之路_小猿姐_InfoQ写作社区