在K8S上部署OceanBase的最佳实践

news2025/1/8 20:16:38

在K8S上部署OceanBase的最佳实践

目录

  • 1. 背景与选型
    • 1.1 为什么选择OB
    • 1.2 为什么选择ob-operator实现OB on K8S
  • 2. 部署实操
    • 2.1 环境准备
    • 2.2 安装 ob-operator
    • 2.3 配置 OB 集群
    • 2.4 配置 OBProxy 集群
    • 2.5 Headless Service 和 CoreDNS 配置
    • 2.6 监控与运维
      • 2.6.1 Promethues部署
      • 2.6.2 Grafana接入
  • 3. 部署中遇到的问题及解决方案
    • 3.1 ob-operator 的调度器问题
    • 3.2 网络配置问题

1. 背景与选型

OB(下称OB)是一款分布式关系型数据库,具有高性能、高可用性和弹性扩展等特点,其企业版已经在公司内部的"去Oracle"项目中进行了落地,并取得了不错的效果。此外,考虑到我们仍有许多业务在关系型数据库上有着需求,同时考虑到我们已经具备MySQL/MariaDB/MongoDB/PostgresSQL在公司内部的K8S集群上进行容器化部署经验,因此我们决定将OceanBase也进行容器化部署。

1.1 为什么选择OB

在选择数据库时,我们从以下几个维度进行了分析:

  • 高可用性:OB是基于Paxos算法的强一致性数据库,具备强大的容灾能力,支持多数据中心部署,同时单点故障并不影响业务连续性。
  • 弹性扩展:OB的租户特性,使得相比MySQL和TiDB等关系型数据库而言,OB提供了更灵活的扩展能力,能够根据业务需求动态调整资源。
  • 成本:OB内核天然自带数据压缩能力,相比MySQL/TiDB具备更低的存储成本,特别是在大规模部署时,能够有效降低硬件成本(实测重复性文本数据下,OB的存储成本仅为MySQL的1/4甚至更低)。
  • 兼容性:OB内核天然兼容MySQL协议,方便现有应用的迁移和集成。

1.2 为什么选择ob-operator实现OB on K8S

在将OB部署到K8S的过程中,我们选择了 ob-operator 作为核心组件。ob-operator 提供了自动化管理 OB集群的能力,能够简化部署、扩展和运维的复杂性。其主要优势包括:

  • 自动化管理:ob-operator 能够自动处理OB集群的生命周期管理,包括创建、更新和删除。
  • 灵活性:支持自定义OServer/OBTenant资源,支持快速扩展集群规模, 支持通过CR文件快速修改参数。
  • 高可用性:通过多实例部署和健康检查机制,确保集群的稳定运行。支持静态IP和OVN网络,确保POD重建后仍然使用原IP,避免了POD重建后IP变化带来的问题。

2 部署实操

对于希望将 OB 接入 K8S 但不知如何下手的用户,ob-operator 提供了一个方便快捷的起点。

2.1 环境准备

在开始之前,请确保已满足以下条件:

  • 有可用的 Kubernetes 集群,至少有 9 个可用 CPU,33 GB 可用内存和 360 GB 的可用存储空间。
  • ob-operator 依赖 cert-manager,请确保已安装 cert-manager。cert-manager 的安装方法如下。
  • 连接 OceanBase 集群时,需已安装 MySQL 客户端或 OBClient。
  • Kubernetes集群需要安装网络插件,例如OVN。2.3.1以上版本 ob-operator 支持OVN网络,并且能够做到pod重建后IP不变,进一步提高了 OB集群 的稳定性。

安装 cert-manager

# 检查是否已安装 cert-manager
kubectl get pod -n cert-manager

# 若未安装,则执行以下命令
wget https://github.com/jetstack/cert-manager/releases/download/v1.5.3/cert-manager.yaml

