本文介绍: 在 Kubernetes 中,StorageClass用于定义动态存储卷的对象。它允许管理员定义不同类型存储,并使开发人员能够按需创建 PVC(Persistent Volume Claim 持久声明)StorageClass 可以看作是一种存储资源抽象,它定义了存储类型属性参数信息。Kubernetes 可以根据这些信息动态创建 PV(Persistent Volume 持久卷),并将其绑定到 PVC 上。利用 StorageClass 可以达到自动创建PVC的目的。

1. 前置条件

这里使用 NFS 存储方式,来演示动态创建 PV 的案例

前置条件需要在 K8s 集群安装 NFS 的环境安装参考持续集成部署-k8s-数据持久化-NFS安装与使用

确保 NFS 服务器正常可用之后,接着后续的步骤操作

验证配置是否生效

[root@docker-54 nfs]# showmount --export
Export list for docker-54:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-54 nfs]#
[root@docker-55 ~]# showmount -e master
Export list for master:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-55 ~]# 

[root@docker-56 ~]# showmount -e master
Export list for master:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-56 ~]# 

可以看到,两台 Node 节点上均已显示 NFS Server 的信息了。

在动态创建 PV 之前,我们需要先了解下用到组件的基础概念

2. StorageClass 存储类的概念使用

Kubernetes 中,StorageClass用于定义动态存储卷的对象。它允许管理员定义不同类型的存储,并使开发人员能够按需创建 PVC(Persistent Volume Claim 持久声明)。

StorageClass 可以看作是一种存储资源的抽象,它定义了存储的类型属性参数等信息。Kubernetes 可以根据这些信息动态地创建 PV(Persistent Volume 持久卷),并将其绑定PVC 上。
在这里插入图片描述
数据存储,动态构建 PV 的过程,如上面的流程图所示

但是在我们创建的过程中,则需要先创建 StorageClass,才能保证在 PVC 使用时,对应上,另外 在 Pod 创建时指定的 PVC 也是需要提前创建才行。

3. RBAC 配置

新建配置文件nfsprovisioner-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["get", "list", "watch", "update"]
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
- 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: kube-system
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
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
subjects:
- kind: ServiceAccount
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: kube-system
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

这个对应了 k8s 中角色权限的部分内容,在 k8s 的服务管理方面,其实就是一套类似 HTTP 的 RESTful 风格的 API,这些 API 默认是具备一个 RBAC 权限的。

上面的配置文件创建了角色账号,以及如何角色账号关联起来。

4. storageClass 配置

新建配置文件nfs-storage-class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs
parameters:
  archiveOnDelete: "false" # 是否存档 false 表示不存档,会删除 oldPath 下的数据true表示会存档,会重命名路径
reclaimPolicy: Retain # 回收策略默认为 Delete  可以配置为 Retain 
volumeBindingMode: Immediate # 默认为 Immediate,表示创建 PVC 立即绑定,只有azuredisk 和 AWSelasticblockstore 支持其他值

新建制备器配置文件nfs-provisioner-deployment.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: kube-system
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccount: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
#          image: quay.io/external_storage/nfs-client-provisioner:latest
          image: registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs # 对应 sc 里面的provisioner 的名称
            - name: NFS_SERVER
              value: 192.168.104.54 # nfs 服务的IP 和 路径 都需要关联上才行
            - name: NFS_PATH
              value: /home/nfs/rw
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.104.54
            path: /home/nfs/rw

上面这些东西,可能刚开始的时候看有点熟悉,又有点懵,上面的内容,不需要特殊记忆,理解就行,需要改动的地方,也就是最下面 volumes 相关serverpath ,其他内容均为官方配置的内容基本上也不会有很大的改动。

接着最后应用配置文件nfs-sc-demo-statefulset.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-sc
  labels:
    app: nginx-sc
spec:
  type: NodePort
  ports:
  - name: web
    port: 80
    protocol: TCP
  selector:
    app: nginx-sc
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-sc
spec:
  replicas: 1
  serviceName: "nginx-sc" # 对应上面的 Service 
  selector:
    matchLabels:
      app: nginx-sc # 匹配到下面的 Pod标签配置
  template:
    metadata:
      labels:
        app: nginx-sc # Pod 模板标签
    spec:
      containers:
      - image: nginx
        name: nginx-sc
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /usr/share/nginx/html # 挂载容器的哪个目录
          name: nginx-sc-test-pvc # 挂载哪个 volume
  volumeClaimTemplates:
  - metadata:
      name: nginx-sc-test-pvc
    spec:
      storageClassName: managed-nfs-storage
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi

