数据库和Kubernetes(评论和视频报告)

11月8日,在HighLoad ++ 2018会议的主厅中,在DevOps和Operations部分的框架内,做了一个名为Databases and Kubernetes的报告。 它讨论了数据库的高可用性以及对Kubernetes进行容错的方法,以及与之相关的方法,以及将DBMS置于Kubernetes集群中的实用选项以及为此的现有解决方案(包括PostgreSQL的Stolon)。



按照传统,我们很高兴为您提供一个带有报告视频 (大约一个小时, 文章内容丰富得多 ),并以文本形式进行主要压缩。 走吧

理论


这份报告是对过去几年来我们在不同地方不知疲倦地问到的最流行问题之一的答案:有关中心或YouTube的评论,社交网络等。 听起来很简单:“是否可以在Kubernetes中运行数据库?”,而且如果我们通常回答“通常是,但是...”,那么显然对于“一般”和“但是”没有足够的解释,而是适合它们短消息中没有成功。

但是,对于初学者来说,我将从“数据库[data]”到整个有状态的问题进行总结。 DBMS只是有状态决策的一种特殊情况,其更完整的列表可以表示如下:



在查看特定案例之前,我将讨论Kubernetes的工作/使用的三个重要特征。

1. Kubernetes高可用性哲学


每个人都知道“宠物与牛 ”的比喻,并且了解到,如果Kubernetes是牧群的故事,那么经典的DBMS就是宠物。

在“传统”版本中,“宠物”的架构是什么样的? 安装MySQL的一个经典示例是在具有冗余电源,磁盘,网络...和其他所有东西(包括工程师和各种辅助工具)的两台铁服务器上进行复制,这将帮助我们确保MySQL进程不会失败,以及是否存在任何关键问题。对于它的组件,将考虑容错能力:



Kubernetes的外观如何? 在这里,通常有更多的铁服务器,它们更简单,并且没有冗余的电源和网络(从某种意义上说,一台机器的丢失不会影响任何东西)-所有这些都被组合成一个集群。 它的容错能力由软件提供:如果节点发生故障,Kubernetes会检测并启动另一个节点上的必要实例。

K8中高可用性的机制是什么?



  1. 控制器 有很多,但主要有两个: Deployment (用于无状态应用程序)和StatefulSet (用于有状态应用程序)。 它们存储在节点崩溃(无法访问Pod)时采取的所有操作逻辑。
  2. PodAntiAffinity指定特定Pod的能力,以使它们不在同一节点上。
  3. PodDisruptionBudgets在计划的工作中可以同时关闭的Pod实例数的限制。

2. Kubernetes一致性保证


熟悉的单主机容错方案如何工作? 两台服务器(主服务器和备用服务器),其中一台由应用程序不断访问,而服务器又通过负载平衡器使用。 如果出现网络问题怎么办?



经典的裂脑 :应用程序开始访问两个DBMS实例,每个实例都认为自己是主要实例。 为避免这种情况,在对主服务器进行投票时,已经用三个实例的corosync替换了keepalived以达到法定人数。 但是,即使在这种情况下,仍然存在问题:如果一个崩溃的DBMS实例试图以各种可能的方式“杀死自己”(删除IP地址,将数据库转换为只读...),那么集群的另一部分也不知道主服务器发生了什么-可能会发生,该节点实际上仍然可以正常工作并且有请求到达该节点,这意味着我们仍然无法切换向导。

为了解决这种情况,存在一种隔离节点的机制,以保护整个群集免受错误操作的影响-此过程称为fencing 。 实际的实质归结为以下事实:我们正在尝试通过某种外部手段“杀死”下车的人。 这些方法可能有所不同:从通过IPMI关闭计算机并阻止交换机上的端口到访问云提供商的API等。 并且只有在执行此操作之后,才能切换向导。 这确保了一次最多的保证,以确保我们的一致性