# 拉取镜像需要科学上网
# 我们使用的K8S的网络插件为OVN,节点需要调度到 OVN 网络的节点上,否则可能无法通过 cert-manager 的 service 访问后端 POD
kubectl apply -f cert-manager.yaml

2.2 安装 ob-operator

安装ob-operator的操作可参考ob-operator部署,如果手动通过CRD部署可以自行从github仓库中下载CRD和Operator的yaml文件,然后通过kubectl apply -f 命令进行安装。

2.3 配置 OB 集群

可参考官方文档进行集群创建

2.4 配置 OBProxy 集群

OBProxy(即odp,OceanBase Database Proxy) 是 OB集群 的代理组件,生产环境上建议使用 OBProxy 对OB集群进行访问。使用 OBProxy 的好处包括:

  • 连接管理:OBProxy 负责管理客户端的连接,维护与后端 OB集群 的会话,减少客户端与数据库之间的连接开销。
  • 负载均衡:OBProxy 能够智能地将客户端请求分发到不同的 OB 节点,优化资源使用,提升系统性能。
  • 高可用性:在后端 OB 节点发生故障时,OBProxy 能够自动剔除故障节点,确保请求的高可用性。
  • 安全性:通过 OBProxy,可以集中管理访问控制和安全策略,增强系统的安全性。

配置步骤

安装 OBProxy:直接应用 YAML 文件进行安装。

obproxy YAML文件地址:obproxy.yaml,但在部署 OBProxy 前需要创建一个用于 OBProxy 与 OB集群 通信的 Secret。

# 创建用于 OBProxy 与 OB集群 通信的 Secret
kubectl create secret -n oceanbase generic proxyro-password --from-literal=password='<proxyro_password>'

# 部署 OBProxy
kubectl apply -f obproxy.yaml

基本内容如下

# 相比官方提供的 obproxy.yaml 文件,增加了 odp-headless 的无头服务配置,主要目的是用于 coreDNS 进行域名解析
apiVersion: v1
kind: Service
metadata:
  name: odp-headless
  namespace: oceanbase
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    app: odp
    name: odp
  ports:
    - name: "sql"
      port: 2883
      targetPort: 2883

---
apiVersion: v1
kind: Service
metadata:
  name: odp
  namespace: oceanbase
spec:
  type: ClusterIP
  selector:
    app: odp
    name: odp
  ports:
    - name: "sql"
      port: 2883
      targetPort: 2883
    - name: "prometheus"
      port: 2884
      targetPort: 2884

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: odp            # 生产环境下,不建议使用 odp 作为 Deployment 名称,建议使用 odp-${obcluster_name} 作为 Deployment 名称
  namespace: oceanbase
spec:
  selector:
    matchLabels:
      app: odp
      name: odp        # 生产环境下,不建议使用 odp 作为 Deployment 名称,建议使用 odp-${obcluster_name} 作为 Deployment 名称
  replicas: 3
  template:
    metadata:
      labels:
        app: odp
        name: odp
    spec:
      containers:
        - name: obproxy
          image: oceanbase/obproxy-ce:4.2.1.0-11
          ports:
            - containerPort: 2883
              name: "sql"
            - containerPort: 2884
              name: "prometheus"
          env:
            - name: APP_NAME
              value: helloworld # 用于 OBProxy 的名称
            - name: OB_CLUSTER
              value: obcluster # 此处填写OB集群的名称,其来源于 OB 部署YAML文件中的 clusterName 值
            - name: RS_LIST
              value: '******' # 格式为 ${OBServer1 POD_IP}:2881;${OBServer2 POD_IP}:2881;${OBServer3 POD_IP}:2881,需要根据实际OBSevrer PODIP来进行替换。
            - name: PROXYRO_PASSWORD
              valueFrom: 
                secretKeyRef:
                  name: proxyro-password # 用于 OBProxy 与 OB集群 通信的 Secret
                  key: password
          resources:
            limits:
              memory: 2Gi
              cpu: "1"
            requests: 
              memory: 200Mi
              cpu: 200m