这里创建了 Service 和 StatefulSet ,来管理 Nginx 的 Pod

volumeClaimTemplates 的配置为 希望可以帮我自动创建一个 PVC,这个 PVC 声明使用的存储类 storageClass,配置了 storageClass名称storageClassName访问模式accessModes,这声明为可以多个节点同时读写的一个模式最后声明,期望所需的资源最小1Gi

5. 创建应用测试 PVC 的自动配置

我们希望的效果是,一旦上面的应用创建起来之后,它自动我们把 PVC 创建出来,并且把 PV 也创建出来。

接下来完成上面这些内容的构建,分别把他们构建出来,然后再去把应用跑起来。

先看下当前环境pvpvc 的情况:

[root@docker-54 ~]# kubectl get pv | grep nginx
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get pvc 
No resources found in default namespace.
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get storageclass
NAME                    PROVISIONER   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storage (default)   nfs-client    Delete          Immediate           false                  132d
[root@docker-54 ~]#

可以看到当前没有对应的 PV 和 PVC 的。

接着需要先把 RBAC启动起来:

[root@docker-54 ~]# cd /opt/k8s/config/
[root@docker-54 config]# ls
application.yaml   file-test-pod.yaml               nfs-provisioner-rbac.yaml  nginx.conf                   test
env-test-pod.yaml  nfs-provisioner-deployment.yaml  nfs-storage-class.yaml     private-image-pull-pod.yaml
[root@docker-54 config]# 
[root@docker-54 config]# kubectl apply -f nfs-provisioner-rbac.yaml 
serviceaccount/nfs-client-provisioner unchanged
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner configured
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner unchanged
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner unchanged
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner unchanged
[root@docker-54 config]# 

这里由于我之前创建过一些 RBAC 权限这里有的显示 unchanged,首次执行这个应该created或者configured
可以看到,上面RBAC 里面配置了一个 serviceaccount以及它对应集群角色,然后是角色的绑定。接着是一个普通的角色以及普通角色的绑定

创建完权限,接着来创建 deployment:

[root@docker-54 config]# kubectl apply -f nfs-provisioner-deployment.yaml 
serviceaccount/nfs-client-provisioner unchanged
deployment.apps/nfs-client-provisioner configured
[root@docker-54 config]# 

接着创建 StorageClass:kubectl apply -f nfs-storage-class.yaml

[root@docker-54 config]# kubectl apply -f nfs-storage-class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
[root@docker-54 config]#

这里 StorageClass 也创建完成后,可以查看下:

[root@docker-54 config]# kubectl get sc
NAME                    PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage     fuseim.pri/ifs   Retain          Immediate           false                  60s
nfs-storage (default)   nfs-client       Delete          Immediate           false                  132d
[root@docker-54 config]# 

可以看到,这里确实多了一条记录managed-nfs-storage,并且 PROVISIONER 的值,也正是我们配置的 fuseim.pri/ifs,这个是我们后续使用时关联的一个标识

接着我们来看下上面创建的 Deployment :

[root@docker-54 config]# kubectl get po -n kube-system | grep nfs
nfs-client-provisioner-77bdfd69d9-9hzhx   1/1     Running   0              134m
[root@docker-54 config]# 

可以看到已经是正常运行状态了。

接下来我们创建statefulsetkubectl apply -f nfs-sc-demo-statefulset.yaml

[root@docker-54 config]# kubectl apply -f nfs-sc-demo-statefulset.yaml 
service/nginx-sc created
statefulset.apps/nginx-sc created
[root@docker-54 config]# 

接着看下应用的状态

[root@docker-54 config]# kubectl get sts
NAME       READY   AGE
nginx-sc   1/1     54s
[root@docker-54 config]# 
[root@docker-54 config]# kubectl get po | grep nginx
nginx-sc-0                     1/1     Running     0                115s
[root@docker-54 config]#

可以看到正常创建、并启动了。

6. 解决 PVC 为 Pending 状态问题

如果这里 Nginx 的 Pod 为 Pending 状态,则要检查下:kubectl describe po nginx-sc-0

