深挖Kubernetes存储为何如此难及其解决方案

2020 年 5 月 14 日

深挖Kubernetes存储为何如此难及其解决方案

以 Kubernetes 为代表的容器编排工具在应用开发部署领域起正发挥着颠覆性的变革作用。随着微服务架构的发展,从开发人员的角度来看,应用逻辑架构与基础设施架构之间开始解耦,这意味着开发者能够将精力更多集中在软件构建以及价值交付身上。


Kubernetes 的作用,在于对其管理的物理服务器进行抽象。在 Kubernetes 的帮助下,我们可以描述并使用所需要的内存与计算容量的总和,而不再关注底层基础设施架构。


当管理 Docker 镜像的时候,Kubernetes 也让实际应用变的十分便捷灵活。在利用 Kubernetes 进行容器架构的应用部署时,管理员们将在无需修改底层代码的前提下将其部署在任何位置——包括公有云、混合云乃至私有云。


虽然 Kubernetes 在扩展性、便携性与管理性等方面的表现都相当给力,但截至目前,它仍然不支持存储状态。与之对应的是,如今的大多数应用都是有状态的——换言之,要求在一定程度上配合外部存储资源。


Kubernetes 架构本身非常灵活的,能够根据开发者的需求、规范以及实际负载情况,对容器进行随意创建与撤销。此外,Pod 和容器还具有自我修复与复制能力。因此从本质上讲,它们的生命周期普遍非常短暂。


但是,现有持久存储解决方法无法支持动态的应用场景,而持久化存储也无法满足动态创建与撤销的需求。


当我们需要将有状态应用部署到其它基础架构平台,或者另一家内部或混合云供应商的环境中时,可移植性低下无疑将成为我们面临的巨大挑战。更具体地讲,持久化存储解决方案往往会锁定于特定云服务供应商,而无法灵活完成转移。


另外,云原生应用中的存储机制也相当复杂、难于理解。Kubernetes 中的不少存储术语极易混淆,其中包含着复杂的含义与微妙的变化。再有,在原生 Kubernetes、开源框架以及托管与付费服务之间还存在着诸多选项,这极大增加了开发人员在做出决定之前的考量与试验成本。


以下是 CNCF 列出的云原生存储可选方案:



我们首先从最简单的场景出发,即在 Kubernetes 当中部署一套数据库。具体流程包括:选择一套符合需求的数据库,让它在本地磁盘上运行,然后将其作为新的工作负载部署到集群当中。但是,由于数据库中存在的一些固有属性,这种方式往往无法带来符合预期的效果。


容器本身是基于无状态原则进行构建的,凭借这一天然属性,我们才能如此轻松地启动或撤销容器环境。由于不存在需要保存及迁移的数据,集群也就不需要同磁盘读写这类密集型操作绑定在一起了。


但对于数据库,其状态必须随时保存。如果以容器方式部署在集群当中的数据库不需要进行迁移,或者不需要频繁开关,那么其基本属性就相当于一种物理存储设备。在理想情况下,使用数据的容器应该与该数据库处于同一 Pod 当中。


当然,这并不是说将数据库部署在容器中的作法不可取。在某些应用场景下,这样的设计完全能够满足需求。举例来说,在测试环境或者处理非生产级数据时,由于总体数据量很小,将数据库纳入集群完全没有问题。但在实际生产中,开发人员往往需要仰仗于外部存储机制。


Kubernetes 到底是如何与存储资源彼此通信的?其利用的是控制层接口。这些接口负责将 Kubernetes 与外部存储相对接。接入 Kubernetes 的外部存储解决方案被称为“卷插件(Volume Plugins)”。正是有了卷插件的存在,存储资源才得以抽象化并实现可移植性。


以前,卷插件一般由核心 Kubernetes 代码库进行构建、链接、编译以及装载。这样就极大的限制了开发人员的发挥空间,同时也带来了额外的维护开销。因此,项目维护人员们决定在 Kubernete 的代码库上增加一些新的存储功能。


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



原生 Kubernetes 与存储


原生 Kubernetes 如何处理存储资源?它提供一系列管理存储选项:除了临时选项之外,还包括持持久卷(Persistent Volumes),持久卷声明(Persistent Volume Claims),存储类(Storage Classes)乃至 StatefulSets 等持久存储形式。似乎有点乱,下面我们就对其进行一一解释。


持久卷是由管理员负责配置的存储单元,它们独立于任何单一 Pod 之外,因此不受 Pod 生命周期的影响。


另一方面,持久卷声明是对存储资源——也就是持久卷——的需求。有了持久卷声明,我们就可以将存储与特定的节点绑定在一起使用。


存储资源有两种使用方式:静态存储与动态存储。


使用静态存储时,管理员根据预估对持久卷进行预配置,这些持久卷将被手动绑定到具有明确持久卷声明的特定 Pod 上。