部署完成后,如下图所示:

在这里插入图片描述

通过 OBProxy 访问OB集群

此时,可以通过OBProxy的Service提供OB数据库的访问入口,如下(obmysql是我提前创建好的租户,testdb是提前在obmysql下创建的用户):

当然,在实际的生产中,我们采用的是域名访问的方式,而不是通过IP地址访问,因此需要进行域名重写,可看下一小节。

2.5 Headless Service 和 CoreDNS 配置

在我们的实践中,为了更好地管理 OBProxy 的访问,我们采用了 Headless Service 配合 CoreDNS 的方案:

  1. 为什么使用 Headless Service

    • Headless Service(无头服务)通过将 clusterIP: None 设置,使得 DNS 查询可以直接返回后端 Pod 的 IP 地址。
    • 这种方式避免了普通 Service 的 kube-proxy 转发,减少了网络跳转,提升了访问性能。
  2. CoreDNS 域名重写配置

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
    data:
      Corefile: |
         .:3053 {
           errors
           log
           health {
             lameduck 10s
           }
           rewrite stop {
             name regex ob-(.*).rds.com odp-headless-ob-{1}.oceanbase.svc.cluster.local
             answer name odp-headless-ob-(.*).oceanbase.svc.cluster.local ob-{1}.rds.com
           }
    
           kubernetes cluster.local in-addr.arpa ip6.arpa {
             pods insecure
             fallthrough in-addr.arpa ip6.arpa
           }
           prometheus :9153
           ready :8153
           loop
           reload
           cache 10
           loadbalance
         }
    
  3. 域名重写的优势

    • 简化访问:用户可以通过简单的域名格式(如 ob-test.rds.com)访问数据库,无需关心内部复杂的 K8S 域名。
    • 统一管理:通过规范的域名格式(ob-*.rds.com),便于管理和维护多个 OB 集群。
    • 透明代理:CoreDNS 自动完成域名转换,对应用层完全透明。
    • 灵活扩展:可以根据需求轻松添加新的 OB 集群,只需遵循命名规范即可。
  4. 访问流程

    • 应用通过 ob-{clustername}.rds.com 访问数据库
    • CoreDNS 将请求域名重写为 odp-headless-ob-{clustername}.oceanbase.svc.cluster.local
    • Headless Service 返回对应 OBProxy Pod 的 IP
    • CoreDNS 在响应中将域名重写回 ob-{clustername}.rds.com
    • 应用获得 Pod IP 并建立连接
  5. CoreDNS 主机模式部署

    • 将 CoreDNS 部署在主机网络模式 (即 hostNetwork: true),使 CoreDNS POD与主机共享网络。
    • 这样用,在其余K8S集群中的机器上,将 /etc/resolv.conf 配置为 CoreDNS 服务器ip后,即可通过 CoreDNS 进行域名解析。
    • 这种配置方式使得外部机器能够方便地通过 CoreDNS 进行域名解析,适合需要跨集群访问的场景。
  6. 如图所示

    • 直接通过域名即可访问,而不用关心 obproxy 的service ip,进一步加强了集群的高可用能力

2.6 监控与运维

2.6.1 Promethues部署
  • 应用ob-operator中的promethues.yaml文件进行部署,文件链接:promethues.yaml

执行以下命令部署

kubectl apply -f prometheus.yaml

执行以下命令检查是否部署完成

kubectl get pod -n oceanbase  | grep prometheus

执行以下命令获取SVC

kubectl get svc -n oceanbase  | grep prometheus

如下

root@(datamars)mhpl74334-10.20.248.59 ~$ kubectl get svc -n oceanbase  | grep pro
svc-prometheus    NodePort    12.80.144.38   <none>        9090:30090/TCP      7d15h
2.6.2 Grafana接入
  • 可以应用ob-operator中的grafana.yaml文件进行部署,文件链接:grafana.yaml
  • 也可以通过grafana的配置页面,添加prometheus数据源,然后通过prometheus的SVC地址进行接入。