Events:
  Type     Reason            Age    From               Message
  ----     ------            ----   ----               -------
  Warning  FailedScheduling  3m20s  default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.
  Normal   Scheduled         3m18s  default-scheduler  Successfully assigned default/nginx-sc-0 to docker-55
  Normal   Pulled            3m18s  kubelet            Container image "nginx" already present on machine
  Normal   Created           3m18s  kubelet            Created container nginx-sc
  Normal   Started           3m18s  kubelet            Started container nginx-sc
[root@docker-54 config]# 

如果状态异常,上面命令可以看到具体的原因。这里有个FailedScheduling的警告,提示我们三个节点都是可用的,但是 3 个 pod 还是 unbound ,意思是还未绑定到 PVC。

这时候可以排查下 PVC 的状态及原因:

[root@docker-54 config]# kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
nginx-sc-test-pvc-nginx-sc-0   Bound    pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            managed-nfs-storage   6m18s
[root@docker-54 config]# 

如果这里也为 Pending,状态,此时可能 PV 也是非正常的,可以使用 describe 看下具体原因或者看下 PV 的状态。

[root@docker-54 config]# kubectl get pv | grep nginx
pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            Retain           Bound       default/nginx-sc-test-pvc-nginx-sc-0   managed-nfs-storage            8m3s
[root@docker-54 config]#

我这里 PV 是正常的,是因为我修改了,k8s制备器的镜像,k8s 默认quay.io/external_storage/nfs-client-provisioner:latest 镜像,这个镜像需要用到 K8s 中的 一个 selfLink 的功能,但是从 1.20 版本之后,k8s 把这个功能给关掉了,可能是处于性能以及 API 调用请求的一个方向考虑的,把这个功能给禁用掉了,所以就意味着我们版本不能再直接使用这个镜像了。

我这里使用的版本v1.22.6

[root@docker-54 config]#   kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.6", GitCommit:"f59f5c2fda36e4036b49ec027e556a15456108f0", GitTreeState:"clean", BuildDate:"2022-01-19T17:33:06Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.6", GitCommit:"f59f5c2fda36e4036b49ec027e556a15456108f0", GitTreeState:"clean", BuildDate:"2022-01-19T17:26:47Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
[root@docker-54 config]# 

这里PVC 处于 Pending 状态有两种解决方案

vim /etc/kubernetes/manifests/kube-apiserver.yaml

spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false # 新增该行
    ......

修改后重新应用该配置,

kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml

这样可以解决因为版本导致 PVC pending 状态的问题。不过既然官方已经不支持了,我们也没必要强制修改让它支持,看下第二种方案。

gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0

registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0

修改镜像后,然后执行nfs-provisioner-deployment.yaml 更新deployment

当看到 Pod 的状态正常,PVC 和 PV 的状态正常后,就完事了。

7. 单独测试自动创建 PVC

如果我们想单独测试下这个自动创建 PVC ,那么可以这么操作

新建配置文件auto-pv-test-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: auto-pv-test-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 300Mi
  storageClassName: managed-nfs-storage

这里直接创建 PVC,并没有声明关于 PV 的内容,仅仅声明了 PVC 的名称、需要的资源、使用的 storageClassName

[root@docker-54 config]# kubectl apply -f auto-pv-test-pvc.yaml 
persistentvolumeclaim/auto-pv-test-pvc created
[root@docker-54 config]# 
[root@docker-54 config]# kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
auto-pv-test-pvc               Bound    pvc-1a180c44-a4d3-44e3-83d0-b69bbf73f2df   300Mi      RWO            managed-nfs-storage   26s
nginx-sc-test-pvc-nginx-sc-0   Bound    pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            managed-nfs-storage   47m
[root@docker-54 config]# 

可以看到,新建的 PVC auto-pv-test-pvc 已经正常绑定到名为pvc-1a180c44-a4d3-44e3-83d0-b69bbf73f2df的 PV 上了。这样也是可以达到自动创建 PVC 的目的。

在后续的使用中,我们使用自动创建 PVC 就不用关心 PV ,我们只需要写我们的需求就好了,系统可以根据我们的需求自动创建PV 来自动绑定

原文地址:https://blog.csdn.net/linmengmeng_1314/article/details/134622473

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_17207.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注