公有云容器化指南:腾讯云TKE实战与应用
上QQ阅读APP看书,第一时间看更新

2.9 Kubernetes的存储

数据存储在存储介质中,了解清楚底层的存储实现方式对于数据的使用、保护以及IO性能的优化有很大的帮助。本节将介绍Kubernetes的存储实现机制。

2.9.1 存储虚拟化介绍

一个好的虚拟化解决方案就像游历一个虚拟现实的主题公园。当游客想象自己正在城市上空滑翔时,传感器就会把相应的感觉传递给游客,同时隐藏真实的力学环境。这好比电影《黑客帝国》中,虚拟世界的人完全感受不到自己是在虚拟的环境中。存储的虚拟化与此类似,上层用户完全不了解底层硬盘、磁带,屏蔽掉底层复杂的物理设备后,把零散的硬件存储资源抽象成一个“存储池”,这个“存储池”能灵活分配给用户。存储池虚拟化如图2-25所示。

图2-25 存储池虚拟化

SNIA(存储网络工业协会,非营利行业组织)对存储虚拟化的定义:通过对存储(子)系统或存储服务的内部功能进行抽象、隐藏或隔离,对应用、服务器、网络等资源进行分离,从而实现这些资源的独立管理。目前这个定义是相对权威和中立的,这里说的“抽象”可以理解为对底层硬件存储资源的共同属性的整合,把所有存储资源抽象成一个虚拟的存储池;“隐藏”的意思是对于上层用户需要屏蔽掉底层的硬件,用户无须关心底层;“隔离”的意思是虚拟的存储池资源需要根据上层用户的需求划分成小块,块与块之间相互独立、相互不影响。

抽象→隐藏→隔离,这三步是存储虚拟化机制要达到的最基本要求,通过这三步能实现设备使用效率提升,实现统一数据管理、设备构件化、数据跨设备流动,提高可扩展性、降低数据管理难度等目的。

1.存储I/O虚拟化

I/O虚拟化是存储虚拟化的基石,I/O虚拟化的质量将直接影响整体存储虚拟化方案的效果。I/O虚拟化和CPU虚拟化一样经历全虚拟、半虚拟、硬件辅助虚拟的过程。全虚拟化模式,全部处理请求要经过VMM,这就让I/O路径变得很长,造成的影响就是性能大大降低。所以,后面出现了半虚拟化I/O技术virtio(Virtual I/O Device)。

virtio是前后端架构,相关请求路径减少了很多,但还是需要经过VMM和Kernel的,因此性能或多或少还是会有损耗。直到英特尔推出了硬件辅助式的VT-D技术,这项技术极大减少了VMM在I/O请求操作中的参与度,让路径变为最短,而且还提供了专门的内存空间处理I/O请求,性能得到了非常大的提升。

2.当前主流存储虚拟化方式

目前存储虚拟化方式主要有3种,分别是基于主机的存储虚拟化、基于网络的存储虚拟化和基于存储设备的存储虚拟化。表2-11所示是这3种存储虚拟化方式优劣对比。

表2-11 3种主流存储虚拟化方式对比

3.存储虚拟化的价值

据统计,存储的需求量年增长率为50%~60%。面对新的技术应用以及不断增加的存储容量,企业用户需要虚拟化技术来降低管理的复杂性,同时提高效率。

据有关报告显示,采用存储虚拟化技术能节省一半的IT成本。但是,从企业对存储掌握的情况来看,很多企业遇到了问题,总结起来有三点:一是存储数据的成本在不断增加;二是数据存储容量爆炸性增长;三是越来越复杂的网络环境使得存储的数据不便管理。

存储虚拟化首先要解决的难题就是不同架构平台的数据管理问题。数据管理没有有效便捷的方法,处理不当会对数据的安全产生很大的威胁。在当前云时代背景下,大部分客户已选择上云(公有云或私有云),这也是让存储走向虚拟化的一个表现。云环境下,公有云厂商有自己很强的存储虚拟化技术体系来支撑用户需求,当前私有云的Ceph和GlusterFS技术也能很好地解决上述问题。

2.9.2 Kubernetes存储机制设计

前面有提到过,企业选择虚拟化技术能大大降低IT成本。Kubernetes是容器资源调度管理平台,因此它也是虚拟化资源的管理平台。下面我们介绍存储虚拟化资源在Kubernetes下是如何运作和管理的。

在传统虚拟机模式下,我们可以分配块存储、文件存储挂载到VM里。同理,在容器Kubernetes模式下,Pod也需要存储资源来实现数据的持久化。在Kubernetes里,存储资源以数据卷的形式与Pod绑定。底层通过块存储和分布式文件系统来提供数据卷,而块存储和分布式文件系统在2.9.1节提到过,这些需要更底层的存储虚拟化机制来实现,如图2-26所示。

图2-26 Kubernetes存储虚拟化机制

那么,Kubernetes到底是通过什么机制把底层块存储或分布式文件系统做成一份份的数据卷给Pod使用的呢?接下来我们通过PV、PVC、StorageClass等概念进行说明。

