背景
借助Deployments和ReplicationControllers,用户可以在Kubernetes中方便地部署高可用性和可伸缩的分布式无状态服务。这些类型的应用程序不在本地存储数据。通过使用简单的负载平衡策略,它们可以实现请求传递。随着k8的普及和云原生架构的兴起,越来越多的人希望通过使用k8来编排诸如数据库之类的有状态服务。但是,由于有状态服务的复杂性,此过程并不容易。本文以受欢迎的开源数据库MySQL为例,介绍如何在k8s上部署和维护有状态服务。本文的内容基于k8s 1.13
。
使用StatefulSets部署MySQL
本节使用官方的k8s教程“运行复制的有状态应用程序”中的示例来描述如何通过使用StatefulSets部署高可用性MySQL服务。
StatefulSet概述
部署和ReplicationController设计用于有状态服务。部署和ReplicationController中的Pod名称,主机名和存储不稳定。此外,会按随机顺序启动和销毁Pod。因此,它们不适用于有状态的应用程序,例如数据库。K8s提供用于管理有状态服务的StatefulSet工作负载。它的管理窗格具有以下功能:
1.性:对于具有N个副本的StatefulSet,将为StatefulSet中的每个Pod分配一个从0到N-1的整数序数。
2.序列:默认情况下,按顺序启动,更新和销毁StatefulSet中的Pod。
3.稳定的网络身份:重新安排Pod后,Pod的主机名和DNS不会更改。
4.稳定的持久性存储:重新安排Pod的时间后,它仍然可以挂载原始PersistentVolume以确保数据完整性和一致性。
服务部署
在此示例中,高可用性MySQL服务包含一个主节点和多个从节点,这些从节点以异步方式从该主节点复制数据(即,一个主-多从复制模型)。主节点可以处理来自用户的读/写请求,而从节点只能处理来自用户的读请求。
要部署这样的服务,除了StatefulSets之外,还需要许多其他k8s资源对象,包括ConfigMaps,Headless Services和ClusterIP Services。这些对象之间的协作允许有状态服务(如MySQL)有条件地在k8s上运行。
ConfigMap
为了使维护应用程序配置变得容易和方便,大型系统和分布式应用程序通常采用集中式配置管理策略。在k8s中,用户可以使用ConfigMap来将配置与Pod分开,以维护工作负载的可移植性并简化配置更改和管理。
该示例包含一个名为的ConfigMap mysql
。启动StatefulSet中的Pod时,它将根据自己的角色从ConfigMap中读取正确的配置。
无头服务
无头服务为每个关联的Pod提供表单的相应DNS地址<pod-name>.<service-name>
。这允许客户端访问任何所需的应用程序实例,并可以解决分布式环境中不同实例之间的身份识别问题。
该示例包含一个名为的无头服务mysql
,该服务与Pods相关联。这些Pod被分配了以下DNS地址:mysql-0.mysql, mysql-1.mysql
和mysql-2.mysql
。这样,客户端可以mysql-0.mysql
通过mysql-1.mysql
或通过访问主节点,从节点访问从节点mysql-2.mysql
。
ClusterIP服务
为了简化只读情况下的访问,该示例提供了一个名为的普通服务mysql-read
。该服务具有其自己的群集IP,并将请求发送到关联的Pod(包括主服务器和从服务器),以向用户隐藏Pod访问详细信息。
有状态集
StatefulSet是服务部署的关键部分。StatefulSet管理的每个Pod都被分配一个的表单名称<statefulset-name>-<ordinal-index>
。在此示例中,StatefulSet的名称为mysql
。因此,在StatefulSet豆荚命名mysql-0
,mysql-1
和mysql-2
分别。默认情况下,它们是按顺序创建的,并以相反的顺序破坏。
如下图所示,一个Pod包含两个init容器和两个app容器,并绑定到由卷供应商通过的PersistentVolumeClaim提供的PersistentVolume。
与Pod相关的组件的功能如下:
- 所述
init-mysql
容器生成的配置文件。它从主机名中提取Pod序数并将序数导出到/mnt/conf.d/server-id.cnf
文件中。通过将内容复制到中,它还可以应用ConfigMap中的master.cnf或slave.cnf(取决于节点类型)/mnt/conf
。 - 所述
clone-mysql
容器克隆数据。中的clone-mysql
容器将Pod N+1
数据从Pod克隆N
到PersistentVolume绑定。 - 初始化容器成功完成后,应用程序容器将运行。该
mysql
容器运行实际的mysqld服务器。 - 该
xtrabackup
容器充当小车。它等待mysql
容器中的mysqld 准备就绪,然后运行START SLAVE
命令以初始化从属服务器上的数据复制。xtrabackup容器还侦听来自其他Pod的请求数据克隆的连接。 - StatefulSet通过使用volumeClaimTemplates将的PC关联到每个Pod。在此示例中,Pod
N
与名为的PVC关联,该PVCdata-mysql-N
也绑定到存储系统提供的PV。此机制确保重新安排的Pod仍然可以装入原始数据。
服务维护
为了确保服务性能并提高系统可靠性,在成功完成部署后,需要进行适当的维护。与数据库服务有关的常见维护工作包括服务故障恢复,服务扩展,服务状态监视以及数据备份和恢复。
服务故障恢复
服务在故障情况下是否可以恢复自身是指示系统自动化级别的关键指标之一。在当前体系结构中,当主机遇到停机或主节点或从属节点无法响应时,可以自动还原MySQL服务。在上述问题的情况下,k8s重新安排并重新启动发生问题的Pod。StatefulSet可以确保这些Pod的名称,主机名和卷与原始项目保持一致。
服务扩展
在单主从多MySQL复制模型中,缩放意味着调整从属的数量。感谢StatefulSet提供的Pod启动和销毁顺序保证,可以使用以下命令简单地缩放从站的数量。
Kubectl scale statefulset mysql -- replicas = <NumOfReplicas>
服务状态监控
监视服务状态是确保服务稳定性的重要组成部分。除了准备情况探针和活动性探针之外,通常还需要更细粒度的监视指标来检测服务运行状况。用户可以使用mysqld-exporter将 MySQL中的关键指标公开给Prometheus,并基于Prometheus实施监视和警报。我们建议用户在同一个Pod中以sidecar模式与mysqld容器一起部署mysqld-exporter。
数据备份与恢复
数据备份和恢复是确保数据安全的有效手段。用户可以使用卷接口或VolumeSnapshots实现数据备份和恢复。以下部分描述了这两种方法。
使用音量接口
许多批量供应商都提供了保存数据快照和基于快照恢复数据的功能。这些功能通常以界面形式向用户公开。这要求用户熟悉相应的批量供应商提供的操作界面。例如,如果服务使用阿里云磁盘作为外部卷,则用户需要了解为磁盘提供的快照界面。
使用VolumeSnapshots
三快照相关的资源对象在K8S V1.12介绍:VolumeSnapshot
,VolumeSnapshotContent
,和VolumeSnapshotClass
。这些对象提供执行快照操作的标准方法。用户可以在不感知外部卷的情况下创建存储MySQL数据的卷的快照,也可以基于快照恢复数据。
与直接使用基础卷接口相比,使用VolumeSnapshots显然是一种更好的方法。但是,VolumeSnapshot仍处于Alpha阶段,并且仅有限数量的外部卷支持标准快照操作。这些因素限制了VolumeSnapshot的应用方案。有关VolumeSnapshots的更多信息,请参见Volume Snapshots文档。
使用运算符部署MySQL
尽管用户可以在基于StatefulSets的k8中部署和维护一组高度可用的MySQL服务,但过程相对复杂。此过程要求用户熟悉各种k8s资源对象,了解许多MySQL操作细节并维护一组复杂的管理脚本。Kubernetes运营商旨在降低在k8上部署复杂应用程序的门槛。
操作员介绍
一个运营商是CoreOS打包,部署和管理上Kubernetes运行复杂的应用程序引入的方法。运营商以代码形式表达维护人员对软件操作的知识,并全面使用各种k8s资源对象来部署和维护复杂的应用程序。
操作员通过使用CustomResourceDefinition定义服务的新资源对象,并通过使用自定义控制器确保应用程序处于预期状态。
操作员的工作流程可以分为三个步骤:
1.观察:使用k8s API观察目标对象的当前状态。
2.分析:找到期望状态和当前状态之间的差异。
3.Act:采取必要的步骤使应用程序的运行状态与其预期状态相匹配
Oracle MySQL运算符
许多出色的开放源代码Operator解决方案已经可用于MySQL服务,包括grtl / mysql-operator,oracle / mysql-operator,presslabs / mysql-operator和kubedb / mysql。本节中描述的Oracle MySQL Operator是这些开源解决方案的典型示例。
Oracle MySQL操作员如何工作
Oracle MySQL Operator支持以下两种MySQL部署模式。
- 主节点:在这种模式下,服务组由一个可读写的单主节点和多个只读主节点组成。
- 多主节点:在多主节点模式下,集群中的每个节点都扮演相同的角色,主从节点的概念不适用。每个节点都可以处理来自用户的读/写请求。
下图显示了操作员在多主模式下的工作方式。
以下过程对于了解操作员的工作方式非常有帮助:
1.使用k8s CustomResourceDefinitions(CRD)定义与MySQL部署和维护相关的多个资源对象。
mysqlclusters-描述预期的集群状态,包括部署模式和节点数。
mysqlbackups-描述按需备份策略并配置备份数据的存储位置(例如,在AWS S3中)。
mysqlrestores-描述数据恢复策略,并需要备份数据和目标集群。
mysqlbackupschedules-描述常规备份策略并配置备份时间间隔。
2.在k8s中部署Operator的实例。操作员将不断监视对这些资源对象的CRUD操作,并观察对象状态。
3.当用户执行操作(例如,创建MySQL集群)时,将创建一个新的MySQLCluster资源对象。当操作员侦听MySQLCluster创建事件时,它将创建一个与该用户的配置匹配的集群。本示例基于组复制创建了一个高度可用的MySQL群集,并使用了诸如StatefulSets和Headless Services之类的本地k8s资源对象。
4.当操作员发现所需状态和当前状态有所不同时,它将执行适当的编排操作以确保状态一致。
服务部署
由于操作员封装了复杂的部署详细信息,因此现在很容易创建集群。例如,用户可以使用以下配置轻松创建由三个节点组成的多主MySQL集群。
apiVersion: mysql.oracle.com/v1alpha1
kind: Cluster
metadata:
name: mysql-multimaster-cluster
spec:
multiMaster: true
members: 3
服务维护
使用操作员时,还必须进行维护,包括服务故障恢复,服务扩展,服务状态监视以及数据备份和恢复。
服务故障恢复
由于StatefulSet的存在,当k8s无法响应时,它将重新安排MySQL服务实例。另外,如果一个StatefulSet被意外删除,操作员将重新创建一个。
服务扩展
用户可以通过更改spec.members
MySQLCluster资源对象的字段轻松扩展服务。仅MySQLCluster向用户公开,而隐藏的k8s资源对象被隐藏。
服务状态监控
Prometheus可以部署在k8上,以监视Operators和各个MySQL集群的状态。有关更多信息,请参阅监视
数据备份与恢复
MySQLBackups和MySQLRestores可用于备份和恢复数据,从而消除了在不同卷上的操作差异。MySQLBackupSchedules也可以用来创建计划的备份任务。
例如,以下配置mysql-cluster
每30分钟对MySQL集群中的测试数据库执行一次备份。
[...]
kind: BackupSchedule
spec:
schedule: '*/30 * * * *'
backupTemplate:
cluster:
name: mysql-cluster
executor:
provider: mysqldump
databases:
- test
[...]
摘要
本文介绍如何通过本地k8s资源对象StatefulSet和MySQL Operator部署和维护一组高可用性MySQL服务。我们可以看到,操作员隐藏了复杂应用程序的业务流程细节,并大大降低了在k8s中使用它们的阈值。如果您需要部署其他复杂的应用程序,我们建议您使用操作员。