因为我们本地已经有grafana,所以这里我们通过grafana的配置页面,添加prometheus数据源,然后通过prometheus的SVC地址进行接入。

2.6.2.1 配置Prometheus数据源
  1. 在Grafana左侧导航栏,单击 Configuration 按钮,然后单击 Add data source 按钮。
  2. Add data source 页面,选择 Prometheus 作为数据源类型。
  3. Prometheus 页面,填写 Nameob-prometheusURLhttp://12.80.144.38:9090(即上面的promethues对应的svc ip),然后单击 Save & Test 按钮。

2.6.2.2 配置Grafana Dashboard
  1. 新建一个名为OceanBase的文件夹

  1. 进入该文件夹,接着导入文件链接:grafana.yaml 中的grafana-dashboards-ob部分的json配置

  1. 监控展示如图

3. 部署中遇到的问题及解决方案

3.1 ob-operator 的调度器默认为K8S原生的 default-scheduler,而在我们环境中需要使用自定义的调度器

解决方案

  • 在 OBCluster的CRD中新增了 schedulerName 字段,用于指定调度器,具体修改可以参考 MR: Support Custom SchedulerName, 用法如下:
apiVersion: oceanbase.oceanbase.com/v1alpha1
kind: OBCluster
metadata:
  name: test
  namespace: oceanbase
spec:
  observer:
    image: oceanbase/oceanbase-cloud-native:4.2.3.1-101000032024061316
    podFields:
      schedulerName: custom-scheduler # 指定调度器为 custom-scheduler
    resource:
      cpu: 8
      memory: 16Gi
    ...

3.2 网络配置问题

问题描述:在使用 OVN 网络插件时,发现 Pod IP 在重启后发生变化,导致OBProxy无法正常访问OB集群。

解决方案
(1)使用ob-operator的service模式,即为每个OBServer Pod创建一个Service,通过service来做静态IP的绑定,从而解决IP变化的问题,用法如下:

apiVersion: oceanbase.oceanbase.com/v1alpha1
kind: OBCluster
metadata:
  name: test
  namespace: oceanbase
  annotations:
    "oceanbase.oceanbase.com/mode": "service" # 指定为service模式
spec:
  observer:
    image: oceanbase/oceanbase-cloud-native:4.2.3.1-101000032024061316
    podFields:
      schedulerName: custom-scheduler
    resource:
      cpu: 8
      memory: 16Gi
    ...

但是链路上多一节service做静态IP的绑定,会增加网络的复杂度,而从生产角度和高可用shang因此我们采用了下面的方案。

(2)ob-operator更新到2.3.1,该版本支持OVN网络插件,并且能够做到Pod重建后IP不变。

(3)但仍存在潜在的IP冲突问题,即当一个 OB Pod 正在重建过程中时,如果此时有其他新的 Pod 被创建,这些新 Pod 可能会占用到正在重建的 OB Pod 原本使用的 IP 地址。这会导致该 OB Pod 重建完成后无法使用其原有的 IP 地址。

为了解决这个问题,我们采用了 OVN 的子网隔离方案:

  • 创建专用子网:为 OceanBase 的命名空间创建了一个专用的 subnet,将其与其他业务的 Pod 网络进行隔离。
  • 配置方式
    apiVersion: kubeovn.io/v1
    kind: Subnet
    metadata:
      name: ob-subnet
    spec:
      protocol: IPv4
      cidrBlock: 10.16.0.0/16  # 为 OB 集群预留足够大的网段
      namespaces:
        - oceanbase  # 将子网与 oceanbase 命名空间绑定
      gateway: 10.16.0.1
      excludeIps:
        - 10.16.0.1..10.16.0.10  # 排除网关等保留地址
    