如何在Kubernetes中实现相同目标? 为此,已经提到了控制器,在节点无法访问的情况下,其行为有所不同:

  1. Deployment :“有人告诉我应该有3个吊舱,现在只有2个吊舱-我将创建一个新的吊舱”;
  2. StatefulSet :“豆荚走了吗?” 我将等待:这个节点将返回,或者他们将告诉我们杀死它,” 容器本身(无需操作员操作)不会重新创建。 这就是达到相同的一次最多保证的方式。

但是,在这种情况下,在后一种情况下,需要隔离:我们需要一种机制来确认此节点肯定不存在。 首先,使其变得自动化非常困难(需要许多实现),其次,更糟糕的是,它通常会缓慢杀死节点(访问IPMI可能需要几秒钟或数十秒,甚至几分钟)。 很少有人对每分钟将主机切换到新主机感到满意。 但是还有另一种方法不需要隔离机制...

我将在Kubernetes之外开始他的描述。 它使用一个特殊的负载平衡器,后端通过该负载平衡器访问DBMS。 它的特殊性在于它具有一致性的特性,即 防止网络故障和裂脑的保护,因为它允许您删除与当前主服务器的所有连接,等待另一个节点上的同步(副本)并切换到该主节点。 我没有找到这种方法的固定术语,而是称之为“ 一致切换”



他面临的主要问题是如何使其通用,同时为云提供商和私有安装提供支持。 为此,将代理服务器添加到应用程序中。 它们中的每个都将接受来自其应用程序的请求(并将它们转发到DBMS),并且将从所有它们中收集仲裁。 一旦群集的某些部分发生故障,丢失仲裁的那些代理将立即删除其与DBMS的连接。



3.数据存储和Kubernetes


主要机制是各种实现中针对所需云选项或裸机的网络块设备 (aka SAN)网络驱动器。 但是,由于延迟 ,将加载的数据库(例如,需要5万IOPS的MySQL)放入云(AWS EBS)中将无法正常工作。



在这种情况下,Kubernetes可以连接本地硬盘驱动器- 本地存储 。 如果发生故障(磁盘在Pod中不再可用),那么我们将被迫修理这台机器-类似于一台可靠服务器发生故障的经典方案。

这两个选项(“ 网络块设备”和“ 本地存储” )都属于ReadWriteOnce类别:不能将存储安装在两个位置(pod)中-为了进行这种扩展,您将需要创建一个新磁盘并将其连接到一个新的pod(为此内置了K8s机制) ,然后填写必要的数据(已经由我们的部队完成)。

如果我们需要ReadWriteMany模式,则可以使用网络文件系统 (或NAS)实施:对于公共云,它们是AzureFileAWSElasticFileSystem ,对于安装它们的CephFS和Glusterfs(适用于分布式系统的爱好者)以及NFS。



练习


1.独立


此选项适用于以下情况:什么都不能阻止您使用本地存储在单独的服务器模式下启动DBMS。 毫无疑问是高可用性的……尽管可以在一定程度上(即对于该应用程序而言)在铁级上实现。 此应用程序有很多情况。 首先,这些都是各种暂存和开发环境,但不仅如此:辅助服务也落在这里,禁用它们15分钟并不重要。 在Kubernetes中,这是由StatefulSet通过一个Pod实现的:



通常,这是一个可行的选择,从我的角度来看,与在单独的虚拟机上安装DBMS相比,它没有什么缺点。

2.复制对,手动切换


再次使用StatefulSet ,但一般方案如下所示:



如果其中一个节点崩溃( mysql-a-0 ),则不会发生奇迹,但是我们有一个副本( mysql-b-0 ),我们可以将流量切换到该副本。 在这种情况下,即使在切换流量之前,重要的是不要忘记不仅要从mysql服务中删除DBMS请求,而且要手动登录到DBMS并确保所有连接都已完成(杀死它们),还必须从DBMS转到第二个节点并重新配置副本在相反的方向。