1.PV

PV(Persistent Volume,持久化的数据卷)是对底层共享存储资源的抽象,它能对接多种类型的存储实现,主要有Ceph、GlusterFS、NFS、vSphereVolume(VMware存储系统)、Local(本地存储设备)、HostPath(宿主机目录)、iSCSI、FC(光纤存储设备)、AWSElasticBlockStore(AWS弹性块设备)、AzureDisk(微软云Disk)、AzureFile(微软云File)、GCEPersistentDisk(谷歌云永久磁盘)。PV是Kubernetes存储能力、访问模式、存储类型、回收策略、后端存储类型等机制的体现,下面我们定义一个PV。


apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003                                    # 定义PV的名字
spec:
capacity:
    storage: 5Gi                        # 定义了PV为5Gi
volumeMode: Filesystem                  # 定义volume模式类型
accessModes:
    - ReadWriteOnce                     # 定义读写权限,并且只能被单个节点挂载
persistentVolumeReclaimPolicy: Recycle  # 定义回收策略
storageClassName: slow                  # 定义storageClass名字
mountOptions:
    - hard                              # 定义NFS挂载模式,硬挂载
    - nfsvers=4.1                               # 定义NFS的版本号
nfs:
    path: /tmp                          # 定义NFS挂载目录
    server: 172.17.0.2                  # 定义NFS服务地址

第一次写PV的YAML可能不清楚到底有哪些关键参数,表2-12整理了PV的关键配置参数供大家参考。

表2-12 PV YAML参数

每种存储类型支持的访问模式是不同的,如表2-13所示,通过“depends on the driver”后边的信息可以看到不支持的访问模式,这取决于具体的驱动能力。

表2-13 多存储类型的访问模式

另外,也需要关注PV的生命周期,可用于问题排障,查看相关PV的状态,如表2-14所示。

表2-14 PV状态

2.PVC

PVC(Persistent Volume Claim)相比PV多了一个Claim(声明、索要、申请)。PVC是在PV基础上进行资源申请。那么有了PV为何还要用PVC呢?因为PV一般是由运维人员设定和维护的,PVC则是由上层Kubernetes用户根据存储需求向PV侧申请的,我们可以联想Linux下的LVM,Kubernetes里的PV好比LVM的物理卷,Kubernetes里的PVC好比LVM里的逻辑卷。LVM逻辑架构如图2-27所示。

PV与PVC的逻辑关系如图2-28所示。

PVC的申请也是配置YAML,举例如下。

图2-27 LVM逻辑架构

图2-28 PV与PVC的逻辑关系


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: myclaim              # 设置PVC的名字
spec:
    accessModes:
        - ReadWriteOnce        # 设置访问模式
    volumeMode: Filesystem     # 定义volume模式类型
    resources:
        requests:
            storage: 8Gi       # 设置PVC的空间大小
    storageClassName: slow     # 设置存储类别为slow,注意PVC这里一般和storageClass结合
    selector:
        matchLabels:
            release: "stable"  # 匹配标签stable
        matchExpressions:
            -{key: environment, operator: In, values: [dev]}  
              #同时包含environment环境有[dev]的标签

PVC是用户设置存储空间、访问模式、PV选择、存储类别等信息的机制,它的YAML关键参数如表2-15所示。

表2-15 PVC YAML关键参数

PVC目前一般会跟StorageClass结合使用,关于StorageClass的功能,具体请看下面的介绍。

3.StorageClass

在Kubernetes里,存储资源的供给分为两种模式:静态模式和动态模式。静态模式是Kubernetes集群管理员(一般是运维人员)手工创建和设置好后端存储特性的PV,然后PVC再申请使用。动态模式下集群管理员无须手工创建和设置PV,集群管理将定义好不同类型的StorageClass,StorageClass及时与后端存储类型做关联;待用户创建PVC后,系统将自动完成PV的创建和PVC的绑定。

在自动化发展日趋成熟的今天,人工操作逐渐被自动化手段替代,静态模式可以应用在集群规模小、架构简单的测试环境中,但是面对规模宏大、架构复杂的环境,就需要采用动态的管理方式。

下面定义一个StorageClass的YAML文件。


apiVersion: storage.Kubernetes.io/v1
kind: StorageClass
metadata:
    name: standard                   # 定义StorageClass的名字为standard
provisioner: kubernetes.io/aws-ebs   # 定义后端存储驱动,这里用的是AWS的ebs盘
parameters:
    type: gp2                   # aws的磁盘有5种类型,gp2是其中一种,这里定义的类型是gp2
reclaimPolicy: Retain           # 设置PV的数据回收策略,默认DELETE,这里设置的是
 Retain(保留,Kubernetes 1.8版以后才支持)
allowVolumeExpansion: true      # 设置只有从StorageClass中创建的PVC才允许使用卷扩展
mountOptions:
    - debug
volumeBindingMode: Immediate    # 设置何时进行卷绑定和动态预配置