这种配置的优势:

  • 网络隔离:OB 集群的 Pod 使用独立的 IP 地址段,避免与其他业务 Pod 发生 IP 冲突
  • 地址管理:可以更好地规划和管理 IP 地址资源
  • 安全性:通过网络隔离提升了系统安全性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【设计模式-1】软件设计模式概述

1. 软件设计模式的产生背景 “设计模式”这个术语最初并不是出现在软件设计中&#xff0c;而是被用于建筑领域的设计中。 1977 年&#xff0c;美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫亚历山大&#xff08;Christopher Alexander&#xff09;在…

Nginx——反向代理(三/五)

目录 1.Nginx 反向代理1.1.Nginx 反向代理概述1.2.Nginx 反向代理的配置语法1.2.1.proxy_pass1.2.2.proxy_set_header1.2.3.proxy_redirect 1.3.Nginx 反向代理实战1.4.Nginx 的安全控制1.4.1.如何使用 SSL 对流量进行加密1.4.2.Nginx 添加 SSL 的支持1.4.3.Nginx 的 SSL 相关指…

win10 VS2019上libtorch库配置过程

win10 VS2019上libtorch库配置过程 0 引言1 获取libtorch2 在VS上配置使用libtorch库3 结语 0 引言 &#x1f4bb;&#x1f4bb;AI一下&#x1f4bb;&#x1f4bb;   libtorch库是一个用于深度学习的C库&#xff0c;是PyTorch的官方C前端。它提供了用于构建和训练深度学习模…

Windows 环境配置 HTTPS 服务实战

一、 环境准备 win10以上操作系统安装 Certbot申请阿里云\腾讯云域名安装 nginx 1.3以上版本 二、Certbot 安装及 SSL 证书生成 Certbot 是一个免费、开源工具&#xff0c;用于自动化在Web服务器上获取和更新SSL/TLS证书。它可以通过Let’s Encrypt服务获取免费的SSL/TLS证书…

【C++数据结构——图】最小生成树(头歌实践教学平台习题) 【合集】

目录&#x1f60b; 任务描述 相关知识 带权无向图 建立邻接矩阵 Prim算法 1. 算法基本概念 2. 算法背景与目标 3. 算法具体步骤 4. 算法结束条件与结果 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;编写一个程序求图的最小生成树。 相关知识 为了完成…

11.认识异常

本节目标 1.异常概念与体系结构 2.异常的处理方式 3.异常的处理流程 4.自定义异常类 1.异常的概念与体系结构 1.1异常的概念 在Java中,将程序执行过程中发生的不正常行为称为异常,比如: 1.算术异常 System.out.println(10/0);//执行结果 Exception in thread "mai…

基于海思soc的智能产品开发(camera sensor的两种接口)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于嵌入式开发设备来说&#xff0c;除了图像显示&#xff0c;图像输入也是很重要的一部分。说到图像输入&#xff0c;就不得不提到camera。目前ca…

vulnhub靶场-potato(至获取shell)

arp-scan -l 扫描IP 使用御剑端口扫描扫描端口&#xff0c;扫到了80和7120两个端口&#xff0c;其中7120为ssh端口 使用dirb http://192.168.171.134 扫描目录 发现info.php 访问为phpinfo界面 访问192.168.171.134为一个大土豆&#xff0c;没什么用 所以我们从ssh入手 盲…

Flutter:邀请海报,Widget转图片,保存相册

记录下&#xff0c;把页面红色区域内的内容&#xff0c;转成图片后保存到相册的功能 依赖 # 生成二维码 qr_flutter: ^4.1.0 # 保存图片 image_gallery_saver_plus: ^3.0.5view import package:demo/common/index.dart; import package:ducafe_ui_core/ducafe_ui_core.dart; i…

Milvus×合邦电力:向量数据库如何提升15%电价预测精度

