大约75%的容器编排是在Kubernetes中完成的。但是,k8s平台的普及并不意味着它在所有场景下都容易使用。Kubernetes可能有一个陡峭的学习曲线,特别是在管理状态和存储方面。在最近一期的 "The Cockroach Hour "节目中,产品营销总监Jim Walker与Cockroach的解决方案工程师之一Keith McClellan坐下来,讨论了部署Kubernetes会遇到的存储和数据挑战,以及与CockroachDB一起运行可以如何简化这些挑战。
这篇博文回顾了他们关于Kubernetes中所有状态和存储的对话。完整的视频可以在这里观看。
为什么Kubernetes在容器编排中占主导地位?
Keith曾经在D2iQ工作过--那时它还叫Mesosphere--并以讨论Kubernetes是如何形成的,以及为什么它击败了大多数其他容器编排平台而开始了对话。D2iQ的容器编排调度平台是基于谷歌的Borg结构,它比Kubernetes更早。但在2015年,D2iQ在Kubernetes项目作为开源平台发布之前就开始为其做贡献,这也是Keith在该项目上的经验的开端。
在那段时间里,Kubernetes迅速成为顶级的容器编排平台。市场上的其他工具大多以运营商为中心,但Kubernetes赢得了胜利,因为它使开发人员能够轻松地将他们的应用程序部署到机器集群中。其他平台适合运营商将他们的容器化应用部署到机器集群中。这是一个细微的区别,但当你在谈论你要花多长时间把一个应用程序弄到人们面前时,这一点非常重要。
从ETL到Kubernetes的转变
从其他平台转移到Kubernetes需要对分布式系统进行范式转变。对于Keith来说,他最初是一个ETL开发者,在Kubernetes出现之前就遇到了ETL集群的调度问题,看到将工作负载分配给集群机器并使其能够支持生产的工具是非常好的。但是,在大型分布式数据库环境和数据管道环境中工作的挑战使Keith来到了基础设施协调领域。
当Keith在D2iQ时,它的一个产品使用CockroachDB作为元数据层。他可以看到,在分布式计算领域需要解决的下一个问题是在这种环境中做记录系统的工作负载的能力。
在Kubernetes中维护状态
Kubernetes中的存储是短暂的存储,基本上是一个临时的文件系统。当你把存储配置到该机器、该pod的本地磁盘时,它与pod共存亡。它存在的时间足够长,如果发生了非常糟糕的事情,你需要找回那个状态,你有机会做到这一点,但没有办法主动把那个状态重新连接到一个新的pod。
Kubernetes最大的挑战之一就是维护状态,然后保持状态的一致性。可以说这是在Kubernetes 1.13之前,但持久化卷和StatefulSets早在1.8的alpha测试阶段就可以使用。但在此之前,如果你的pod有一些短暂的存储,如果你没有将外部存储连接到该pod上,你就没有真正的状态,在pod重启时持续存在。因此,Kubernetes生态系统中需要有很多东西。Kubernetes最好的部分之一就是Kubernetes最坏的部分之一,因为它被设计成对开发者来说超级简单。它比一些替代品更难操作,而其中一个更难操作的东西就是引入这个有状态的存储层。
在1.8到1.13的时间框架内,他们给Kubernetes带来了持久化卷的概念,这是一个让持久化存储在本地节点上运行的想法,可供容器或吊舱使用,而不需要你做任何手动操作,将文件系统安装到吊舱或任何此类的东西。这使你能够拥有更多的有状态的应用程序。然而,持久化卷的最大挑战是,它们必须提前进行手动配置。它们必须是运营商在Kubernetes中设置的可用资源。每个节点都必须设置一组持久化卷,它们都必须挂载在该机器上,并且对运行在该机器上的Kubernetes守护程序可用,然后它们可以被保留。
存储类的设计是为了让这一切变得更容易一些。它不是直接附加到一个持久卷上,而是让节点请求具有特定类型的挂载的存储,例如,一次读/一次写或持久卷。然后,系统就会想办法把它挂载进去。但是在基于Kubernetes的生态系统之上运行持久化存储仍然存在挑战。绝大多数的持久化卷是某种类型的直接连接存储,这不是可移植的。这意味着,一旦在一个节点上启动了带有特定持久性卷的pod,在没有操作者干预的情况下,你就不能真正移动这个pod。它们是远程存储选项,允许你有一些更多的存储可移植性。但这些不一定是你要保证在每个Kubernetes集群中拥有的东西。
如果一个pod失败了,并且有一个持久的卷,那么这个卷就不会被垃圾回收,除非管理员进去删除PV。默认情况下,短暂存储的超时是12或24小时,这取决于你运行的Kubernetes中的分布。但是对于一个有状态的工作负载,你不会使用这个。那是用来收集周期性失败的豆荚的日志的,但不是我们真正要使用的存储。
状态集可以做什么
Kubernetes StatefulSet允许你将一个持久化卷的要求绑定到一个pod的克隆中。与其每次重新启动吊舱时都要手动回收该持久性卷,StatefulSet可以维护该要求,即使吊舱重新启动,并管理自动重新装载到该吊舱的过程。因此,如果我们做一个滚动重启来做一个软件升级,我们不会失去我们的存储。我们不会在Pod重启期间丢失持久性卷,以改变二进制文件,或做一个安全补丁,或重启服务器,因为我们不得不做一个操作系统补丁。
状态集的使用超越了存储。它在很大程度上是将状态与pod绑定的配置。任何需要这种标准的东西都被记录在StatefulSet的元数据中。至于系统的哪些部分目前正在利用该基础设施,它在每个Kubernetes版本中都会发生变化。每当有新的状态需要附加时,他们就把它添加到StatefulSet中。如果没有StatefulSets,你会看到更多短暂的模式。例如,如果你有一个需要证书的微服务,你就需要使用Vault这样的东西。现在,Kubernetes有自己的内置证书管理,所以它变得更容易管理。但要弄清楚元数据需要存储在Kubernetes中的位置,就变得有点复杂了。
DaemonSets和StatefulSets是不同的。一个StatefulSet将在任意数量的服务器上运行任意数量的pod。一个Daemon Set将在Kubernetes集群的每台服务器上运行一个特定pod的克隆。除非你设置了,在Kubernetes生态系统中被称为污点的东西,除非你已经标记了一个节点,使其不能获得该守护程序的副本,否则你将在集群中的每个节点上运行该pod的副本。它主要用于像安全代理这样的事情,有时你把它用于东、西负载平衡。有时,你把它用于其他类型的管理工具,比如你有一个需要在每一个节点上运行的日志存储代理,这就是你使用它的原因。它是运行有状态应用程序的一种选择。守护程序集与StatefulSet有相同的底层结构,就维护一个附加状态而言。它的工作方式与StatefulSet有点不同,但是你可以附加一个持久的卷要求作为守护集的一部分,这允许你做很多与StatefulSet相同的事情。
你可以在CockroachDB中使用daemonSets。这样做有很好的理由;很多时候,这取决于你运行Kubernetes集群的基础设施的类型。所以,因为我们可以横向和纵向扩展,所以我们可以将我们的单个pod扩展到消费者资源,或者我们可以扩展出更多的pod来提高我们的资源利用率,这取决于你的工作负载,你会如何选择更多的分布。如果你正在做大量的数据管道,在你的每一个节点上有一个本地网关到你的数据库可能是一个非常有价值的事情。但是Cockroach支持两种模式,这取决于你的使用情况。
除非你在运行两个独立的CockroachDB集群,否则你不需要同时运行一个StatefulSet和一个DaemonSet。如果你在同一个Kubernetes集群上共享生产和预生产,你可能想这么做。在这种情况下,你可能想在daemon set上运行你的生产环境,而你可能想在一个较小的节点子集上运行预生产或测试环境。但在一般意义上,这将是一种非常高级的边缘案例。
开发者真正需要关注的是他们是否有需要持久化的状态。如果他们有需要持久化的状态,那么他们就需要关心StatefulSets,或者其他一些机制来保存跨pod重启的状态。这主要是为了使生产中的这些类型的工作负载容易操作。
从开发者的角度来看,在你的pod配置中,最多只有10行YAML。在后端,有配置存储类,或配置持久化卷,以及管理索赔和所有这些东西。但从开发者的角度来看,这是一个非常容易使用的模式。
为什么在Kubernetes上使用CockroachDB?
实际上,在Kubernetes](https://www.cockroachlabs.com/docs/stable/orchestrate-cockroachdb-with-kubernetes.html)上操作CockroachDB比在裸机或静态配置的虚拟机上操作更容易,这主要是因为CockroachDB是一个单一的可执行文件,通过每个节点为数据库提供一个通用的网关。每个节点都是完全一样的。唯一的区别是该节点恰好在管理哪种类型的数据段。因此,如果你有一个间歇性的故障或你正在做一个滚动升级,你真的希望该基础设施能尽快恢复。如果你是在裸机上,你必须写一个脚本或系统服务来确保数据库重新启动。在Kubernetes上,有很多操作工作都可以不做。
然而,在有些情况下,建议客户使用裸机或基于虚拟机的安装,而不是基于Kubernetes的安装,而且有理由说明Kubernetes可能是对某人来说绝对最好的平台。但也有客户在三个或更多的数据中心运行的情况,这是很常见的事情,在多个不同的环境中运行一个数据库集群。有了Kubernetes的通用操作层,可以更容易地管理你可能没有完全相同的基础设施的事实。
在你用Kubernetes得到的这种弹性和你用裸机得到的性能之间,也有一个权衡。在这种情况下,最好的情况是在裸机上的性能要比在Kubernetes上的要好,尽管在裸机上维护数据库需要更多的操作费用。那么在基于Kubernetes的环境中,如何满足交易需求就成了一个问题。在这种情况下,CockroachDB可以通过在Kubernetes中大幅降低运营开销](https://www.cockroachlabs.com/guides/kubernetes-statefulsets/))。
问与答
Q: 你如何选择何时挂载什么东西,而何时使用本地存储?
答:一般来说,如果我知道持久性存储的状态需要在Pod重启时继续存在,我就会担心挂载持久性存储。如果我不关心状态是否能在豆荚重启后存活,那么我将使用短暂存储,因为这将允许我有最大的豆荚便携性。一旦我开始做持久化卷索赔之类的事情,就会改变这些吊舱的移动性,所以你必须作为一个操作者更加注意。如果我可以不安装存储,我就不安装存储。
Q: 你在编辑和管理YAML文件方面有什么技巧和窍门吗?
答:确保你使用VI,你不要试图在你的Mac上使用TextEdit,因为它将弄乱你所有的间距。你可以在你的Mac上或在Linux上得到一个工具,叫做YAMLlint。
Q: 为什么要联合集群的操作?为什么不直接联合数据呢?那么,CockroachDB是否可以作为这个工具来联合多个集群的工作负载?
答:这有一些例外,但是如果你的应用程序在很大程度上是无状态的,它使用数据库来维护状态,那么CockroachDB可以做到这一点。那么你就不需要连接你的控制平面,Kubernetes就是你的控制平面。你仍然要做网络配对,这在Kubernetes中不是最容易做到的事情。服务网不一定是最好的,因为它不是为点对点通信而设计的。它的设计是为了在某一特定pod的若干克隆中负载平衡传入的请求。所以你可能会使用Istio来管理你的应用程序的无状态方面。可能需要使用一些其他形式的网络配对,因为数据库中的每个节点都需要能够与数据库中的每个其他节点对话。并不是因为这种情况会经常发生,而是在失败的情况下,有时数据库不能只是与下一个最近的邻居交谈,而这个邻居恰好托管了一份数据,以获得共识。