36

Kubernetes下存储使用为何如此之难?

 5 years ago
source link: http://dockone.io/article/8567?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Kubernetes这样的容器编排工具在应用开发部署方面起到了革命性的变革作用。随着微服务架构的发展以及从开发人员视角来看,应用逻辑架构与基础设施架构是进行了解耦,开发人员将更多的关注在软件构建以及价值交付方面。

Kubernetes将它所管理的物理服务器进行了抽象,有了Kubernetes就可以描述出和使用所需的内存和计算能力的总量,无需再关注底层的基础设施架构了。

当管理Docker镜像的时候,Kubernetes让应用变的十分便携灵活。一旦有人使用了Kubernetes进行了容器架构的应用部署,他们不用修改底层的代码就可以在部署在任何地方-不管公有云、混合云还是私有云。

虽然Kubernetes在扩展性、便携性、管理性等方面十分给力,但它同时却不支持存储状态。而现在大多数的应用却都是有状态的,此时只能使用外部存储了。

Kubernetes架构是非常灵活的,根据开发者的需求规范以及实际的负载情况,容器可以随时被创建及销毁。Pods和容器还具有自愈以及复制能力,本质上来讲,它们的生命周期很短暂。

但是,一个持久化的存储解决方法无法支持动态的应用,持久化存储无法满足动态创建和销毁的需求。

当有状态的应用需要部署到另一个基础架构平台、另一个本地或混合云提供商上时,在可移植性方面都面临着巨大的挑战。持久化的存储解决方案可以绑定到特定的云提供商上去。

另外,对于云原生应用上的存储领域很难被理解。Kubernetes存储术语很容易被混淆,包含了复杂的含义和微妙的变化。另外,在本地Kubernetes、开源框架和托管以及付费服务之间有多种选项,开发人员在做出决定之前必须考虑这些选项。

以下是CNCF列出的本地云存储方案

eQjQjmU.png!web

可能我们首先想到的是在Kubernetes里面部署数据库:选择一种适合需求的数据库,让它在本地盘上运行,然后将其作为另一个工作负载部署到集群中。但是,因为数据库的一些固有属性,这样可能并不能很好的工作。

容器是基于无状态原则进行构建的,这就意味着能很容易的使用容器。因为没有需要保存迁移的数据,集群也就不用处理磁盘读写这样密集型的工作了。

而对于数据库,其状态是需要保存的。如果在集群里以容器方式部署的数据库没有迁移,没有频繁的装配,那么数据存储的物理特性就会发挥作用。理想情况下,使用数据的容器应该与数据库位于同一个POD里面。

当然,这并不是说在容器里面部署数据库是个坏主意,在某些应用实例下,这样做就够了。在测试环境中,或者在处理非生产级别的数据时,集群中的数据库是有意义的,因为数据量很小。

实际生产中,开发人员通常要依赖外部存储。

Kubernetes通常是使用控制面板接口跟存储进行通信,这些接口将Kubernetes与外部存储进行打通,Kubernetes的外部存储方案被称为卷插件,卷插件抽象了存储并且将存储便携化了。

以前,卷插件是由核心的Kubernetes代码库构建、链接、编译以及装载的。这样就极大的限制了开发人员的便利性,带来了额外的维护花销。因此需要在Kubernetes的代码库上增加些新的存储功能了。

随着CSI以及Flexvolume的引入,卷插件可以在集群中部署,而无需更改代码库。

2aEJry2.png!web

原生Kubernetes以及存储

原生Kubernetes如何处理存储?它提供了一些方法来管理存储:短暂选项,持久卷,持久卷声明,存储类或状态集等方面的持久存储。但看起来,这可能很混乱。

PV是由管理员负责配置的存储单元,他们独立于任何一个单独的POD,不受POD生命周期的影响。

另一方面,PVC是对存储的需求,也就是PV。有了PVC,就可以将存储与特定的节点绑定在一起使用。

有两种使用存储的方法:静态存储和动态存储。

使用静态存储时,管理员提前配置好预估的PV,这些PV被绑定到具有显示PVC的特定POD上。