01. 全球能源市场化改革下的合邦电力 在全球能源转型和市场化改革的大背景下&#xff0c;电力交易市场正逐渐成为优化资源配置、提升系统效率的关键平台。电力交易通过市场化手段&#xff0c;促进了电力资源的有效分配&#xff0c;为电力行业的可持续发展提供了动力。 合邦电力…

网络层协议之IP数据包层分片随笔

1.全篇内容均在图中&#xff0c;如何分片以及分片举例细节拆解&#xff0c;见下图: 1.1分片公式&#xff1a; 上述公式中有关/8 再*8目的是为了使用8字节对齐&#xff0c;从而使的分片数据包均为8字节整数倍&#xff01; 1.2.ip层数据包分片计算&图解

TDengine + MQTT :车联网时序数据库如何高效接入

现代新能源汽车&#xff0c;作为一种内部系统极为复杂的交通工具&#xff0c;配备了大量传感器、导航设备、应用软件&#xff0c;这些传感器产生的数据都需要上报到车联网平台当中。对于这些车辆的状态数据&#xff08;如车速、发动机转速等&#xff09;、位置数据&#xff08;…

jenkins入门3 --执行一个小demo

1、新建视图 视图可以理解为是item的集合&#xff0c;这样可以将item分类。新建视频可以选择加入已有的item 2、新建item 1)输入任务名称、选择一个类型&#xff0c;常用的是第一个freestyle project 2&#xff09;进行item相关配置&#xff0c;general 设置项目名字,描述,参数…

【Vue.js】监听器功能(EventListener)的实际应用【合集】

目录 &#x1f914;在实际开发过程中&#xff0c;我遇到了一个颇为棘手的小问题 &#x1f60b;解决这个小问题 问题出现的原因剖析 解决方法阐述 问题成功解决&#xff01;​ &#x1f4d6;相关知识总结 基本概念 使用方法 实际应用场景 &#x1f914;在实际开发过程中…

【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 一、线性表的基本概念 二、初始化线性表 三、销毁线性表 四、判定是否为空表 五、求线性表的长度 六、输出线性表 七、求线性表中某个数据元素值 八、按元素值查找 九、插入数据元素 十、删除数据元素 测试说明 通关代码 测…

【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 一、根据键盘输入的一组有序数据建立顺序表 二、顺序表的输出 三、二分查找算法 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;实现二分查找的算法。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; …

20250103在Ubuntu20.04.5的Android Studio 2024.2.1.12中跑通Hello World

20250103在Ubuntu20.04.5的Android Studio 2024.2.1.12中跑通Hello World 2025/1/3 14:06 百度&#xff1a;android studio helloworld android studio hello world kotlin helloword kotlin 串口 no run configurations added android studio no run configurations added 1、…

卸载干净 IDEA(图文讲解)

目录 1、卸载 IDEA 程序 2、注册表清理 3、残留清理 1、卸载 IDEA 程序 点击屏幕左下角 Windows 图标 -> 设置-控制面板->intellij idea 勾选第一栏 Delete IntelliJ IDEA 2022.2 caches and local history&#xff0c;表示同时删除 IDEA 本地缓存以及历史。 Delete I…

【HarmonyOS】鸿蒙应用实现屏幕录制详解和源码

【HarmonyOS】鸿蒙应用实现屏幕录制详解和源码 一、前言 官方文档关于屏幕录制的API和示例介绍获取简单和突兀。使用起来会让上手程度变高。所以特意开篇文章&#xff0c;讲解屏幕录制的使用。官方文档参见&#xff1a;使用AVScreenCaptureRecorder录屏写文件(ArkTS) 二、方…

我的创作纪念日——《惊变128天》

我的创作纪念日——《惊变128天》 机缘收获日常成就憧憬 机缘 时光飞逝&#xff0c;转眼间&#xff0c;我已在这条创作之路上走过了 128 天。回顾起 2024 年 8 月 29 日&#xff0c;我满怀忐忑与期待&#xff0c;撰写了第一篇技术博客《讲解LeetCode第1题&#xff1a;两数之和…