如果您当前使用的是带有两个服务器(主服务器+备用服务器)且没有自动故障转移的经典版本,则此解决方案在Kubernetes中是等效的。 适用于MySQL,PostgreSQL,Redis等产品。

3.扩展读取负载


实际上,这种情况不是有状态的,因为我们只是在谈论阅读。 在这里,主DBMS服务器在所考虑的方案之外,并且在Kubernetes的框架内,创建了一个“从属服务器场”,它们是只读的。 通用机制-使用初始化容器在该服务器场的每个新容器上填充DBMS数据(使用热转储或具有附加操作的常用容器等)取决于所使用的DBMS。 为确保每个实例与主实例之间的距离都不太远,可以使用活动性测试。



4.智能客户端


如果您创建一个由三个Memcached组成的StatefulSet ,Kubernetes将提供一项特殊服务,该服务不会平衡请求,但会为自己的域创建每个Pod。 如果客户本人能够进行分片和复制,则可以与他们一起工作。

您无需走太远的例子:这是开箱即用的会话存储在PHP中的工作方式。 对于每个会话请求,同时向所有服务器发出请求,然后从它们中选择最相关的答案(类似于记录)。



5.云原生解决方案


最初有许多解决方案着眼于节点故障,即 它们本身可以执行节点的故障转移和恢复,并提供一致性保证。 这不是它们的完整列表,而只是流行示例的一部分:



它们都被简单地放置在StatefulSet ,之后节点之间会相互发现并形成一个集群。 产品本身在实现三件事方面的不同之处:

  1. 节点如何相互了解? 有这样的方法,例如Kubernetes API,DNS记录,静态配置,专用节点(种子),第三方服务发现...
  2. 客户端如何连接? 通过分配给主机的负载均衡器,或者客户端需要了解所有主机,他将决定如何进行操作。
  3. 水平缩放如何完成? 没办法,完全或困难/有限制。

无论针对这些问题选择哪种解决方案,所有这些产品都可以与Kubernetes很好地工作,因为它们最初是作为“牛群” (牛)创建的

6. Stolon PostgreSQL


Stolon实际上允许您将作为宠物创建的PostgreSQL转换为 。 如何实现的?



  • 首先,我们需要一个服务发现,其角色可能是etcd (其他选项可用)-它们的集群放置在StatefulSet
  • 基础架构的另一部分是带有PostgreSQL实例的StatefulSet 。 除了适当的DBMS之外,每个安装旁边还有一个名为keeper的组件,该组件执行DBMS配置。
  • 另一个组件( 哨兵)被部署为Deployment并监视群集的配置。 由他决定谁将成为主服务器和备用服务器,并将此信息写入etcd。 并且keeper从etcd读取数据,并使用PostgreSQL实例执行与当前状态相对应的操作。
  • 部署在Deployment并面向PostgreSQL实例的另一个组件( 代理)是已经提到的一致性切换模式的实现。 这些组件已连接到etcd,如果此连接丢失,则代理将立即终止传出连接,因为从那时起,它就不知道其服务器的角色(现在是主服务器还是备用服务器?)。
  • 最后,代理实例面对通常的LoadBalancer LoadBalancer。

结论


那么有可能基于Kubernetes吗? 是的,当然,在某些情况下是有可能的……如果合适的话,可以这样做(参见Stolon工作流程)……

每个人都知道技术在不断发展。 最初,任何新设备都很难使用,但是随着时间的流逝,一切都会发生变化:技术变得可用。 我们要去哪里 是的,它会保留在里面,但我们不知道它如何工作。 Kubernetes正在积极发展运营商 。 到目前为止,它们的数量并不多,也不是那么好,但是朝着这个方向发展。

影片和幻灯片


表演视频(大约一个小时):



报告介绍:



附言:我们还在网上从这份报告中发现了非常简短的文字提示 -感谢Nikolai Volynkin。

PPS


我们博客上的其他报告:


您可能也对以下出版物感兴趣:

Source: https://habr.com/ru/post/zh-CN431500/


All Articles