集群管理员预先定义好StorageClass,后面创建PVC的时候,有符合条件的StorageClass将自动创建好PV与PVC绑定使用。StorageClass的YAML关键参数是Provisioner和Parameters。Provisioner是Kubernetes底层存储资源的提供者,其实就是后端存储的类型。定义的时候需要以kubernetes.io开头,后面接上存储类型。Parameters是后端存储类型的具体参数设置,不同的存储类型参数是不一样的。

StorageClass YAML文件Parameters参数的定义比较复杂,想清楚了解具体怎么设置,比如GlusterFS、Ceph RBD、OpenStack Cinder的StorageClass是怎样的,可以参考官方文档的YAML例子。

4.PV、PVC、StorageClass之间关系

前面我们详细了解了PV、PVC、StorageClass的相关信息,下面通过几张图从高维度来整体认识三者之间的关系。

首先,我们可以通过图2-29清晰地了解它们之间相互依赖的关系。

图2-29 PV、PVC、StorageClass逻辑关系

然后,我们通过图2-30来进一步直观地理解它们总体的架构层次关系。

图2-30 PV、PVC、StorageClass架构层次关系

最后是它们的生命周期,如图2-31所示,管理员创建StorageClass后会去寻找合适的PV,接着PVC会与PV绑定,分配给Pod使用。如果Pod不再使用,会释放PVC,最终删除PVC,PV解绑回归待绑定闲时状态。

只要掌握了StorageClass、PVC、PV的定义和设置,清楚它们之间的内在关系和生命周期,对于Kubernetes存储的知识就有了基本的了解。当然,对于一些性能上的优化,具体还要看底层存储的能力。当前云环境下,底层存储各具特色,各大云厂商都有自己的实现机制和性能特色;私有云下,在完善底层硬件性能的同时,通常IaaS层都会采用Ceph来做分布式存储,进而再给PaaS层使用。

图2-31 PV生命周期

2.9.3 Kubernetes CSI

2.8节我们学习Kubernetes网络的时候了解过CNI,那么在存储方面,Kubernetes也有一套接口管理规范机制,也就是CSI(Container Storage Interface,容器存储接口)。CNI是用来统一网络规范接口的,CSI自然是想统一标准化存储方面的接口,方便管理。

1.为什么要发展CSI

CSI 1.0版本是在2017年12月发布的。在没有CSI之前,Kubernetes已经提供了功能强大的卷插件机制(In-tree Volume Plugin和Out-of-tree Provisioner),但由于In-tree模式的代码主要是Kubernetes维护,意味着插件的代码是Kubernetes核心代码的一部分,并会随核心Kubernetes二进制文件一起发布。

此外,第三方插件代码在核心Kubernetes二进制文件中可能会引起可靠性和安全性的问题,由于代码的审核和测试是Kubernetes侧人员做的,有些错误是很难发现的。因此,CSI的出现非常有必要。CSI的设计目的是定义一个行业标准,该标准将使第三方存储提供商能够自己实现、维护和部署他们的存储插件。

借助CSI,第三方存储提供商无须接触Kubernetes的核心代码,这为Kubernetes用户提供了更多的存储选项,并使系统更加安全可靠。

Kubernetes集群在没有CSI的标准下,架构如图2-32所示。

2.CSI架构

CSI目前包括三部分:Identity、Controller和node。

●CSI Identity的主要功能是认证插件的状态信息。

●CSI Controller的主要功能是对存储资源和存储卷进行管理和操作。

●CSI node的主要功能是对节点上的volume进行管理和操作。

图2-32 没有CSI标准的Kubernetes集群架构

Kubernetes与CSI的关系如图2-33所示。

图2-33 Kubernetes与CSI的关系

3.CSI新特性

CSI的GA版本正式发布了,有如下几个功能的改进。

1)Kubernetes当前最新版本与CSI 1.0和0.3版本兼容。CSI 0.1到3.0之间有重大变化,但是Kubernetes 1.13同时支持两个版本,因此其中任何一个版本都可以与Kubernetes 1.13一起使用。请注意,随着CSI 01.0 API的发布,Kubernetes不再支持0.3及以下版本的CSI API驱动程序,Kubernetes 1.15后则完全不支持了;CSI 0.2和0.3之间没有重大变化,因此0.2驱动程序可以和Kubernetes 1.10.0以上版本联合使用。另外,在使用Kubernetes 1.10.0之前的版本时,必须将老版本的CSI 0.1驱动程序更新为至少兼容CSI 0.2。

2)Kubernetes VolumeAttachment对象已添加到storage v1 group v1.13中。

3)Kubernetes CSIPersistentVolumeSource卷类型已提升为GA。

4)“kubelet设备插件注册机制”(发现新的CSI驱动程序机制方法),已在Kubernetes 1.13的GA中。

本节主要介绍了Kubernetes存储机制和Kubernetes CSI,存储不管是在哪个IT时代都需要得到高度重视,只有重视存储才能让数据得到更好的输入和读取,当然,数据的安全性也是需要高度重视的。