暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kubernetes动态资源——StorageClass详解

IT运维大爆炸 2023-10-26
105

1、简介

现在集群管理员不预分配 PV,他写了一个模板文件,这个模板文件是用来表示创建某一类型存储(块存储,文件存储等)所需的一些参数,这些参数是用户不关心的,给存储本身实现有关的参数。用户只需要提交自身的存储需求,也就是PVC文件,并在 PVC 中指定使用的存储模板(StorageClass)。K8s 集群中的管控组件,会结合 PVC 和 StorageClass 的信息动态,生成用户所需要的存储(PV),将 PVC 和 PV 进行绑定后,pod 就可以使用 PV 了。通过 StorageClass 配置生成存储所需要的存储模板,再结合用户的需求动态创建 PV 对象,做到按需分配,在没有增加用户使用难度的同时也解放了集群管理员的运维工作。

2、Provisioning(供应) - 为PVC提供PV

为pvc供应( Provisioning )pv有两种方式,静态和动态:

静态供应 (Static)

集群管理员实现创建好一系列 PersistentVolume,它们包含了可供集群中应用程序使用的关于实际存储的具体信息。

动态供应 (Dynamic)

在配置有合适的 StorageClass(存储类)PersistentVolumeClaim 关联了该 StorageClass 的情况下,kubernetes 集群可以为应用程序动态创建 PersistentVolume。

3、绑定 (Binding)

  • 用户创建了一个 PersistentVolumeClaim 存储卷声明,并指定了需求的存储空间大小以及访问模式。

  • Kubernets master 将立刻为其匹配一个 PersistentVolume 存储卷,并将存储卷声明和存储卷绑定到一起。

  • 除动态提供,应用程序将被绑定一个不小于(可能大于)其 PersistentVolumeClaim 中请求的存储空间大小的 PersistentVolume。一旦绑定,PersistentVolumeClaim 将拒绝其他 PersistentVolume 的绑定关系。PVC 与 PV 之间的绑定关系是一对一的映射

  • PersistentVolumeClaim 将始终停留在 未绑定 unbound 状态,直到有合适的 PersistentVolume 可用。举个例子:集群中已经存在一个 50Gi 的 PersistentVolume,同时有一个 100Gi 的 PersistentVolumeClaim,在这种情况下,该 PVC 将一直处于 未绑定 unbound 状态,直到管理员向集群中添加了一个 100Gi 的 PersistentVolume。

4、使用中保护 (Storage Object in Use Protection)

  • 使用中保护(Storage Object in Use Protection)的目的是确保正在被容器组使用的 PersistentVolumeClaim 以及其绑定的 PersistentVolume 不能被系统删除,以避免可能的数据丢失。

  • 如果用户删除一个正在使用中的 PersistentVolumeClaim,则该 PVC 不会立即被移除掉,而是推迟到该 PVC 不在被任何容器组使用时才移除;同样的如果管理员删除了一个已经绑定到 PVC 的 PersistentVolume,则该 PV 也不会立刻被移除掉,而是推迟到其绑定的 PVC 被删除后才移除掉。

5、回收 (Reclaiming)