实际上,静态定义PV并不能适应Kubernetes的可移植特性,因为存储可能依赖于环境,譬如AWS的EBS或者GCE的持久磁盘。手工绑定需要针对特定品牌的存储来修改YAML文件。

在资源分配方面,静态配置实际上也是违背了Kubernetes的原则,CPU和内存不是事先被分配好绑定在POD或者容器上,他们是被动态分配的。

动态分配依靠存储类来实现,集群管理员不需要事先手动创建PV,而是创建类似于模版的文件。当开发人员制作PVC时,根据请求的内容创建一个模版并附加到POD上。

eaMZBnV.png!web

以上是本地Kubernetes如何使用外部存储的最宽泛的说法,还有其他更多的因素需要考虑。

容器存储接口:

首先介绍下容器存储接口,CSI是由CNCF存储工作组创建的统一标准,旨在定义一个标准的容器存储接口,从而使存储驱动器可以在任何容器架构下工作。

CSI规范已经适用于Kubernetes,大量的驱动插件已经可以部署在Kubernetes集群里。开发人员可以使用Kubernetes上的CSI卷来访问CSI兼容的开放存储卷。

随着CSI的引入,存储可以作为Kubernetes集群上的另一种工作负载被容器化以及部署。

开源项目

围绕着云原生技术出现了大量的工具以及项目,作为在生产中最为突出的问题之一,也有大量的开源项目来解决云原生架构下的存储使用问题。

目前最为流行的存储项目是Ceph和Rook.

Ceph是一种动态管理,水平扩展,分布式的存储集群。Ceph提供了一种存储资源之上的逻辑抽象,它的设计理念是无单点故障、自管理、软件定义。Ceph可以对同一套存储集群同时提供块存储、对象存储以及文件存储的接口。

Ceph架构是很复杂的,使用了大量的底层技术,譬如RADOS,librados,RADOSGW,RDB,CRUSH算法以及像监视器,OSD和MDS这样的组件。先不用细究它的底层架构,关键在于Ceph是一个分布式的存储集群,使得扩展更便利、在不牺牲性能的前提下消除了单点故障,提供了对象存储、块存储以及文件存储的统一存储。

自然的,Ceph和云原生环境是兼容的,有多种方法可以部署一套Ceph集群,譬如使用Ansible。我们可以部署一套Ceph集群,并且使用CSI和PVC来提供对Kubernetes集群的接口。

FRjMvmE.png!web

Ceph架构图

另一种有趣且十分流行的项目是Rook,一种旨在将Kubernetes和Ceph融合的技术,将计算节点和存储节点放在了同一个集群里。

Rook是一种云原生的编排器,它扩展了Kubernetes。Rook允许将Ceph放在容器里,并且提供了卷管理逻辑,使得能在Kubernetes上可靠的运行Ceph。Rook自动化了本应由集群管理员来操作的工作,譬如部署、引导、配置、扩展、负载等等。

Rook可以像Kubernetes一样使用yaml文件来部署Ceph集群,这种文件作为高级别的声明,提供了集群管理员的所需要的内容。

Rook启动完集群后,就开始了实时监控。Rook作为操作端或者控制端来确保yaml文件里面所声明的状态正常。Rook运行在一个协调的逻辑环中,该循环观察运行状态并根据它检测到的差异来采取行动。

Rook自身没有持久状态,也不需要被管理,是真正根据Kubernetes的原则进行构造的。

2YzMjen.png!web

Rook和Ceph以及Kubernetes一起,成为了最受欢迎的云原生存储解决方案。已经有了差不多4000的Github评星,1600多万次的下载,以及100多名贡献者。

作为CNCF认可的第一个存储项目,Rook现在已经进入了孵化阶段。

对于一个应用中的任何问题,最重要的是判断需求、设计系统或者选取恰当的工具。云原生环境下存储也是这样,虽然问题很复杂,但也会有更多大量的工具方案来解决它。随着云原生世界的发展,无疑也会出现新的解决方案。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK