在 K8S 上部署 OceanBase 实践
本文作者:美的集团软件工程院 陈子鎏(OceanBase 社区论坛账号:@qchenzi)
目录
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 的方案:
-
为什么使用 Headless Service
- Headless Service(无头服务)通过将
clusterIP: None
设置,使得 DNS 查询可以直接返回后端 Pod 的 IP 地址。
- Headless Service(无头服务)通过将