PaaS中OpenShift持久化存储的管理实践

在 OpenShift 中,Pod 会被经常性的创建和销毁,也会在不同的主机之间快速的迁移。为了保证容器在重启或者迁移以后能够使用原来的数据,就必须使用持久化存储。所以,持久化存储的管理对于 PaaS 平台来说就显得非常重要。

1

   

OpenShift 存储 PV 和 PVC

OpenShift 利用 Kubernetes Persistent Volume 概念来管理存储。管理员可以快速划分卷提供给容器使用。开发人员通过命令行和界面申请使用存储,而不必关心后端存储的具体类型和工作机制。

Persistent Volume(PV)是一个开放的存储管理框架,提供各种不同类型存储的支持。OpenShift 默认支持 NFS、GlusterFS、Cinder、Ceph、EBS、iSCSI 和 Fibre Channel 等存储,用户还可以根据需求对 PV 框架进行扩展,从而使其支持更多类型的存储。

PersistentVolumeClaim (PVC) 是用户的一个 Volume 请求。用户通过创建 PVC 消费 PV 的资源。

PV 只有被 PVC 绑定后才能被 Pod 挂载使用,PV 和 PVC 的生命周期如下图 2-72 所示:

686a89a84724d8466e90184d6aded411.png

图2-72 PV和PVC的生命周期

从图中可以看到,生命周期包含5个阶段:

  • Avaliable:这个阶段表示PV创建完成,处于可用状态。创建PV可以通过手动创建或动态创建。

  • Pending:这个阶段表示PV和PVC处于匹配状态,匹配的策略有访问模式和卷大小,以及支持通过label匹配。如果无法匹配则PVC会一直处于Pending状态,如果可以匹配,但是后端存储置备卷失败,则会转为Failure状态。

  • Bound:这个阶段表示PV和PVC已经处于绑定状态,这个状态的PVC才能被Pod挂载使用。

  • Release:这个阶段表示挂载PVC的Pod被删除,PVC处于释放状态,也就是未被任何Pod挂载,但这个状态的PV无法被PVC再次绑定。

  • Retain:这个阶段表示删除PVC,PV转变为回收状态,该状态下的PV无法直接被新的PVC绑定。回收状态下PV是否保留数据取决于PV的回收策略定义,默认会保留。如果想要将改状态的PV转变为Avaliable,必须删除PV然后重新创建。

在PV和PVC的生命周明中,最关键的两个阶段是创建和绑定。PV按创建方式的不同可分为动态PV和静态PV。静态PV指通过手动创建的PV,而动态卷是指由StorageClass(简称SC)自动创建PV。

静态PV需要手动编辑Yaml文件并应用到集群中,不同的存储后端,PV的配置参数不同,如NFS后端的PV示例内容如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv0001
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteOnce
  nfs:
    path: /data/mydb
    server: xxx.xxx.xxx.xxx
  persistentVolumeReclaimPolicy: Retain

其中访问模式和PV容量对能否和PVC绑定至关重要。PV支持的访问模式共有三种,如下表2-8所示:

表2-8 PV访问模式

访问模式

简写

描述

ReadWriteOnce

RWO

PV可以由单个Pod以读写方式挂载。

ReadOnlyMany

ROX

PV可以由多个Pod以只读方式挂载。

ReadWriteMany

RWX

PV可以由多个Pod以读写方式挂载。

对于不同后端存储对访问模式的支持是不同的。接下来我们看一下常见后端存储支持的PV访问模式,如下表2-9所示:

表2-9 不同存储后端支持的访问模式

Volume Plug-in

ReadWriteOnce

ReadOnlyMany

ReadWriteMany

AWS EBS

Yes

No

No

Azure File

Yes

Yes

Yes

Azure Disk

Yes

No

No

Cinder

Yes

No

No

Fibre Channel

Yes

Yes

No

GCE Persistent Disk

Yes

No

No

HostPath

Yes

No

No

iSCSI

Yes

Yes

No

LocalVolume

Yes

No

No

NFS

Yes

Yes

Yes

VMware vSphere

Yes

No

No