实际上,静态定义的持久卷并不能适应 Kubernetes 的可移植特性,因为存储资源具有对环境的依赖性——例如 AWS EBS 或者 GCE Persistent Disk。另外,手动绑定还需要根据不同供应商的存储方案修改 YAML 文件。


在资源分配方面,静态配置实际上也违背了 Kubernetes 的设计原则。后者的 CPU 与内存并非事先被分配好绑定在 Pod 或者容器上,而是以被动态形式进行分配。


动态分配则依靠存储类来实现。集群管理员不需要预先手动创建持久卷,而是创建类似于模板的文件。当开发人员制作持久卷声明时,只需要根据实际需求创建一套模板并附加至 Pod 即可。



通过简单的说明,相信大家已经了解了原生 Kubernetes 对外部存储资源的使用方式。当然,这里仅仅做出概括,实际使用场景中还有更多其它因素需要考量。


CSI——容器存储接口


下面来看容器存储接口(简称 CSI)。CSI 是由 CNCF 存储工作组创建的统一标准,旨在定义一个标准的容器存储接口,从而使存储驱动程序能够在任意容器架构下正常起效。


CSI 规范目前已经在 Kubernetes 中得到普及,大量驱动插件被预先部署在 Kubernetes 集群内供开发人员使用。如此一来,我们就可以利用 Kubernetes 上的 CSI 卷来访问与 CSI 兼容的开放存储卷。


CSI 的引入,意味着存储资源能够作为 Kubernetes 集群上的另一种工作负载实现容器化以及部署。


相关开源项目


目前,围绕云原生技术涌现出大量工具与项目。但作为生产场景中的一大突出问题,我们往往很难在云原生架构中选择最合适的开源项目。换言之,解决方案选项太多,反而令存储需求变得更难解决。


我们再看一次 CNCF 列出的云原生存储的可选方案:



下面我会分享一下当下流行的存储方案 Ceph 与 Rook,还有 Rancher 开源的容器化分布式存储 Longhorn。


Ceph


Ceph 是一种动态托管、横向扩展的分布式存储集群。Ceph 面向存储资源提供一种逻辑抽象机制,其设计理念包括无单点故障、自管理以及软件定义等特性。Ceph 可以面向同一套存储集群分别提供块存储、对象存储以及文件存储的对应接口。


Ceph 架构相当复杂的,其中使用到大量的底层技术,例如 RADOS、librados、RADOSGW、RDB、CRUSH 算法,外加 monitor、OSD 以及 MDS 等功能性组件。这里我们先不谈它的底层架构,关键在于 Ceph 属于一种分布式存储集群,这使得扩展更便利、能够在不牺牲性能的前提下消除单点故障,且提供涵盖对象存储、块存储以及文件存储的统一存储体系。


很明显,Ceph 与云原生环境彼此兼容的,我们也可以利用多种方法部署一套 Ceph 集群,譬如使用 Ansible。我们可以部署一套 Ceph 集群,并使用 CSI 与持久卷声明来提供指向 Kubernetes 集群的接口。



Ceph 架构图


Rook


另一个有趣且颇具人气的项目是 Rook,这是一项旨在将 Kubernetes 与 Ceph 融合起来的技术方案。从本质上讲,它将计算节点和存储节点放进了同一个集群当中。


Rook 是一种云原生编排器,并对 Kubernetes 做出扩展。Rook 允许用户将 Ceph 放置在容器内,同时提供卷管理逻辑以立足 Kubernetes 之上实现 Ceph 的可靠运行。Rook 还使本应由集群管理员操作的多种任务完成了自动化实现,其中包括部署、引导、配置、扩展以及负载均衡等等。


Rook 可以像 Kubernetes 一样使用 yaml 文件来部署 Ceph 集群。这种文件以高级声明的形式存在,负责为集群管理员提供所需要的全部内容。


Rook 在集群启动完成后,即开始进行实时监控。Rook 将以操作端或者控制端的姿态确保 yaml 文件中所声明的状态始终正常。Rook 运行在一套协调的逻辑循环中,该循环将观察运行状态并根据检测到的异常采取响应。


Rook 自身不具备持久状态,也不需要单独管理。这,才是真正与 Kubernetes 设计原则相符的存储资源管理方案。



Rook 凭借着将 Ceph 与 Kubernetes 协同起来的强大能力而颇受欢迎,在 GitHub 上获得近 4000 颗星,1600 多万次的下载,并吸引到 100 多名贡献者,现已进入 CNCF 孵化阶段。


Longhorn


Longhorn项目是 Rancher Labs 推出的开源的基于云和容器部署的分布式块存储新方式。Longhorn 遵循微服务的原则,利用容器将小型独立组件构建为分布式块存储,并使用容器编排来协调这些组件,形成弹性分布式系统。


