K8S-持久化存储及常用存储方案

1. 存储知识的回顾

1.1 块存储

传统的文件系统,是直接访问存储数据的硬件介质的。介质不关心也无法去关心这些数据的组织方式以及结构,因此用的是最简单粗暴的组织方式:所有数据按照固定的大小分块,每一块赋予一个用于寻址的编号。以大家比较熟悉的机械硬盘为例,一块就是一个扇区,老式硬盘是512字节大小,新硬盘是4K字节大小。老式硬盘用柱面-磁头-扇区号(CHS,Cylinder-Head-Sector)组成的编号进行寻址,现代硬盘用一个逻辑块编号寻址(LBA,Logical Block Addressing)。所以,硬盘往往又叫块设备(Block Device),当然,除了硬盘还有其它块设备,例如不同规格的软盘,各种规格的光盘,磁带等。

至于哪些块组成一个文件,哪些块记录的是目录/子目录信息,这是文件系统的事情。不同的文件系统有不同的组织结构,这个就不展开了。为了方便管理,硬盘这样的块设备通常可以划分为多个逻辑块设备,也就是我们熟悉的硬盘分区(Partition)。反过来,单个介质的容量、性能有限,可以通过某些技术手段把多个物理块设备组合成一个逻辑块设备,例如各种级别的RAID,JBOD,某些操作系统的卷管理系统(Volume Manager)如Windows的动态磁盘、Linux的LVM等。

补充一下的是,块设备的使用对象除了传统的文件系统以及一些专用的管理工具软件如备份软件、分区软件外,还有一些支持直接读写块设备的软件如数据库等,但一般用户很少这样使用。

在网络存储中,服务器把本地的一个逻辑块设备——底层可能是一个物理块设备的一部分,也可能是多个物理块设备的组合,又或者多个物理块设备的组合中的一部分,甚至是一个本地文件系统上的一个文件——通过某种协议模拟成一个块设备,远程的客户端(可以是一台物理主机,也可以是虚拟机,某个回答所说的块设备是给虚拟机用是错误的)使用相同的协议把这个逻辑块设备作为一个本地存储介质来使用,划分分区,格式化自己的文件系统等等。这就是块存储,比较常见的块存储协议有iSCSI,光纤通道(FC)、以太网上的光纤通道(FCOE)等。

1.2 文件存储

​ 文件存储的用户是自然人,最容易理解。计算机中所有的数据都是0和1,存储在硬件介质上的一连串的01组合对我们来说完全无法去分辨以及管理。因此我们用“文件”这个概念对这些数据进行组织,所有用于同一用途的数据,按照不同应用程序要求的结构方式组成不同类型的文件(通常用不同的后缀来指代不同的类型),然后我们给每一个文件起一个方便理解记忆的名字。而当文件很多的时候,我们按照某种划分方式给这些文件分组,每一组文件放在同一个目录(或者叫文件夹)里面,当然我们也需要给这些目录起一个容易理解和记忆的名字。而且目录下面除了文件还可以有下一级目录(称之为子目录或者子文件夹),所有的文件、目录形成一个树状结构。我们最常用的Windows系统中,打开资源管理器就可以看到以这种方式组织起来的无数个文件和目录。在Linux可以用tree命令列出以某个文件夹为根节点列出一棵树:

img

为了方便查找,从根节点开始逐级目录往下,一直到文件本身,把这些目录、子目录、文件的名字用特殊的字符(例如Windows/DOS用“\”,类Unix系统用“/”)拼接起来,这样的一串字符称之为路径,例如Linux中的“/etc/systemd/system.conf”或者Windows中的“C:\Windows\System32\taskmgr.exe”。人类用路径作为唯一标识来访问具体的文件。而由作为自然人的程序员所编写的各种软件程序,绝大部分也使用这种方式来访问文件。

把存储介质上的数据组织成目录-子目录-文件这种形式的数据结构,用于从这个结构中寻找、添加、修改、删除文件的程序,以及用于维护这个结构的程序,组成的系统有一个专用的名字:文件系统(File System)。文件系统有很多,常见的有Windows的FAT/FAT32/NTFS,Linux的EXT2/EXT3/EXT4/XFS/BtrFS等。而在网络存储中,底层数据并非存储在本地的存储介质,而是另外一台服务器上,不同的客户端都可以用类似文件系统的方式访问这台服务器上的文件,这样的系统叫网络文件系统(Network File System),常见的网络文件系统有Windows网络的CIFS(也叫SMB)、类Unix系统网络的NFS等。而文件存储除了网络文件系统外,FTP、HTTP其实也算是文件存储的某种特殊实现,都是可以通过某个url来访问一个文件。

