本文已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。
如何在 Kubernetes 中为 TPR 集成 RollingUpdate 策略
使用 Kubernetes,可以轻松管理和扩展无状态应用程序,例如开箱即用的 Web 应用程序和 API 服务。到目前为止,几乎所有关于 Kubernetes 的讨论都集中在微服务和无状态应用程序上。
随着基于容器的微服务架构的普及,迫切需要部署和管理 RDBMS(关系数据库管理系统)。RDBMS 需要经验丰富的数据库特定知识,才能正确扩展、升级和重新配置,同时防止数据丢失或不可用。
例如,MySQL(最流行的开源 RDBMS)需要将数据存储在对每个 MySQL 数据库的存储都是持久且独占的文件中。每个 MySQL 数据库需要单独区分,另一个更复杂的是在集群中,需要将一个 MySQL 数据库与集群中的不同角色区分开来,例如主服务器、从服务器或分片。在更换故障机器上的数据库节点时,实现高可用性和零数据丢失也很困难。
使用强大的 Kubernetes API 扩展机制,我们可以将 RDBMS 领域知识编码到名为 WQ-RDS 的软件中,该软件像内置资源一样在 Kubernetes 之上运行。
WQ-RDS 利用 Kubernetes 的基本资源和控制器,它提供许多企业级功能,并带来了一种非常可靠的方式来自动化耗时的操作任务,例如数据库设置、补丁备份和设置高可用性集群。WQ-RDS 支持主流版本的 Oracle 和 MySQL(均与 MariaDB 兼容)。
让我们演示如何管理 MySQL 分片集群。
MySQL 分片集群
MySQL 分片集群是一种横向扩展的数据库架构。基于哈希算法,该架构将数据分布到集群的所有分片中。分片对客户端完全透明:代理能够连接到集群中的任何分片,并将查询直接发送到正确的分片。
| ----- |
| |
|
注意:每个分片对应一个 MySQL 实例。目前,WQ-RDS 最多支持 64 个分片。
|
所有分片都使用 Kubernetes Statefulset、服务、存储类、configmap、secrets 和 MySQL 构建。WQ-RDS 管理分片集群的整个生命周期。分片集群的优点很明显
- 横向扩展每秒查询数 (QPS) 和每秒事务数 (TPS)
- 横向扩展存储容量:通过将数据分发到多个节点来获得更多存储空间
创建 MySQL 分片集群
让我们创建一个具有 8 个分片的 Kubernetes 集群。
kubectl create -f mysqlshardingcluster.yaml
接下来,创建一个包含 8 个分片的 MySQL 分片集群。
- TPR : MysqlCluster 和 MysqlDatabase
[root@k8s-master ~]# kubectl get mysqlcluster
NAME KIND
clustershard-c MysqlCluster.v1.mysql.orain.com
从 clustershard-c0 到 clustershard-c7 的 MysqlDatabase 属于 MysqlCluster clustershard-c。
[root@k8s-master ~]# kubectl get mysqldatabase
NAME KIND
clustershard-c0 MysqlDatabase.v1.mysql.orain.com
clustershard-c1 MysqlDatabase.v1.mysql.orain.com
clustershard-c2 MysqlDatabase.v1.mysql.orain.com
clustershard-c3 MysqlDatabase.v1.mysql.orain.com
clustershard-c4 MysqlDatabase.v1.mysql.orain.com
clustershard-c5 MysqlDatabase.v1.mysql.orain.com
clustershard-c6 MysqlDatabase.v1.mysql.orain.com
clustershard-c7 MysqlDatabase.v1.mysql.orain.com
接下来,让我们看看两个主要功能:高可用性和滚动更新策略。
为了演示,我们将首先运行 sysbench 以在集群上生成一些负载。在此示例中,QPS 指标由 MySQL 导出生成,由 Prometheus 收集并在 Grafana 中可视化。
功能:高可用性
WQ-RDS 处理 MySQL 实例崩溃,同时防止数据丢失。
当杀死 clustershard-c0 时,WQ-RDS 将检测到 clustershard-c0 不可用,并在故障机器上替换 clustershard-c0,平均耗时约 35 秒。
同时实现零数据丢失。
功能:滚动更新策略
MySQL 分片集群不仅为我们带来了强大的可扩展性,还带来了一些维护复杂性。例如,当更新 MySQL 配置(如 innodb_buffer_pool_size)时,DBA 必须执行许多步骤
1. 应用更改时间。
2. 禁用客户端对数据库代理的访问。
3. 启动滚动升级。
滚动升级需要按顺序进行,并且是该过程中最苛刻的步骤。除非对 MySQL 实例的先前更新正在运行并准备就绪,否则无法继续滚动升级。
4 验证集群。
5. 启用客户端对数据库代理的访问。
滚动升级可能出现的问题包括
- 节点重启
- MySQL 实例重启
- 人为错误。相反,WQ-RDS 使 DBA 可以自动执行滚动升级。
Kubernetes 中的 StatefulSet 滚动更新
Kubernetes 1.7 包含一个主要功能,该功能为 StatefulSet 添加了自动更新,并支持包括滚动更新在内的一系列更新策略。
注意: 有关 StatefulSet 滚动更新的更多信息,请参阅 Kubernetes 文档。
由于 TPR(目前为 CRD)不支持滚动升级策略,因此我们需要将滚动更新策略集成到 WQ-RDS 中。幸运的是,Kubernetes 存储库是学习的宝藏。在实施过程中,有一些要分享的要点
**MySQL 分片集群发生了**变化:每个 StatefulSet 都有其对应的 ControllerRevision,其中记录了所有修订数据和顺序(如 git)。每当 StatefulSet 同步时,StatefulSet 控制器将首先将其规范与最新的对应 ControllerRevision 数据进行比较(类似于 git diff)。如果发生更改,则将生成新的 ControllerrRevision,并且修订号将增加 1。WQ-RDS 借用此过程,MySQL 分片集群对象将记录 ControllerRevision 中的所有修订和顺序。
**如何初始化 MySQL 分片集群以满足请求**副本:Statefulset 支持两种 Pod 管理策略:并行和有序就绪。由于 MySQL 分片集群的初始过程不需要按顺序创建,因此我们使用并行策略来加速集群的初始化。
**如何执行滚动**升级:Statefulset 以严格递减的顺序重新创建 Pod。不同之处在于,WQ-RDS 更新分片而不是重新创建它们,如下所示:
滚动更新何时结束:Kubernetes 明确发出终止信号。当集合的所有 Pod 都已更新到 updateRevision 时,滚动更新完成。状态的 currentRevision 设置为 updateRevision,其 updateRevision 设置为空字符串。状态的 currentReplicas 设置为 updateReplicas,其 updateReplicas 设置为 0。
WQ-RDS 中的控制器修订
修订信息存储在 MysqlCluster.Status 中,与 Statefulset.Status 没有区别。
root@k8s-master ~]# kubectl get mysqlcluster -o yaml clustershard-c
apiVersion: v1
items:
\- apiVersion: mysql.orain.com/v1
kind: MysqlCluster
metadata:
creationTimestamp: 2017-10-20T08:19:41Z
labels:
AppName: clustershard-crm
Createdby: orain.com
DBType: MySQL
name: clustershard-c
namespace: default
resourceVersion: "415852"
uid: 6bb089bb-b56f-11e7-ae02-525400e717a6
spec:
dbresourcespec:
limitedcpu: 1200m
limitedmemory: 400Mi
requestcpu: 1000m
requestmemory: 400Mi
status:
currentReplicas: 8
currentRevision: clustershard-c-648d878965
replicas: 8
updateRevision: clustershard-c-648d878965
kind: List
示例:执行滚动升级
最后,我们现在可以更新“clustershard-c”,将配置“innodb_buffer_pool_size”从 6GB 更新为 7GB 并重新启动。
该过程需要 480 秒。
升级以单调递减的方式进行
结论
滚动升级对数据库管理员有意义。它提供了一种更有效的方式来操作数据库。