跳转到主要内容

使用nfs-storageClass

  • storageClass (存储类)


k8s持久化存储有多种方式,当我们没有条件使用ceph时候,NFS存储则成了我们的理想选择;通常的的作法有两种,这两种方法都有弊端和明显的弊端:

  • 在每一台node上挂载主机nfs目录,然后在容器上映射到主机目录
    • 由于对用到主机磁盘路径完全依靠手工填写,需要每个容器、至少是namespace级别统一规划好路径,否则很容易发生文件夹冲突

  • 使用PV/PVC,先创建PV,映射到NFS,在创建PVC,绑定到PV
    • 项目一多,创建起来非常麻烦

storageClass则是为了解决这个问题而诞生,他能够根据一组配置,自动生产PV/PVC


  • 安装


  • nfs-storage-rabc.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  # 替换为你的namespace
  namespace: default
---
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
    # replace with namespace where provisioner is deployed
    # 替换为你的namespace
    namespace: default
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
  # replace with namespace where provisioner is deployed
  # 替换为你的namespace
  namespace: default
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
  # replace with namespace where provisioner is deployed
  # 替换为你的namespace
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    # 替换为你的namespace
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

  • nfs-storage-provisioner

这其实是一个容器,他会进行一些列的API监视,然后根据给定的参数创建PV/PVC并进行绑定。

需要设置的参数:

# env:
#  - PROVISIONER_NAME:名称,这个地方在后面创建storageClass时候回用到
#  - NFS_SERVER:nfs服务器地址
#  - NFS_PATH: nfs路径
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          # image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          image: k8s.dockerproxy.com/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              # value: <YOUR NFS SERVER HOSTNAME>
              value: 192.168.5.10
            - name: NFS_PATH
              # value: /var/nfs
              value: /data/share
      volumes:
        - name: nfs-client-root
          nfs:
            # server: <YOUR NFS SERVER HOSTNAME>
            server: 192.168.5.10
            path: /data/share

  • nfs-storage-class

provisioner参数需要和PROVISIONER_NAME参数对应

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
 # or choose another name, must match deployment's env PROVISIONER_NAME'
 # 替换为 provisioner pod 的 环境变量 PROVISIONER_NAME
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner 
parameters:
  # 此处也可以使用 "${.PVC.namespace}/${.PVC.name}" 来使用pvc的名称作为nfs中真实目录名称
  pathPattern: "${.PVC.namespace}/${.PVC.annotations.nfs.io/storage-path}"
  # 删除PVC时候的策略,delete :删除目录,retain保留目录
  onDelete: retain  
  # 删除PVC时候的策略,如果存在本项,且值为false,删除目录;如果存在 onDelete 设置,则以 onDelete 设置为准
  archiveOnDelete: false  
  
# 回收策略 Retain – 手动回收,Recycle – 需要擦除后才能再次使用,Delete – 当用户删除对应的 PersistentVolumeClaim 时,动态配置的 volume 将被自动删除。默认为 Delete
reclaimPolicy: Retain 
  • nfs-sotrage-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-default
  annotations:
    nfs.io/storage-path: "default-pvc" # not required, depending on whether this annotation was shown in the storage class description
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  • 执行安装
kubectl apply -f nfs-storage-rabc.yaml
kubectl apply -f nfs-storage-provisioner.yaml
kubectl apply -f nfs-storage-class.yaml

# 非必要
# 因为前文的storage-class路径规则为 "${.PVC.namespace}/${.PVC.annotations.nfs.io/storage-path}"
# 由于rancher界面使用快捷创建、预创建PVC,不支持增加注释,需要复制到导入YAML进行执行,如果你想指定到不同的路径下,可以执行这个

kubectl apply -f nfs-storage-pvc.yaml

  • 使用存储类


  • 预创建PVC

  • 快捷创建

    也可以在创建POD的时候,在添加数据卷的时候直接使用或者新建PVC,存储类选择给定的storageClass,配置选项与预创建一致

  • 最佳实践