1.3 对象存储 “对象存储”或“基于对象的存储”一词是由它的名称派生出来的,因为它将数据和元数据封装到对象中。元数据本质上是描述其他数据的数据,或者在基于对象的存储的情况下,是关于通常存储在对象内的文件的信息。

对象存储在平面结构或地址空间中。每个对象都分配一个对象ID或唯一标识符,使它们可以从单个存储库或存储池中检索。企业非常重视这种方法,因为它提供了更大的灵活性,可以将数据放置在基于数据块和文件的存储解决方案之外。

1.4 总结

以上三种存储方式的寻址方式不同,第一种一般以物理地址为寻址方式,第二种依赖于操作系统,第三种即为每个要存取的信息分配唯一编码,以唯一编码为寻址方式。

2. 常见的存储解决方案

存储体系介绍

img

2.1 Ceph

2.2 glusterfs

2.3 公有云对象存储

2.4 nas

2.5 san

3. K8S中存储的相关概念

3.1 卷

参考链接: https://kubernetes.io/zh/docs/concepts/storage/volumes/

Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用 程序带来一些问题。问题之一是当容器崩溃时文件丢失。kubelet 会重新启动容器, 但容器会以干净的状态重启。 第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。 Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。

3.1.1 背景

Docker 也有 卷(Volume) 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录。 Docker 提供卷驱动程序,但是其功能非常有限。

Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁 持久卷。对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。

卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放 的内容。

使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 容器中的进程看到的是由它们的 Docker 镜像和卷组成的文件系统视图。 Docker 镜像 位于文件系统层次结构的根部。各个卷则挂载在镜像内的指定路径上。 卷不能挂载到其他卷之上,也不能与其他卷有硬链接。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。

CSI Driver List

https://kubernetes-csi.github.io/docs/drivers.html#sample-drivers

3.2 卷类型

目前Kubernetes 支持下列类型的卷:

3.2.1 awsElasticBlockStore

wsElasticBlockStore 卷将 Amazon Web服务(AWS)EBS 卷 挂载到你的 Pod 中。与 emptyDir 在 Pod 被删除时也被删除不同,EBS 卷的内容在删除 Pod 时 会被保留,卷只是被卸载掉了。 这意味着 EBS 卷可以预先填充数据,并且该数据可以在 Pod 之间共享。

3.2.2 azureDisk

azureDisk 卷类型用来在 Pod 上挂载 Microsoft Azure 数据盘(Data Disk) 。 若需了解更多详情,请参考 azureDisk卷插件

3.2.3 azureFile

azureFile 卷类型用来在 Pod 上挂载 Microsoft Azure 文件卷(File Volume)(SMB 2.1 和 3.0)。 更多详情请参考 azureFile卷插件

3.2.4 cephfs

cephfs 卷允许你将现存的 CephFS 卷挂载到 Pod 中。 不像 emptyDir 那样会在 Pod 被删除的同时也会被删除,cephfs 卷的内容在 Pod 被删除 时会被保留,只是卷被卸载了。这意味着 cephfs 卷可以被预先填充数据,且这些数据可以在 Pod 之间共享。同一 cephfs 卷可同时被多个写者挂载。

说明: 在使用 Ceph 卷之前,你的 Ceph 服务器必须已经运行并将要使用的 share 导出(exported)。

更多信息请参考 CephFS 示例

3.2.5 configMap

configMap 卷 提供了向 Pod 注入配置数据的方法。 ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被 Pod 中运行的 容器化应用使用。

引用 configMap 对象时,你可以在 volume 中通过它的名称来引用。 你可以自定义 ConfigMap 中特定条目所要使用的路径。 下面的配置显示了如何将名为 log-config 的 ConfigMap 挂载到名为 configmap-pod 的 Pod 中:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test
      image: busybox
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: log-config
        items:
          - key: log_level
            path: log_level

log-config ConfigMap 以卷的形式挂载,并且存储在 log_level 条目中的所有内容 都被挂载到 Pod 的 /etc/config/log_level 路径下。 请注意,这个路径来源于卷的 mountPath 和 log_level 键对应的 path。

