为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在Kubernetes上使用存储这么难?

图片描述

Kubernetes这样的容器编排工具正在彻底改变应用程序的开发和部署方式。从开发人员视角来看,随着微服务架构的兴起以及基础架构与应用程序逻辑解耦,开发人员越来越聚焦于构建软件和提供价值本身。

Kubernetes对其管理的物理机器进行了抽象。使用Kubernetes,您可以描述所需的内存量和计算能力,并使其可用而无需担心底层基础架构。

在管理Docker镜像时,Kubernetes还使得应用程序可移植。一旦使用Kubernetes开发容器化架构,它们就可以部署在任何地方 - 公共云,混合云或本地私有部署 - 无需对底层代码进行任何更改。

虽然Kubernetes在许多方面非常有用,例如可伸缩性,可移植性和可管理性,但它不支持存储状态。而几乎所有的生产应用程序又都是有状态的,即需要某种外部存储。

Kubernetes架构是动态的。容器的创建和销毁取决于负荷和开发人员的需求描述。Pod和容器可以自我修复和复制。从本质上讲,它们是短暂的。

但是,持久存储的方案无法实现这种动态行为。永久存储不能绑定到哪些动态创建和销毁的规则上。

当有状态应用需要部署在另一个基础架构,比如可能是另一个云提供商,本地或混合云上时,它们在可移植性方面面临挑战。持久存储解决方案可以绑定到特定的云提供商。

此外,为云原生应用程序的打造的存储方案并不容易理解。Kubernetes的存储机制描述带有许多具有复杂含义和微妙变化的术语,可能会引起疑惑和费解。此外,在原生Kubernetes、开源框架以及托管或付费服务之间,开发人员在做出决策之前必须考虑有很多因素选项。

您可以在下面看到CNCF全景图中列出的云原生存储解决方案:

图片描述

也许我们的第一个想法是在Kubernetes中部署数据库:选择适合您需求的数据库解决方案,将其以容器化形式在本地磁盘上运行,并将其作为一个工作负载部署在您的集群中。但是,由于数据库的固有属性,这通常无法很好地工作。

容器构建以无状态为原则。这使得我们可以快速启动和销毁容器,因为没有要保存和迁移的数据,因此群集不需处理通常密集的磁盘读写操作。

使用数据库,需要保留状态。如果以容器化方式部署在集群上的数据库不迁移数据,那么数据存储的物理特性将起作用。理想情况下,使用这些数据的容器与数据库应位于同一个Pod中。

这并不是说在容器中部署数据库是一个坏主意 - 在某些情况中,这种方法可能非常适合。比如:在测试环境中,或者那些不需要生产级数据量的任务中,集群中的数据库可能是有意义的,因为所持有的数据规模较小。

在生产环境中,开发人员通常依赖外部存储。

Kubernetes如何与存储通信?它使用控制平面接口。这些接口将Kubernetes与外部存储相关联。这些与Kubernetes相关的外部存储解决方案称为Volume plugins(卷插件)。Volume Plugins支持抽象存储并授予存储可移植性。

以前,Volume plugin是伴随Kubernetes核心代码库构建,链接,编译和发布的。这极大地限制了开发人员的灵活性,并带来了额外的维护成本。添加新的存储选项需要更改Kubernetes核心代码库。

通过引入CSI和Flexvolume,在无需更改核心代码的情况下,我们就可以在集群上部署卷插件。

图片描述

原生Kubernetes和存储

原生Kubernetes如何处理存储?Kubernetes原生提供了一些管理存储的解决方案:短暂存储和持久存储。后者基于持久存储卷(PV),持久卷声明(PVC),存储类(StorageClass)或StatefulSets等抽象概念。这可能会令人有些迷惑。

持久卷(PV)是由管理员配置的存储单元。它们独立于任何一个Pod,这使它们的生命周期不与Pod挂钩。

另一方面,持久量声明(PVC)是对存储(比如PV)的请求。使用PVC,可以将存储绑定到特定节点,使其可供该节点使用。

Kubernetes有两种处理存储的方法:静态或动态。

使用静态配置,管理员在实际请求之前提供他们自认为pod可能需要的PV,并且这些PV被手动绑定到具有显式PVC的特定pod。

