在K8S上部署OceanBase的最佳实践
在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
部署完成后,如下图所示:
https://i-blog.csdnimg.cn/direct/36cf3f603b8e4dab92711ddb8b5fe6a2.png
通过 OBProxy 访问OB集群:
此时,可以通过OBProxy的Service提供OB数据库的访问入口,如下(obmysql是我提前创建好的租户,testdb是提前在obmysql下创建的用户):
https://i-blog.csdnimg.cn/direct/1a295722a50e496e8363e64883dd24db.png
当然,在实际的生产中,我们接纳的是域名访问的方式,而不是通过IP所在访问,因此需要进行域名重写,可看下一小节。
2.5 Headless Service 和 CoreDNS 配置
在我们的实践中,为了更好地管理 OBProxy 的访问,我们接纳了 Headless Service 配合 CoreDNS 的方案:
[*] 为什么使用 Headless Service
[*]Headless Service(无头服务)通过将 clusterIP: None 设置,使得 DNS 查询可以直接返回后端 Pod 的 IP 所在。
[*]这种方式制止了普通 Service 的 kube-proxy 转发,淘汰了网络跳转,提拔了访问性能。
[*] 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
}
[*] 域名重写的优势
[*]简化访问:用户可以通过简朴的域名格式(如 ob-test.rds.com)访问数据库,无需关心内部复杂的 K8S 域名。
[*]同一管理:通过规范的域名格式(ob-*.rds.com),便于管理和维护多个 OB 集群。
[*]透明代理:CoreDNS 自动完成域名转换,对应用层完全透明。
[*]机动扩展:可以根据需求轻松添加新的 OB 集群,只需遵循命名规范即可。
[*] 访问流程
[*]应用通过 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 并建立连接
[*] CoreDNS 主机模式部署
[*]将 CoreDNS 部署在主机网络模式 (即 hostNetwork: true),使 CoreDNS POD与主机共享网络。
[*]如许用,在别的K8S集群中的呆板上,将 /etc/resolv.conf 配置为 CoreDNS 服务器ip后,即可通过 CoreDNS 进行域名分析。
[*]这种配置方式使得外部呆板可以或许方便地通过 CoreDNS 进行域名分析,得当需要跨集群访问的场景。
[*] 如图所示:
[*]直接通过域名即可访问,而不消关心 obproxy 的service ip,进一步增强了集群的高可用能力
https://i-blog.csdnimg.cn/direct/9ff92ff74b6c4ccdaf8b537587af4b7b.png
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数据源
[*]在Grafana左侧导航栏,单击 Configuration 按钮,然后单击 Add data source 按钮。
[*]在 Add data source 页面,选择 Prometheus 作为数据源类型。
[*]在 Prometheus 页面,填写 Name 为 ob-prometheus,URL 为 http://12.80.144.38:9090(即上面的promethues对应的svc ip),然后单击 Save & Test 按钮。
https://i-blog.csdnimg.cn/direct/69f4f047d1c94b05aca5478ea30a3eb4.png
2.6.2.2 配置Grafana Dashboard
[*]新建一个名为OceanBase的文件夹
https://i-blog.csdnimg.cn/direct/9abe2fe048de4c90983b70ee4d3bb980.png
[*]进入该文件夹,接着导入文件链接:grafana.yaml 中的grafana-dashboards-ob部分的json配置
https://i-blog.csdnimg.cn/direct/2a913e34189d4373ad4aff39a1eef669.png
[*]监控展示如图
https://i-blog.csdnimg.cn/direct/e165a6e56aa543a8a4840381b44e8b2a.png
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 所在资源
[*]安全性:通过网络隔离提拔了系统安全性
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]