从上表中,我们可以看到,Azure File和NFS支持的读写类型是最全的。我们可以使用NAS或者配置NFS Server。当然,企业级NAS的性能要比NFS Server好得多。在OpenShift中,除了上表列出常见存储类型之外,还可以选择软件定义存储,如Ceph,Ceph可以同时提供块存储RBD、对象存储、文件系统存储CephFS。

除了静态PV之外,OpenShift还可以使用StorageClass来管理动态PV。每个StorageClass都定义一个Provisioner属性,也就是后端存储类型。OpenShift安装后,会内嵌一些Provisioner,它们的StorageClass会被自动创建,如下表所示:

Volume Plug-in

Internal Provisioner

Storage Class Provisioner Value

AWS EBS

Yes

kubernetes.io/aws-ebs

Azure File

Yes

kubernetes.io/azure-file

Azure Disk

Yes

kubernetes.io/azure-disk

Cinder

Yes

kubernetes.io/cinder

Fibre Channel

No

GCE Persistent Disk

Yes

kubernetes.io/gce-pd

HostPath

No

iSCSI

No

LocalVolume

No

NFS

No

VMware vSphere

Yes

kubernetes.io/vsphere-volume

如果要创建一个没有对应 Provisioner的StorageClass,也称为静态StorageClass,可以使用kubernetes.io/no-provisioner,示例如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: static-provisioner
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

StorageClass创建之后,就可以通过创建PVC触发StorageClass完成PV的创建。但是,静态StorageClass除外,因为静态StorageClass没有真实的后端存储,依然需要手动创建PV并明确指定storageClassName为静态StorageClass的名称,详细的使用案例参见第三章3.2.4-2小节。

无论是通过静态还是动态创建PV,只有PVC和PV绑定之后才能被Pod使用。尤其在集群中有多个不同的后端的PV,PVC如何能绑定到满足预期的PV将成为关键,下面我们就进行详细说明。

2

   

PV 和 PVC 绑定逻辑

在上一小节中,我们介绍了 PV 的创建方式和支持的类型,那么如果一个集群中,既有多种类型的 StorageClass,又有多种不同后端的静态 PV,PVC 与 PV 的匹配遵循一定的逻辑,如下图 2-73 所示:


958a5922f1e64c6c5d0f0f2e808c0ffd.png

图2-73 PV和PVC匹配逻辑

从图中可以看出动态卷优先,如果动态卷无法满足PVC需求,才会匹配静态PV。而且能否匹配成功是根据PV、PVC、集群中StorageClass的配置等多方面决定的,匹配大致逻辑如下:

1. 创建PVC后,首先会判定PVC中是否指定了storageClassName字段,例如下面PVC定义会触发StorageClass gp2创建的PV并绑定(静态StorageClass需要手动创建PV,后文不再重复强调),如果无法找到指定的StorageClass,则PVC处于Pending状态:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-claim
spec:
storageClassName: gp2
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi

2. 如果PVC中没有指定storageClassName参数,则会判定集群中是否有默认StorageClass,如果存在,则会直接使用默认StorageClass创建PV。一个集群最多只能有一个默认StorageClass,表示如果PVC中未指定明确的storageClassName,则使用默认StorageClass创建PV。使用如下命令将集群中一个SC设置为默认StorageClass:

# oc annotate storageclass <SC_NAME> "storageclass.kubernetes.io/is-default-class=true"

建议不要设置静态StorageClass为默认StorageClass,因为静态StorageClass不会自动创建PV,即使设定为默认StorageClass,还是要手动创建设定storageClassName的PV,导致设定为默认StorageClass没有价值。

3. 如果集群未定义默认StorageClass,则会进入静态PV匹配。首先会判定在PVC是否定义了selector用于匹配特定标签的PV。通常在PV上设定标签主要用于对PV分级,比如根据存储性能,存储地理位置等。例如下面的PVC就只能匹配包含storage-tier=gold且volume-type=ssd的PV,如果无法找到符合标签的PV则PVC处于Pending状态。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: high-performance-volume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
selector:
matchLabels:
storage-tier: gold
volume-type: ssd