在实际中,静态定义的PV与Kubernetes的可移植结构并不兼容,这是因为正在使用的存储可能依赖于环境,例如AWS EBS或GCE Persistent Disk。手动绑定需要更改YAML文件以指向特定于供应商的存储解决方案。

静态配置方式也违背了Kubernetes的思维方式:开发人员如何考虑资源:CPU和内存未事先分配并绑定到pod或容器。它们是动态授予的。

动态配置使用存储类(StorageClass)完成。集群管理员无需事先手动创建PV。他们改为创建多个存储配置文件,就像模板一样。当开发人员制作PVC时,根据请求的要求,在请求时创建其中一个模板,并将其附加到pod。

图片描述

这是对Kubernetes原生处理外部存储机制的的非常广泛的概述。但是,还有许多其他选择可以考虑。

CSI - 容器存储接口

在继续之前,我想介绍容器存储接口(Container Storage Interface,CSI)。CSI是由CNCF存储工作组贡献的成果,它旨在定义标准容器存储接口,使存储驱动程序能够在任何容器编排器上工作。

CSI规范已经适用于Kubernetes,并且可以在Kubernetes集群上部署大量驱动程序插件。开发人员可以使用Kubernetes上的csi卷类型访问由CSI兼容卷驱动程序提供的存储。

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

欲了解更多信息,请与Jie Yu一起收听我们关于CSI的一集。

开源项目

围绕云原生技术出现了大量工具和开源项目。作为生产环境中最突出的问题之一,在云原生架构上处理存储吸引了相当多的致力于解决该问题的开源项目。

关于存储的最受欢迎的项目是Ceph和Rook。

Ceph是一个动态管理,可水平扩展的分布式存储集群。Ceph提供了对存储资源的逻辑抽象。它的设计目的是没有单点故障,自我管理和基于软件算法。Ceph同时为同一存储集群提供块,对象或文件系统接口。

Ceph的架构很复杂,有许多底层技术,如RADOS,librados,RADOSGW,RDB,它的CRUSH算法,以及监视器,OSD和MDS等组件。Ceph是一个分布式存储集群,我们不需要深入研究其体系结构,它是一个分布式存储集群,它使得可扩展性更加容易,消除单点故障而不牺牲性能,并提供可访问对象,块和文件的统一存储。

当然,Ceph已经适应了云原生环境。您可以通过多种方式部署Ceph集群,例如使用Ansible。您可以使用CSI和PVC部署Ceph集群并从Kubernetes集群中获取接口。

图片描述

另一个有趣且颇受欢迎的项目是Rook,这是一个旨在融合Kubernetes和Ceph的工具 - 将计算和存储集中在一个集群中。

Rook是一个云原生存储编排器。它扩展了Kubernetes。Rook本质上允许将Ceph放入容器中,并提供集群管理逻辑,以便在Kubernetes上可靠地运行Ceph。Rook自动化部署,引导,配置,扩展,重新平衡,即集群管理员执行的那些工作。

Rook支持基于yaml部署Ceph集群,就像Kubernetes一样。此文件用作集群管理员在集群中所需内容的更高级别声明。Rook随集群启动,并开启监控。Rook充当操作员(operator)或控制器(controller),确保yaml文件中声明的所需状态得到维护。Rook在一个协调循环中运行,该循环观察状态并根据它检测到的差异采取行动。

Rook没有自己的持久状态,也不需要管理。它是真正根据Kubernetes的原则建造的。

图片描述

Rook将Ceph和Kubernetes结合在一起,是最受欢迎的云原生存储解决方案之一,拥有近4000名Github明星,16.3M下载量和100多名贡献者。

作为第一个被CNCF认可接纳的存储项目,Rook最近被接受进入孵化阶段。

有关Rook的更多信息,请收听我们关于Kubernetes Storage与Bassam Tabara的一集。

对于应用程序中的任何问题,重要的是识别和确定需求,并相应地设计系统或选择工具。云原生环境中的存储也不例外。虽然问题非常复杂,但仍有许多工具和方法。随着云原生世界的发展,无疑也会出现新的解决方案。


点击查看更多内容
“小礼物走一走,来慕课关注我”
赞赏支持
Tony Bai 说 去围观
Tony Bai,智能网联汽车独角兽公司先行研发部负责人,Go语言专家,资深架构师,《Go语言精进之路》作者。
评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消