如今,基于云和容器的部署规模日益扩大,分布式块存储系统也正变得越来越复杂,单个存储控制器上的 volume 数量在不断增加。2000 年代初,存储控制器上的 volume 数量只有几十个,但现代云环境却需要数万到数百万的分布式块存储卷。存储控制器变成了高度复杂的分布式系统。


Longhorn 充分利用了近年来关于 如何编排大量的容器和虚拟机的核心技术 。例如,Longhorn 并没有构建一个可以扩展到 100,000 个 volume 的高度复杂的控制器,而是出于让存储控制器简单轻便的考虑,创建了 100,000 个单独的控制器。然后,我们可以利用像 Kubernetes 这样的最先进的编排系统来调度这些独立的控制器,共享一组磁盘中的资源,协同工作,形成一个弹性的分布式块存储系统。


Longhorn 基于微服务的设计还有很多其他优势。因为每个 volume 都有自己的控制器,在升级每个 volume 的控制器和 replica 容器时,是不会导致 IO 操作明显的中断的。Longhorn 可以创建一个长期运行的工作来编排所有 live volume 的升级,同时确保不会中断系统正在进行的操作。为确保升级不会导致意外的问题,Longhorn 可以选择升级一小部分 volume,并在升级过程中出现问题时回滚到旧版本。这些做法在现代微服务应用中已得到广泛应用,但在存储系统中并不常见。希望 Longhorn 可以 助力于微服务在存储领域的更多应用。


结语


对于实际应用层面出现的任何问题,最重要的自然是判断需求、设计系统或者选择适当的工具。同样的道理也适用于云原生环境。虽然具体问题非常复杂,但也必然会出现大量工具方案尝试解决。随着云原生世界的持续发展,我们可以肯定,新的解决方案将不断涌现。未来,一切都会更加美好!


原文链接:

https://softwareengineeringdaily.com/2019/01/11/why-is-storage-on-kubernetes-is-so-hard/


2020 年 5 月 14 日 22:26278

评论

发布
暂无评论
发现更多内容

团队与领导力健康检查 | 体检表

Bob Jiang

团队建设

避免争执

孙苏勇

职场 随笔杂谈

机器学习项目是如何开发和部署的?

陆道峰

人工智能 学习

《中国互联网简史》系列笔记之P2P

dongh11

读书笔记

MySQL死锁系列-常见加锁场景分析

程序员历小冰

MySQL

时序数据库

pydata

做好领路人——写给技术新人的导师建议

南方

管理 新人

控制 Pod 内容器的启动顺序

张晓辉

Kubernetes

Rust 遇上 C/C++(二):函数传参

Coding Fatty

c c++ rust 编程语言

Eureka 实例注册状态保持 STARTING 的问题排查

张晓辉

spring Spring Cloud netflix

为什么第三方联调应该先行?

大伟

HTML中实现合并单元格

JDoe

html

为什么要学习 Markdown?究竟有什么用?

JackTian

markdown markdown语法 markdown编辑器

ARTS|Week 1 第一次使用LeetCode

Puran

LeetCode ARTS活动

只用CSS实现响应式Full-Width img 2种方法

寇云

CSS css3

写给产品经理的信(5):谈谈项目管理(青铜-王者)

夜来妖

产品 极客时间,项目管理 项目管理 产品经理 项目

前端工程化之创建项目

春生

前端 前端工程 前端架构 全栈工程师

python实现·十大排序算法之基数排序(Radix Sort)

南风以南

Python 排序算法 基数排序

Vol.9 Web前端发展历程及前端工程化

Lanpeng20

前端 前端工程

如何通过样本数据推断其分布

张利东

Python

地铁上看书的老外引发的思考

小天同学

写作 读书 个人感想 日常思考

最香远程开发解决方案!手把手教你配置VS Code远程开发工具,工作效率提升N倍

柠檬橙

Linux 后台开发 vscode 后端

一款开源且具有交互视图界面的实时 Web 日志分析工具!

JackTian

开源 GoAccess 实时 Web 日志分析工具 交互式查看器

不懂送女朋友什么牌子的口红?没关系!Python 数据分析告诉你。

JackTian

Python 程序员 数据分析 python 爬虫 口红

解决版权难题,“豪横”字体自己做

zhoo299

设计 CG

重学 Java 设计模式:实战原型模式

小傅哥

Java 设计模式 小傅哥 复杂代码优化 重构

自定义列表样式

寇云

CSS css3

偏头疼告诉我的,我想告诉每一个人

zkback

纯CSS“返回顶部”特效

寇云

CSS css3

在培训机构花了好几万学Java,当了程序员还常被鄙视,这是招谁惹谁了?

四猿外

Java 学习 程序员 个人成长 转行程序员

认识数据产品经理(四 与互联网产品经理的区别)

马踏飞机747

大数据 互联网 产品经理 职业规划

深挖Kubernetes存储为何如此难及其解决方案-InfoQ