4. 如果PVC中未定义selector,或者有满足selector的PV,则根据PVC和PV两者中定义的访问模式和容量大小匹配。其中访问模式必须完全相同,而容量是只要PV定义的容量大小大于等于PVC定义的容量大小就可以匹配成功。如果访问模式或者容量大小无法满足需要,则PVC处于Pending状态。

可以发现,在动态卷绑定时只判断storageClassName,而在静态PV绑定时才会判断selector、访问模式、容量大小。

另外,需要注意的是,访问模式和容量大小的匹配只是逻辑上的,并不会校验后端存储是否支持这种访问模式或后端存储的真实空间大小。例如我们完全可以通过多读写访问模式挂载iSCSI卷,只不过由于锁机制,无法同时启动多个实例。

3

   

容器云原生存储

OpenShift 目前主推 OpenShift Container Storage(简称 OCS)实现存储层。OCS 主要是通过 Rook+Ceph 实现的。

Rook(https://rook.io/)使 Ceph 部署、引导、配置、供应、扩展、升级、迁移、灾难恢复、监视和资源管理自动化。Operator 将启动和监视 Ceph ( https://rook.io/)使 Ceph 部署、引导、配置、供应、扩展、升级、迁移、灾难恢复、监视和资源管理自动化。Operator 将启动和监视 Ceph ) Monitor 容器,提供 RADOS 存储的 Ceph OSD 守护程序,以及启动和管理其他 Ceph 守护程序。通过初始化 Pod 和运行服务所需的其他工件来管理存储池,对象存储(S3 / Swift)和文件系统的 CRD。

Rook的功能如下:

  • 高可用性和弹性-Ceph没有单点故障(SPOF),并且其所有组件都以高可用性的方式本地工作

  • 数据保护-Ceph会定期清理不一致的对象,并在必要时进行修复,以确保副本始终保持一致

  • 跨混合云的一致存储平台-Ceph可以部署在任何位置(内部部署或裸机),因此无论用户身在何处,都能提供类似的体验

  • 块,文件和对象存储服务-Ceph可以通过多个存储接口公开您的数据,从而解决所有应用程序用例

  • 放大/缩小-Operator完全负责添加和删除存储。

  • 仪表板-Operator部署了一个仪表板,用于监视和自检群集。

OCS的架构图如下图2-74所示:

f477bfdc46a8251af7da90fbe6536382.png

图2-74 OCS存储架构

OCS通过Operator方式进行安装。目前支持在OpenShift物理节点上离线安装。

OCS的安装很简单,大致步骤如下图2-75所示,安装OCS的Operator:

70e418e73d04d93c5dff3fc983b57983.png

图2-75安装OCS的Operator

接下来,利用OCS Operator部署的API创建Ceph集群,选择加入到OCS的节点。此处我们选择新添加的三个节点:如下图2-76所示:

17d67287a24d7426e19b8f3a19ab9a98.png

图2-76 选择OCS节点

当OCS相关所有Pod都创建成功并处于Running状态,代表OCS部署成功。OCS部署成功后,我们查看OpenShift中的StorageClass,增加了Ceph相关的内容:

# oc get sc

NAME                          PROVISIONER                             AGE
localblock                    kubernetes.io/no-provisioner            51m
ocs-storagecluster-ceph-rbd   openshift-storage.rbd.csi.ceph.com      51m
ocs-storagecluster-cephfs     openshift-storage.cephfs.csi.ceph.com   51m
openshift-storage.noobaa.io   openshift-storage.noobaa.io/obc         45m

部署成功后,就可以在OpenShift中通过CSI的方式调用OCS了。

我们使用配置文件创建一个PVC(调用storageClassName: ocs-storagecluster-ceph-rbd):

# cat create_ns_ocs_pvc.yaml

---
kind: Namespace
apiVersion: v1
metadata:
name: "e-library"
labels:
name: "e-library"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ocs-pv-claim
labels:
name: "e-library"
namespace: "e-library"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: ocs-storagecluster-ceph-rbd

查看PVC创建成功,并且OCS自动创建PV与之绑定。

# oc get pvc

NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS  AGE
ocs-pv-claim   Bound    pvc-f06484c8-abd7-11ea-b311-0242ac110022   10Gi       RWO            ocs-storagecluster-ceph-rbd  3m52s

接下来,我们就可以创建Pod来消费这个PVC了。

在OCS早期版本,只支持内置模式,也是就说,必须把OCS装在OpenShift上,利用OpenShift的Worker Node的本地存储空间做存储空间。这种模式部署、使用都很方便。唯一的问题是:存储服务器无法与OpenShift集群解耦。

OCS 从v4.5版本开始支持外部的存储模式。也就是说,通过OpenShift上安装的OCS Operator,可以对接在外部物理机上安装的Ceph。然后以OpenShift中Rook的方式管理外部物理机上的Ceph,实现存储服务器与OpenShift集群解耦。

我们在OpenShift上部署OCS Operator后,可以选择连接外部的Cluster:然后提示下载Python脚本。将这个脚本在外置的Ceph集群的任意一个Monitor节点上执行,获取到Ceph集群信息,输入到OCS对接外部存储的位置,如下图2-77所示:

7fb4dec9d623f7e33067d070b48325de.png

图2-77 OCS对接外置存储

我们将这个脚本在外置的ceph的mon的节点上执行:

首先查看脚本的使用帮助:

#python ceph-external-cluster-details-exporter.py --help

在下面的命令中,rbd-data-pool-name指定要创建的pool的名称;rgw-endpoint指定Ceph集群对象网关地址:

#python ceph-external-cluster-details-exporter.py --rbd-data-pool-name abc --rgw-endpoint 192.168.18.203:8080

命令执行后,会以json的方式返回一大串输出结果,我们将结果粘贴到如到上图2-77的所示的空白处,即可完成添加。由于后续的操作步骤与内置模式类似,因此不再展开说明。

OCS对接外置Ceph存储的后续步骤,请参考repo中“ocs外置存储方式”。

4

   

OpenShift/kubernetes 存储趋势

在 OpenShift 的网络部分,我们提到了一个开源项目 CNI。它定义网络插件和容器之间的通用接口,实现了容器运行时与 SDN 的松耦合。那么,在容器存储方面,有没有类似的开源项目呢?

开源项目 Container Storage Interface(CSI)正是这个目的。CSI旨在提供一种标准,将任意块存储和文件存储在符合这种标准的情况下,可以为Kubernetes上的容器化提供持久存储。随着CSI的采用,Kubernetes存储层变得真正可扩展。使用CSI,第三方存储提供商可以编写和部署插件,在Kubernetes中公开新的存储系统,而无需触及核心Kubernetes代码。CSI为Kubernetes用户提供了更多存储选项,使系统更加安全可靠。目前在OpenShift中的CSI正式GA。

CSI是通过External CSI Controllers实现的,它是一个运行在Infra节点包含三个容器的Pod。如下图2-78所示:

  • external CSI attacher container:它将从OpenShift发过来的attach 和detach调用转换为对CSI driver的ControllerPublish和ControllerUnpublish调用。

  • external CSI provisioner container,它将从OpenShift发过来的provision 和 delete的调用转化为对CSI Driver的CreateVolume 和 DeleteVolume  的调用。

  • CSI driver container

7af28ef2a6c0d2a9ff6d45d50682e86f.png

图2-78 OpenShift CSI逻辑图

通过一个CSI Driver DaemonSet,在每个OpenShift节点上启动一个Driver容器。它允许OpenShift将CSI driver提供的存储挂载到OpenShift节点,并将其映射挂载到Pod中。

需要指出的是,从Ceph 社区版本v14开始,OpenShift访问Ceph必须要有CSI Driver,无法绕开CSI直接访问Ceph存储。

本文选自《OpenShift在企业中的实践》(第2版),经出版社授权发布。

d4733737abf03fcc5270ceef2d5d855d.png

8bfa7bde12ef24dd2df47675a77f21b1.png

扫码京东购买

推荐语:经典畅销书再次升级!红帽首席解决方案架构师联合撰写,20位全球知名企业IT负责人推荐,基于OpenShift v4,详述PaaS、DevOps、云原生、微服务治理。完整描绘企业数字化转型路线,为企业通过OpenShift实现IT转型给出具体建议和参考架构。

微信淘宝等平台要互通!?腾讯阿里字节回应

2021-09-14

b322f6cf1fd95a84a3f668ef4fa33bc7.png

一文详解 API 设计最佳实践

2021-09-12

993c78151acd7851bc794ca22fed4421.png

12 种经典亿级流量架构之资源隔离思想与方法论

2021-09-09

9b8169bcc4169da12164f1622a665e0c.png

拼夕夕订单超时未支付自动关闭实现方案!

2021-09-08

3267f612ee0fa1d6a26db91fd1c035c8.png

在腾讯,我们如何做 Code Review

2021-09-24

5b1cfa1a74356a94aaf56561a5eae010.png

紫色飞猪:基于K8s的集群稳定架构

2021-09-23

c60d62f0ec71038ef33e9df0a2c36adb.png

2W 字详解设计模式!

2021-09-22

c1b630adffa0ac8b4fbe4defe1d3b681.png

巨人大哥聊聊电商微服务体系中分层设计和领域的划分

2021-09-20

a451f8c61c8af8a96ac4d76ba65811b2.png

亿级流量架构怎么做资源隔离?口琴这篇写得太好了!

2021-09-17

598d94420531f5c5cff665f34c448ce4.png

蚂蚁集团于雨:万级规模 K8S 集群 Etcd 高可用建设之路

2021-09-16

64ef5bbf73e7d107afe0071fbd39098d.png

干货丨千万流量大型分布式系统架构设计实战

2021-09-15

90a8bd065d74909fdd364fd230de891b.png

京东面试官:你是怎么理解 MySQL 的优化原理的?

2021-09-26

9331a429a924141925b8d77c0f0bc1d8.png

在腾讯,我们如何做 Code Review

2021-09-24

4105c2f81dfa027dafe6a220196f9946.png

紫色飞猪:基于K8s的集群稳定架构

2021-09-23

f916900168baf92d08f7195d039b94ce.png

2W 字详解设计模式!

2021-09-22

1f1b0bce77e75a3e809c4166f528cba1.png

巨人大哥聊聊电商微服务体系中分层设计和领域的划分

2021-09-20

386b5a637a4e8ebd1d0537761f080c96.png

亿级流量架构怎么做资源隔离?口琴这篇写得太好了!

2021-09-17

ae00706cdbae46358367fccc55ce82de.png

蚂蚁集团于雨:万级规模 K8S 集群 Etcd 高可用建设之路

2021-09-16

db6d4a0880cfd8290c491fb337eb18df.png

干货丨千万流量大型分布式系统架构设计实战

2021-09-15

a88d818a43035eba84f08c9f34e75a27.png

微信淘宝等平台要互通!?腾讯阿里字节回应

2021-09-14

590c4a9d2e54b1111e473fdbda8a635f.png

一文详解 API 设计最佳实践

2021-09-12

a1e6567925d757376651e6ea24e313f0.png

12 种经典亿级流量架构之资源隔离思想与方法论

2021-09-09

bfc4ccf4e9c9ed2b2091f7fb9e3ccb34.png

美团技术:到店结算平台实践(胶片)

2021-09-06

2a509181fe402da4e93a879037733bac.png

Serverless实战之路

2021-09-03

690ca1cc18f796996ecf3d051e1f99e4.png

柴华:DDD在哈啰交易中台的实践

2021-09-02

071a14d69b4a7aa3f954257c3f0a046b.png

建设微服务API网关的一些实践

2021-10-13

9f7c84e8564f3e58a0f648cfaeff05a0.png

新公司要上监控,我决定用Prometheus

2021-10-12

13fd9faade58cb5759a6b929f2964304.png

RabbitMQ 七战 Kafka,差异立现!

2021-09-30

e80f89be370af3341372d989b91bfe52.png

分布领域驱动设计(DDD):领域接口化设计式缓存的选择

2021-09-27

c9097e79608bc287a421a6a4347b1de8.png

c8fc94c98c253b162ca7401dfe75e8b8.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值