Carina 是由博云主导并发起的云原生本地存储项目(GitHub 地址为:https://github.com/carina-io/...),目前已经进入 CNCF 全景图。
Carina 旨在为云原生环境中的有状态应用提供高性能、免运维的本地存储解决方案,具体存储卷生命周期管理、本地设备管理、智能调度等能力。Carina 作为博云容器云平台的组件之一,已经在多个金融机构的生产环境中稳定运行多年。
一、Carina 系列文章 - 前言
本篇是 Carina 系列文章的开篇,在该系列文章中我们将全面地展示本地存储 Carina 项目的功能设计、功能使用及其实现细节等内容。在 Carina 系列文章中将包含如下章节功能(排名不分先后):Carina整体功能介绍、Carina存储卷创建及扩容、Carina存储卷挂载与扩容 、设备注册与节点资源管理、基于K8S的调度器扩展、Carina自动管理Raid使用及原理分析、Carina结合velero实现存储备份恢复、smart感知使用及原理、基于cgroup v1和cgroup v2的设备限速、基于磁盘IO的调度等等。
Carina 是基于 K8S CSI 实现的一个本地存储插件,在本篇文章中我们将首先简要介绍一下 Carina 项目的根基容器存储接口(CSI),以及为什么我们需要本地存储本地存储诞生的契机,在之后我们将展示 Carina 项目架构设计等内容。
二、容器存储接口(CSI)
1. CSI 是什么
CSI 是Container Storage Interface(容器存储接口)的简写,CSI 存在的目的便是定义存储行业标准,使供应商(SP)能够开发一个符合 CSI 标准的插件,在多容器编排系统中方便的提供存储。
Kubernetes 将通过 CSI 接口与云存储厂商进行通信,进行卷的创建、挂载等管理操作,从而实现容器使用持久存储卷的需求。
2. 为什么要有 CSI
在没有 CSI 之前 Kubernetes 已经内置了强大的存储插件系统,但是这样的存储插件是 Kubernetes 代码的一部分,要跟随 Kubernetes 的发布而更新,这样就存在一些问题,如果云存储厂商发现有些问题需要修复或者优化,云存储厂商无法及时修复而单独发布版本其必须与 Kubernetes 一块发布,这样对于 K8S 和云存储厂商而言形成了相互依赖相互制约的关系,不利于双方快速迭代,另外云存储厂商的代码与 Kubernetes 代码高度耦合在一起,还会引起安全性、可靠性问题,这增加了 Kubernetes 代码的复杂度以及后续的维护成本等。
基于以上问题 Kubernetes 将存储系统抽象出了一组外部存储接口即 CSI,Kubernetes 通过 Grpc 接口与云存储厂商的 CSI 驱动服务进行通信,这样一来对于云存储厂商来说,可以单独发布和部署自己的存储插件,正常的迭代开发,无需接触 Kubernetes 核心代码,降低了开发的复杂度;同时对于 Kubernetes 来说,这样不仅降低了维护成本,还能为用户提供更多的存储选项。
3. CSI 系统架构
这是一张简要的 CSI 系统架构图:
首先 Kubernetes 官方为 CSI 提供了一些辅助服务 external-provisioner、external-attacher、external-resizer、external-snapshotter、node-driver-register、livenessprobe等,通过这些辅助组件 CSI 驱动开发者只需通过实现 CSI 接口和云厂商存储服务通信的内容,便可以方便的开发一个 K8S 存储插件。
三、本地存储诞生的契机
1. 中间件上云的困境
Kubernetes CSI 插件机制日趋成熟,各个分布式存储服务分别开源了自己的存储插件比如:ceph-csi、nfs-csi。这些网络存储插件极大地扩展了 Kubernetes 的能力,在过去几年的 K8S 发展中起着至关重要的作用,分布式网络存储系统在可扩展性、数据安全等方面有着巨大的优势,在通用存储领域发挥了很大的作用。但是,对于极高的 IOPS、极低延迟的数据库等中间件领域,网络存储有其天然的劣势。因此,推出一款延迟极低的开源 CSI 对数据库类服务就至关重要。
Kubernetes 已经稳定运行数年之久,主要应用场景一直是无状态服务以及对磁盘 IO 不敏感的业务服务,随着客户对云平台深入使用,希望一些中间件服务也能搬迁到云上,对于中间件服务来说有各种开源的 operator 促使其在 K8S 中稳定运行,但是中间件服务对磁盘 IO 具有非常高的要求,网络存储服务受到很大的挑战。
Kubernetes 集群运行节点主要使用了 CPU、Memory 等资源,对本地磁盘并未有精细的使用,在一定程度上造成了本地资源的浪费。
对于网络存储来说多个副本是一种基本功能,但是在中间件场景下,比如 Mysql 本身主从三副本,在网络存储下就变成了九份副本,也造成了存储资源的冗余。
2. 本地存储需求
由上可知,我们迫切地需要一款本地存储产品能解决上述困境,我们对该项目的需求如下,
1) 能够提供基于本地磁盘的高性能存储设备。
2) 符合 CSI 规范,与其他网络存储插件使用方式完全一致。
3) 能够十分简易的部署,自动管理本地磁盘,使用户几乎无需进行维护。
4) 提供丰富的文档资料及运行日志,能十分轻易的进行功能使用及异常问题排查。
5) 能够支持存储卷的备份恢复,支持 RAID 管理、磁盘寿命监控等。
四、本地存储 Carina 设计
1. 基本的 CSI 功能
该列表展示的是一个 CSI 存储插件的基本功能,在早期设计中 Carina 需要实现的基本功能,当然经过多轮迭代的 Carina 已经有了更丰富多元的功能:
2. 整体架构图
共有三个组件:
Carina Controller:负责监听 pvc 的创建,并且通知 Carina Node 创建存储卷。
Carina Node:负责维护本地设备,并且执行创建存储卷命令、挂载卷到容器命令等。
Carina Scheduler:K8S 调度器的扩展,增加基于本地存储的调度插件。
3. 节点服务
该图描述了 Carina Node 的工作过程,自动维护本地磁盘设备并组建存储卷组,将节点容量信息注册到 Kubernetes Node,Kubelet 通过 grpc 调用将存储卷挂载到指定目录。
4. 整体运行流程
五、过去、现在与未来
笔者在书写这篇文章时,Carina 项目自 2020 年启动,并于 2021 年 10 月份开源,目前已经过数轮迭代。本篇文章从标准的容器接口 CSI、谈到本地存储需求的诞生以及早期 Carina 的设计,在早期的设计中除了基本的 CSI 功能外,我们期望它能够做到简易部署、免运维、占用极低的资源量等。
现在的 Carina 项目实际功能已经经过多轮版本迭代,增加了更加丰富多元的功能,比如设备多级缓存、设备限速等功能,随着版本迭代我们也使用可配置的存储卷代替了自动组建 SSD/HDD 卷组的功能、使用 NodeStorageResource 代替了节点注册功能、当然还有其他更多特性开发中。
在接下来的文章中,我们将首先罗列现有的 Carina 功能,正在开发中的、已经加入开发计划中的功能,然后再在展开逐个功能点进行详细的使用介绍及原理分析等。