当用户不在需要其数据卷时,可以删除掉其 PersistentVolumeClaim,此时其对应的 PersistentVolume 将被集群回收并再利用。Kubernetes 集群根据 PersistentVolume 中的 reclaim policy(回收策略)决定在其被回收时做对应的处理。当前支持的回收策略有:Retained(保留)、Recycled(重复利用)、Deleted(删除):

  • 保留 (Retain)

    保留策略需要集群管理员手工回收该资源。当绑定的 PersistentVolumeClaim 被删除后,PersistentVolume 仍然存在,并被认为是”已释放“。但是此时该存储卷仍然不能被其他 PersistentVolumeClaim 绑定,因为前一个绑定的 PersistentVolumeClaim 对应容器组的数据还在其中。集群管理员可以通过如下步骤回收该 PersistentVolume:

    • 删除该 PersistentVolume。PV 删除后,其数据仍然存在于对应的外部存储介质中(nfs、cefpfs、glusterfs 等)

    • 手工删除对应存储介质上的数据

    • 手工删除对应的存储介质,您也可以创建一个新的 PersistentVolume 并再次使用该存储介质

  • 删除 (Delete)

    删除策略将从 kubernete 集群移除 PersistentVolume 以及其关联的外部存储介质(云环境中的 AWA EBS、GCE PD、Azure Disk 或 Cinder volume)。

  • 再利用 (Recycle)

    • 再利用策略将在 PersistentVolume 回收时,执行一个基本的清除操作(rm -rf thevolume/*),并使其可以再次被新的 PersistentVolumeClaim 绑定。

    • Warning: The Recycle
      reclaim policy is deprecated. Instead, the recommended approach is to use dynamic provisioning.(动态供应)

6、PV字段

PersistentVolume 字段描述如下表所示:

字段名称可选项/备注
容量 Capacity通常,一个 PersistentVolume 具有一个固定的存储容量(capacity)
Volume ModeFEATURE STATE: Kubernetes v1.13 beta Kubernetes 1.9 之前的版本,所有的存储卷都被初始化一个文件系统。当前可选项有:block:使用一个 块设备(raw block device)filesystem(默认值):使用一个文件系统
Access Modes可被单节点读写-ReadWriteOnce【RWO】可被多节点只读-ReadOnlyMany【ROX】可被多节点读写-ReadWriteMany【RWX】注意:不同的存储支持的不同,见下表
存储类 StorageClassName带有存储类 StorageClassName 属性的 PersistentVolume 只能绑定到请求该 StorageClass 存储类的 PersistentVolumeClaim。 没有 StorageClassName 属性的 PersistentVolume 只能绑定到无特定 StorageClass 存储类要求的 PVC。
回收策略 Reclaim Policy保留 Retain – 手工回收再利用Recycle – 清除后重新可用 (rm -rf thevolume/*)删除 Delete – 删除 PV 及存储介质
Mount Options挂载选项用来在挂载时作为 mount 命令的参数
状态 PhaseAvailable – 可用的 PV,尚未绑定到 PVCBound – 已经绑定到 PVCReleased – PVC 已经被删除,但是资源还未被集群回收Failed – 自动回收失败

7、PVC相关字段

字段名称可选项/备注
存储类只有该 StorageClass 存储类的 PV 才可以绑定到此 PVC
读写模式 Access Modes可被单节点读写-ReadWriteOnce可被多节点只读-ReadOnlyMany可被多节点读写-ReadWriteMany
Volume Modesblockfilesystem - default
总量请求存储空间的大小

8、K8s动态资源的用途

  • 数据库实例管理: 您可以创建一个自定义资源来定义数据库实例的规格、访问凭证和备份策略,然后使用控制器来动态创建和管理这些数据库实例。

  • 应用程序配置: 通过自定义资源,您可以定义应用程序的配置,例如环境变量、配置文件和秘密。然后,您可以使用控制器将这些配置应用到相关的Pod中。

  • 监控和警报: 自定义资源可以用于定义监控指标和警报规则。这使您可以在Kubernetes集群中集中管理监控和警报设置。

  • 存储卷管理: 如果您有特定的存储需求,可以创建自定义资源来定义持久卷的规格和访问策略,然后使用控制器来创建和管理这些卷。

  • CI/CD管道: 自定义资源可以用于定义CI/CD管道的配置,包括构建规则、部署策略和自动化测试。

9、实战前准备-安装NFS环境

搭建NFS-Server环境

#配置NFS服务器
yum install -y nfs-utils

#执行命令 vi etc/exports,创建 exports 文件,文件内容如下:
echo "/data/volumes/ *(insecure,rw,sync,no_root_squash)" > etc/exports
#/data/volumes 172.26.248.0/20(rw,no_root_squash)

# 创建共享目录
mkdir -p data/volumes

systemctl enable rpcbind
systemctl enable nfs-server

#执行以下命令,启动 nfs 服务
systemctl restart rpcbind
systemctl restart nfs-server
exportfs -r

#检查配置是否生效
exportfs
# 输出结果如下所示
/data/volumes data/volumes

搭建NFS-Client环境(选测)

#服务器端防火墙开放111、662、875、892、2049的 tcp  udp 允许,否则远端客户无法连接。
#安装客户端工具
yum install -y nfs-utils

#执行以下命令检查 nfs 服务器端是否有设置共享目录
# showmount -e $(nfs服务器的IP)
showmount -e 172.26.248.150

# 输出结果如下所示
Export list for 172.26.248.150
/data/volumes *

#执行以下命令挂载 nfs 服务器上的共享目录到本机路径 root/nfsmount
mkdir root/nfsmount
# mount -t nfs $(nfs服务器的IP):/root/nfs_root root/nfsmount

#高可用备份的方式
mount -t nfs 172.26.248.165:/nfs/data nfs/data

# 写入一个测试文件
echo "hello nfs server" > root/nfsmount/test.txt

#在 nfs 服务器上执行以下命令,验证文件写入成功
cat data/volumes/test.txt

10、创建存储类(NFS环境前面已经搭好)

字段名称填入内容备注
名称nfs-storage自定义存储类名称
NFS Server172.20.60.23NFS服务的IP地址
NFS Path/data/volumesNFS服务所共享的路径

11、Storage Classes

  • Storage Classes是K8s中定义动态存储的一种机制。它是一种资源对象,用于定义存储卷的属性和行为。

  • 每个Storage Class都有一个唯一的名称,并定义了存储卷的类型、访问模式、存储提供者等属性。

  • 当创建PVC(Persistent Volume Claim)时,可以指定所需的Storage Class,K8s将根据Storage Class的定义自动创建和绑定存储卷。

12、实战-动态提供 PV

基于Storage Class和nfs文件系统,实现存储的动态供给(NFS+PV+PVC)

创建sa

# 先创建授权
[root@node1 ~]# vi nfs-rbac.yaml
apiVersion: v1
kind: Namespace                 ##创建Namespace,并全部替换为新建的Namespace
metadata:
name: nfs-client-provisioner
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
 - apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]
 - apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "list", "watch", "create", "delete"]
 - apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["get", "list", "watch", "update"]
 - apiGroups: ["storage.k8s.io"]
  resources: ["storageclasses"]
  verbs: ["get", "list", "watch"]
 - apiGroups: [""]
  resources: ["events"]
  verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
 - kind: ServiceAccount
  name: nfs-client-provisioner
  namespace: nfs-client-provisioner
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: nfs-client-provisioner
rules:
 - apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: nfs-client-provisioner
subjects:
 - kind: ServiceAccount
  name: nfs-client-provisioner
  namespace: nfs-client-provisioner
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io

##这个镜像中volume的mountPath默认为/persistentvolumes,不能修改,否则运行时会报错

部署nfs-client-provisioner

nfs-client-provisioner 是一个 Kubernetes 的简易 NFS 的外部 provisioner,本身不提供 NFS,需要现有的 NFS 服务器提供存储。注意:地址和目录要改成实际的NFS服务对应配置。

[root@node1 ~]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
  app: nfs-client-provisioner
namespace: nfs-client-provisioner       ##指向新建
spec:
replicas: 1
strategy:
  type: Recreate
selector:
  matchLabels:
    app: nfs-client-provisioner
template:
  metadata:
    labels:
      app: nfs-client-provisioner
  spec:
    serviceAccountName: nfs-client-provisioner
    containers:
       - name: nfs-client-provisioner
        image: registry.cn-hangzhou.aliyuncs.com/xzjs/nfs-subdir-external-provisioner:v4.0.0 ##更改镜像
        volumeMounts:
           - name: nfs-client-root
            mountPath: persistentvolumes
        env:
           - name: PROVISIONER_NAME
            value: k8s-sigs.io/nfs-subdir-external-provisioner
           - name: NFS_SERVER
            value: 172.20.60.23                        ##nfs服务器地址
           - name: NFS_PATH
            value: data/volumes/                              ##nfs路径
    volumes:
       - name: nfs-client-root
        nfs:
          server: 172.20.60.23                          ##server
          path: data/volumes/                                  ##路径

创建StorageClass

StorageClass是对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,减轻管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现动态资源供给。StorageClass的定义主要包括名称、后端存储的提供者(provisioner)和后端存储对应的参数。对于后端NFS存储来说,配置相对简单,只需要指定provisioner即可。

#创建storageclass
[root@node1 ~]# vi storageclass-nfs.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner  ##和 deployment.yaml中定义的name一致
reclaimPolicy: Delete

#扩展"reclaim policy"有三种方式:Retain、Recycle、Deleted。
Retain
#保护被PVC释放的PV及其上数据,并将PV状态改成"released",不将被其它PVC绑定。集群管理员手动通过如下步骤释放存储资源:
手动删除PV,但与其相关的后端存储资源如(AWS EBS, GCE PD, Azure Disk, or Cinder volume)仍然存在。
手动清空后端存储volume上的数据。
手动删除后端存储volume,或者重复使用后端volume,为其创建新的PV。

Delete
删除被PVC释放的PV及其后端存储volume。对于动态PV其"reclaim policy"继承自其"storage class"
默认是Delete。集群管理员负责将"storage class""reclaim policy"设置成用户期望的形式,否则需要用
户手动为创建后的动态PV编辑"reclaim policy"

Recycle
保留PV,但清空其上数据,已废弃

改变默认sc

##改变系统默认sc
https://kubernetes.io/zh/docs/tasks/administer-cluster/change-default-storage-class/#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%94%b9%e5%8f%98%e9%bb%98%e8%ae%a4-storage-class

[root@node1 ~]# kubectl patch storageclass storage-nfs-hdd -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

创建pvc

[root@node1 ~]# vi  pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
spec:
storageClassName: nfs-client           ##存储类名字需保持一致
accessModes:
   - ReadWriteMany                      ##多点读写
resources:
  requests:
    storage: 1Gi

实战部署deployment

[root@node1 ~]# cat test-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deploy
labels:
  app: test-deploy
namespace: default  #与RBAC文件中的namespace保持一致
spec:
replicas: 2
selector:
  matchLabels:
    app: test-deploy
strategy:
  type: Recreate
selector:
  matchLabels:
    app: test-deploy
template:
  metadata:
    labels:
      app: test-deploy
  spec:
    containers:
     - name: test-pod
      image: busybox:1.24
      command:
         - "/bin/sh"
      args:
         - "-c"
         # - "touch mnt/SUCCESS3 && exit 0 || exit 1"   #创建一个SUCCESS文件后退出
         - touch mnt/SUCCESS5; sleep 50000
      volumeMounts:
         - name: nfs-pvc
          mountPath: "/mnt"
           # subPath: test-pod-3 # 子路径 (这路基代表存储卷下面的test-pod子目录)
    volumes:
       - name: nfs-pvc
        persistentVolumeClaim:
          claimName: test-claim  #与PVC名称保持一致

验证

# 去nfs服务器中验证
[root@node1 ~]# kubectl --kubeconfig=../sit get pod
NAME                           READY   STATUS   RESTARTS   AGE
test-deploy-5d649d6566-bl7lx   1/1     Running   3         2d1h
test-deploy-5d649d6566-nkpqk   1/1     Running   3         2d1h

[root@node1 ~]# kubectl --kubeconfig=../sit exec -it test-deploy-5d649d6566-bl7lx -- /bin/sh
/ # cd /mnt/
/mnt # ls
SUCCESS5
/mnt # echo "111" > index.html

[root@node1 ~]# kubectl --kubeconfig=../sit exec -it test-deploy-5d649d6566-nkpqk -- /bin/sh
/ # cd /mnt/
/mnt # ls
SUCCESS5   index.html
/mnt # cat index.html
111

欢迎大家扫码关注:

本公众号只写原创,不接广告、不接广告、不接广告。下期小伙伴想学习什么技术,可以私信发我吆。

文章转载自IT运维大爆炸,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论