说明:

  • 在使用 ConfigMap 之前你首先要创建它。

  • 容器以 subPath 卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新。

  • 文本数据挂载成文件时采用 UTF-8 字符编码。如果使用其他字符编码形式,可使用 binaryData 字段。

3.2.6 emptyDir

​ 当 Pod 分派到某个 Node 上时,emptyDir 卷会被创建,并且在 Pod 在该节点上运行期间,卷一直存在。 就像其名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除。

说明: 容器崩溃并会导致 Pod 被从节点上移除,因此容器崩溃期间 emptyDir 卷中的数据是安全的。

emptyDir 的一些用途:

  • 缓存空间,例如基于磁盘的归并排序。

  • 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。

  • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

取决于你的环境,emptyDir 卷存储在该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储。但是,你可以将 emptyDir.medium 字段设置为 “Memory”,以告诉 Kubernetes 为你挂载 tmpfs(基于 RAM 的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。

说明: 当启用 SizeMemoryBackedVolumes 特性门控时, 你可以为基于内存提供的卷指定大小。 如果未指定大小,则基于内存的卷的大小为 Linux 主机上内存的 50%。

emptyDir 配置示例
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

3.2.7 fc (光纤通道)

fc 卷类型允许将现有的光纤通道块存储卷挂载到 Pod 中。 可以使用卷配置中的参数 targetWWNs 来指定单个或多个目标 WWN(World Wide Names)。 如果指定了多个 WWN,targetWWNs 期望这些 WWN 来自多路径连接。

注意: 你必须配置 FC SAN Zoning,以便预先向目标 WWN 分配和屏蔽这些 LUN(卷), 这样 Kubernetes 主机才可以访问它们。

更多详情请参考 FC 示例

3.2.8 hostPath

hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。

例如,hostPath 的一些用法有:

  • 运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径。

  • 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys。

  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type。

支持的 type 值如下:

取值行为
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory在给定路径上必须存在的目录。
FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File在给定路径上必须存在的文件。
Socket在给定路径上必须存在的 UNIX 套接字。
CharDevice在给定路径上必须存在的字符设备。
BlockDevice在给定路径上必须存在的块设备。

当使用这种类型的卷时要小心,因为:

  • 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同 而在不同节点上有不同的行为。
  • 下层主机上创建的文件或目录只能由 root 用户写入。你需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。
hostPath 配置示例:
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # 宿主上目录位置
      path: /data
      # 此字段为可选
      type: Directory

3.2.9 iscsi

iscsi 卷能将 iSCSI (基于 IP 的 SCSI) 卷挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,iscsi 卷的内容在删除 Pod 时 会被保留,卷只是被卸载。 这意味着 iscsi 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

注意: 在使用 iSCSI 卷之前,你必须拥有自己的 iSCSI 服务器,并在上面创建卷。

iSCSI 的一个特点是它可以同时被多个用户以只读方式挂载。 这意味着你可以用数据集预先填充卷,然后根据需要在尽可能多的 Pod 上使用它。 不幸的是,iSCSI 卷只能由单个使用者以读写模式挂载。不允许同时写入。

更多详情请参考 iSCSI 示例

3.2.10 local

local 卷所代表的是某个被挂载的本地存储设备,例如磁盘、分区或者目录。

local 卷只能用作静态创建的持久卷。尚不支持动态配置。

与 hostPath 卷相比,local 卷能够以持久和可移植的方式使用,而无需手动将 Pod 调度到节点。系统通过查看 PersistentVolume 的节点亲和性配置,就能了解卷的节点约束。

然而,local 卷仍然取决于底层节点的可用性,并不适合所有应用程序。 如果节点变得不健康,那么local 卷也将变得不可被 Pod 访问。使用它的 Pod 将不能运行。 使用 local 卷的应用程序必须能够容忍这种可用性的降低,以及因底层磁盘的耐用性特征 而带来的潜在的数据丢失风险。

下面是一个使用 local 卷和 nodeAffinity 的持久卷示例:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node

使用 local 卷时,你需要设置 PersistentVolume 对象的 nodeAffinity 字段。 Kubernetes 调度器使用 PersistentVolume 的 nodeAffinity 信息来将使用 local 卷的 Pod 调度到正确的节点。

PersistentVolume 对象的 volumeMode 字段可被设置为 “Block” (而不是默认值 “Filesystem”),以将 local 卷作为原始块设备暴露出来。

使用 local 卷时,建议创建一个 StorageClass 并将其 volumeBindingMode 设置为 WaitForFirstConsumer。要了解更多详细信息,请参考 local StorageClass 示例。 延迟卷绑定的操作可以确保 Kubernetes 在为 PersistentVolumeClaim 作出绑定决策时, 会评估 Pod 可能具有的其他节点约束,例如:如节点资源需求、节点选择器、Pod 亲和性和 Pod 反亲和性。

你可以在 Kubernetes 之外单独运行静态驱动以改进对 local 卷的生命周期管理。 请注意,此驱动尚不支持动态配置。 有关如何运行外部 local 卷驱动,请参考 local 卷驱动用户指南

nfs

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

要了解更多详情请参考 NFS 示例

3.3 持久卷

3.4 Secret 信息

Secret解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用。

Secret有三种类型:

  • Service Account :用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中;

  • Opaque :base64编码格式的Secret,用来存储密码、密钥等;

  • kubernetes.io/dockerconfigjson :用来存储私有docker registry的认证信息。

3.4.1 Opaque Secret

Opaque类型的数据是一个map类型,要求value是base64编码格式:

$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm

secrets.yml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=

接着,就可以创建secret了:kubectl create -f secrets.yml。

创建好secret之后,有两种方式来使用它:

  • 以Volume方式
  • 以环境变量方式

3.4.2 将Secret挂载到Volume中

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: db
  name: db
spec:
  volumes:
  - name: secrets
    secret:
      secretName: mysecret
  containers:
  - image: gcr.io/my_project_id/pg:v1
    name: db
    volumeMounts:
    - name: secrets
      mountPath: "/etc/secrets"
      readOnly: true
    ports:
    - name: cp
      containerPort: 5432
      hostPort: 5432

3.4.3 将Secret导出到环境变量中

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress-deployment
spec:
  replicas: 2
  strategy:
      type: RollingUpdate
  template:
    metadata:
      labels:
        app: wordpress
        visualize: "true"
    spec:
      containers:
      - name: "wordpress"
        image: "wordpress"
        ports:
        - containerPort: 80
        env:
        - name: WORDPRESS_DB_USER
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: WORDPRESS_DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password

3.4.5 docker镜像密码配置

可以直接用kubectl命令来创建用于docker registry认证的secret:

kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAILsecret "myregistrykey" created.

也可以直接读取~/.docker/config.json的内容来创建:

cat ~/.docker/config.json | base64cat > myregistrykey.yaml <<EOFapiVersion: v1kind: Secretmetadata:  name: myregistrykeydata:  .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==type: kubernetes.io/dockerconfigjsonEOF$ kubectl create -f myregistrykey.yaml

在创建Pod的时候,通过imagePullSecrets来引用刚创建的myregistrykey:

apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey

3.4.6 服务账务

Service Account用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中。

$ kubectl run nginx --image nginx
deployment "nginx" created
$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-3137573019-md1u2   1/1       Running   0          13s
$ kubectl exec nginx-3137573019-md1u2 ls /run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token

3.5 卷快照

3.5.1 什么是快照

一句话答案:快照是数据存储的某一时刻的状态记录;备份则是数据存储的某一个时刻的副本。这是两种完全不同的概念。

详细信息参考: https://www.zhihu.com/question/20374919

在 Kubernetes 中,卷快照是一个存储系统上卷的快照。

3.5.2 卷快照介绍

与 PersistentVolume 和 PersistentVolumeClaim 两个 API 资源用于给用户和管理员提供卷类似,VolumeSnapshotContent 和 VolumeSnapshot 两个 API 资源用于给用户和管理员创建卷快照。

VolumeSnapshotContent 是一种快照,从管理员已提供的集群中的卷获取。就像持久卷是集群的资源一样,它也是集群中的资源。

VolumeSnapshot 是用户对于卷的快照的请求。它类似于持久卷声明。

VolumeSnapshotClass 允许指定属于 VolumeSnapshot 的不同属性。在从存储系统的相同卷上获取的快照之间,这些属性可能有所不同,因此不能通过使用与 PersistentVolumeClaim 相同的 StorageClass 来表示。

卷快照能力为 Kubernetes 用户提供了一种标准的方式来在指定时间点 复制卷的内容,并且不需要创建全新的卷。例如,这一功能使得数据库管理员 能够在执行编辑或删除之类的修改之前对数据库执行备份。

当使用该功能时,用户需要注意以下几点:

  • API 对象 VolumeSnapshot,VolumeSnapshotContent 和 VolumeSnapshotClass 是 CRDs, 不属于核心 API。

  • VolumeSnapshot 支持仅可用于 CSI 驱动。

  • 作为 VolumeSnapshot 部署过程的一部分,Kubernetes 团队提供了一个部署于控制平面的快照控制器, 并且提供了一个叫做 csi-snapshotter 的边车(Sidecar)辅助容器,和 CSI 驱动程序一起部署。 快照控制器监视 VolumeSnapshot 和 VolumeSnapshotContent 对象, 并且负责创建和删除 VolumeSnapshotContent 对象。 边车 csi-snapshotter 监视 VolumeSnapshotContent 对象, 并且触发针对 CSI 端点的 CreateSnapshot 和 DeleteSnapshot 的操作。

  • 还有一个验证性质的 Webhook 服务器,可以对快照对象进行更严格的验证。 Kubernetes 发行版应将其与快照控制器和 CRD(而非 CSI 驱动程序)一起安装。 此服务器应该安装在所有启用了快照功能的 Kubernetes 集群中。

  • CSI 驱动可能实现,也可能没有实现卷快照功能。CSI 驱动可能会使用 csi-snapshotter 来提供对卷快照的支持。详见 CSI 驱动程序文档

  • Kubernetes 负责 CRDs 和快照控制器的安装。

3.5.3 卷快照和卷快照内容的生命周期

VolumeSnapshotContents 是集群中的资源。

VolumeSnapshots 是对于这些资源的请求。

VolumeSnapshotContents 和 VolumeSnapshots 之间的交互遵循以下生命周期:

3.5.3.1 供应卷快照

快照可以通过两种方式进行配置:预配置或动态配置。

3.5.3.2 预配置

集群管理员创建多个 VolumeSnapshotContents。它们带有存储系统上实际卷快照的详细信息,可以供集群用户使用。它们存在于 Kubernetes API 中,并且能够被使用。

3.5.3.3 动态的

可以从 PersistentVolumeClaim 中动态获取快照,而不用使用已经存在的快照。 在获取快照时,卷快照类 指定要用的特定于存储提供程序的参数

3.5.3.4 卷快照示例

每个 VolumeSnapshot 包含一个 spec 和一个状态。

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: new-snapshot-test
spec:
  volumeSnapshotClassName: csi-hostpath-snapclass
  source:
    persistentVolumeClaimName: pvc-test

3.6 动态卷供应

动态卷供应允许按需创建存储卷。 如果没有动态供应,集群管理员必须手动地联系他们的云或存储提供商来创建新的存储卷, 然后在 Kubernetes 集群创建 PersistentVolume对象来表示这些卷。 动态供应功能消除了集群管理员预先配置存储的需要。 相反,它在用户请求时自动供应存储。

3.6.1 启用动态卷供应

要启用动态供应功能,集群管理员需要为用户预先创建一个或多个 StorageClass 对象。 StorageClass 对象定义当动态供应被调用时,哪一个驱动将被使用和哪些参数将被传递给驱动。 以下清单创建了一个 StorageClass 存储类 “slow”,它提供类似标准磁盘的永久磁盘。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

以下清单创建了一个 “fast” 存储类,它提供类似 SSD 的永久磁盘。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

3.6.2 使用动态卷供应

用户通过在 PersistentVolumeClaim 中包含存储类来请求动态供应的存储。 在 Kubernetes v1.9 之前,这通过 volume.beta.kubernetes.io/storage-class 注解实现。然而,这个注解自 v1.6 起就不被推荐使用了。 用户现在能够而且应该使用 PersistentVolumeClaim 对象的 storageClassName 字段。 这个字段的值必须能够匹配到集群管理员配置的 StorageClass 名称(见下面)。

例如,要选择 “fast” 存储类,用户将创建如下的 PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

4. 相关实践

参考文档: https://blog.csdn.net/yinwenjie/article/details/52208294

​ https://www.zhihu.com/question/21536660/answer/1159036357

​ https://kubernetes.io/zh/docs/concepts/storage/volume-snapshots/

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