详解 NFS-CSI 的使用

image

1:为什么要使用nfs-csi

在很早之前,我们讲过一个使用nfs-subdir-external-provisioner来做nfs存储的方法,但是那个方法其实是根据不太规范的Pod使用volume挂载nfs实现的,并且它并非使用了标准的k8s存储接口,我们都知道csi(container storage interface)才是k8s标准的存储接口,所以就衍生出来我们使用csi的方案,其实基于CSI的存储已经有很多了,我们可以去如下github查看

# 基于NFS的CSI:https://github.com/kubernetes-csi/csi-driver-nfs
# 基于SMB的CSI:https://github.com/kubernetes-csi/csi-driver-smb
# 基于local的CSI:https://github.com/kubernetes-csi/csi-driver-host-path

# 当然还有更多的云厂商和一些开源的存储工具它们也提供了存储的方案,大家可以去选一选,这个在CNCF都可以找到几个,在这里我们列出几个
# Ceph
# CubeFS
# Longhorn
# Curve
# Juicefs
# Rook

# 这些都是开源的一些存储,它们同样也都支持CSI的方式,所以,我们后期的存储肯定是按照规范来了,所以nfs-subdir-external-provisioner一定不是长久之计,所以就有了现在的这篇文章

2:如何部署NFS-CSI

1:下载nfs-csi源码
[root@k-m-1 ~]# git clone https://github.com/kubernetes-csi/csi-driver-nfs.git

2:进入项目
[root@k-m-1 nfs-csi]# cd csi-driver-nfs

3:安装nfs-csi
[root@k-m-1 csi-driver-nfs]# ./deploy/install-driver.sh 
Installing NFS CSI driver, version: master ...
serviceaccount/csi-nfs-controller-sa unchanged
serviceaccount/csi-nfs-node-sa unchanged
clusterrole.rbac.authorization.k8s.io/nfs-external-provisioner-role unchanged
clusterrolebinding.rbac.authorization.k8s.io/nfs-csi-provisioner-binding unchanged
csidriver.storage.k8s.io/nfs.csi.k8s.io unchanged
deployment.apps/csi-nfs-controller unchanged
daemonset.apps/csi-nfs-node unchanged
NFS CSI driver installed successfully.

# 看到NFS CSI driver installed successfully证明安装好了,然后我们来看看这个程序
[root@k-m-1 ~]# kubectl get pod -n kube-system -l app=csi-nfs-node
NAME                 READY   STATUS    RESTARTS   AGE
csi-nfs-node-644bb   3/3     Running   0          9s
[root@k-m-1 ~]# kubectl get pod -n kube-system -l app=csi-nfs-controller
NAME                                  READY   STATUS    RESTARTS   AGE
csi-nfs-controller-767f94977c-h7kb5   4/4     Running   0          12s

# 看到Pod之后我们基本就算是部署好了,但是我们不能直接使用CSI,而是利用StorageClass来调用它,然后我们来创建这个StorageClass

[root@k-m-1 nfs-csi]# cd csi-driver-nfs/deploy/example

# 在这个目录下有一个storageclass-nfs.yaml,这里我们只需要更改如下内容
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
  annotations:
    # 此操作是1.25的以上的一个alpha的新功能,是将此storageclass设置为默认,这个在前面文章有讲过
    storageclass.kubernetes.io/is-default-class: "true"
# 此处指定了csidrivers的名称
provisioner: nfs.csi.k8s.io
parameters:
  # NFS的Server
  server: 10.0.0.11
  # NFS的存储路径
  share: /data
  # csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume
  # csi.storage.k8s.io/provisioner-secret-name: "mount-options"
  # csi.storage.k8s.io/provisioner-secret-namespace: "default"
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  # 这里不只可以配置nfs的版本
  - nfsvers=4.1
下面是关于parameters的一些参数
参数名称 意义 示例 强制参数 默认值
server NFS的服务地址 10.0.0.11 YES
share NFS共享的路径 / YES
subDir NFS 共享下的子目录 NO
mountPermissions 挂载的文件夹权限。默认值为,如果设置为非零,驱动程序将在挂载后执行0 chmod NO 不存在则创建
onDelete 删除卷时,如果目录是retain delete(默认值),retain NO delete
基本上我们保持默认就OK了,涉及不到太多的功能,我们只需要将上面的YAML的parameters的server和share改成自己的nfs的地址和path就OK了

# 查看StorageClass,然后测试
[root@k-m-1 example]# kubectl get sc
NAME            PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs (default)   nfs.csi.k8s.io   Delete          Immediate           false                  11h

# 部署如下YAML资源对象
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        command:
        - "/bin/bash"
        - "-c"
        - set -euo pipefail; while true; do echo $(date) >> /mnt/nfs/outfile; sleep 1; done
        volumeMounts:
        - name: data
          mountPath: /mnt/nfs
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
# 根据上面资源的说明会生成一个outfile,然后我们去持久化的PVC下看看

[root@k-m-1 ~]# kubectl get pod,pvc
NAME          READY   STATUS    RESTARTS   AGE
pod/nginx-0   1/1     Running   0          63s

NAME                                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/data-nginx-0   Bound    pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038   1Gi        RWO            nfs            63s
[root@k-m-1 ~]# ls /data/pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038/
outfile

# 这就说明,我们的CSI和StorageClass配置完成了,那么这就是我们用NFS-CSI替换nfs-subdir-external-provisioner的方法了,另外这个NFS的CSI它还支持snapshot功能,这个功能其实也算是个新功能了,在这个NFS-CSI也是支持,也不在我们的正常使用范围内,不过我们既然用到了它,我们就讲一下吧

3:NFS-CSI快照功能

我们如果要使用此功能,那么我么你需要安装一下这个CRD和控制器,还有Controller

# 部署CRD和Controller
[root@k-m-1 nfs-csi]# cd csi-driver-nfs/deploy
[root@k-m-1 deploy]# kubectl apply -f crd-csi-snapshot.yaml -f rbac-snapshot-controller.yaml -f csi-snapshot-controller.yaml 
customresourcedefinition.apiextensions.k8s.io/volumesnapshots.snapshot.storage.k8s.io created
customresourcedefinition.apiextensions.k8s.io/volumesnapshotclasses.snapshot.storage.k8s.io created
customresourcedefinition.apiextensions.k8s.io/volumesnapshotcontents.snapshot.storage.k8s.io created
serviceaccount/snapshot-controller created
clusterrole.rbac.authorization.k8s.io/snapshot-controller-runner created
clusterrolebinding.rbac.authorization.k8s.io/snapshot-controller-role created
role.rbac.authorization.k8s.io/snapshot-controller-leaderelection created
rolebinding.rbac.authorization.k8s.io/snapshot-controller-leaderelection created
deployment.apps/snapshot-controller created

[root@k-m-1 deploy]# kubectl get pod -A -l app=snapshot-controller
NAMESPACE     NAME                                   READY   STATUS    RESTARTS   AGE
kube-system   snapshot-controller-546868dfb4-r879h   1/1     Running   0          50s
kube-system   snapshot-controller-546868dfb4-rvhqc   1/1     Running   0          50s

[root@k-m-1 deploy]# kubectl api-resources | grep snapshot
volumesnapshotclasses             vsclass,vsclasses                               snapshot.storage.k8s.io/v1             false        VolumeSnapshotClass
volumesnapshotcontents            vsc,vscs                                        snapshot.storage.k8s.io/v1             false        VolumeSnapshotContent
volumesnapshots                   vs                                              snapshot.storage.k8s.io/v1             true         VolumeSnapshot

# OK这样就部署好了,我们可以根据官方去看看这个API如何使用
地址:https://kubernetes.io/docs/concepts/storage/volume-snapshots/

# 部署snapshotclass资源
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-nfs-snapclass
driver: nfs.csi.k8s.io
deletionPolicy: Delete
[root@k-m-1 nfs-csi]# cd csi-driver-nfs/deploy/example
[root@k-m-1 example]# kubectl apply -f snapshotclass-nfs.yaml 
volumesnapshotclass.snapshot.storage.k8s.io/csi-nfs-snapclass created
[root@k-m-1 example]# kubectl get vsclass
NAME                DRIVER           DELETIONPOLICY   AGE
csi-nfs-snapclass   nfs.csi.k8s.io   Delete           60s

# 我们来快照一下上面NFS的PVC

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: nginx-pvc-snapshot
spec:
  # 指定vsclass的名称
  volumeSnapshotClassName: csi-nfs-snapclass
  # 指定pvc资源名称
  source:
    persistentVolumeClaimName: data-nginx-0
[root@k-m-1 example]# kubectl apply -f snapshot-nfs-dynamic.yaml 
volumesnapshot.snapshot.storage.k8s.io/nginx-pvc-snapshot created

[root@k-m-1 example]# kubectl get vs
NAME                 READYTOUSE   SOURCEPVC      SOURCESNAPSHOTCONTENT   RESTORESIZE   ......
nginx-pvc-snapshot   true         data-nginx-0                           7577          ......

[root@k-m-1 example]# ls /data/snapshot-be2a23d0-4dc4-46fc-a619-56f340f09299/
pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038.tar.gz

[root@k-m-1 snapshot-be2a23d0-4dc4-46fc-a619-56f340f09299]# tar xf pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038.tar.gz 
[root@k-m-1 snapshot-be2a23d0-4dc4-46fc-a619-56f340f09299]# ls
outfile  pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038.tar.gz


# 我们备份好了之后我们可以去看看配置的csi的地址,里面会有一个snapshot的目录,然后里面是一个以PVC打包的tar.gz的文件,这个文件内就是快照下来的数据,这也就是我们要的一个快照功能,当然我们删除了这个资源之后,快照的文件也会跟着删除

[root@k-m-1 ~]# kubectl delete -f nfs-csi/csi-driver-nfs/deploy/example/snapshot-nfs-dynamic.yaml && ls /data
volumesnapshot.snapshot.storage.k8s.io "nginx-pvc-snapshot" deleted
pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038

# 然而这里面我们要知道的是,snapshot创建出来之后会随之创建一个声明周期管理的资源叫做VSC,这个资源主要包含如下信息
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  creationTimestamp: "2023-08-10T20:58:26Z"
  finalizers:
  - snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection
  generation: 1
  name: snapcontent-dbc9d70e-7c1b-4d51-bc56-567b702cde9a
  resourceVersion: "241853"
  uid: 1d8dc380-cbf3-4084-83ee-339ff23ef833
spec:
  deletionPolicy: Delete
  driver: nfs.csi.k8s.io
  source:
    volumeHandle: 10.0.0.11#data#pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038##
  volumeSnapshotClassName: csi-nfs-snapclass
  volumeSnapshotRef:
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    name: nginx-pvc-snapshot
    namespace: default
    resourceVersion: "241843"
    uid: dbc9d70e-7c1b-4d51-bc56-567b702cde9a
status:
  creationTime: 1691701106274486295
  readyToUse: true
  restoreSize: 10643
  snapshotHandle: 10.0.0.11#data#snapshot-dbc9d70e-7c1b-4d51-bc56-567b702cde9a#snapshot-dbc9d70e-7c1b-4d51-bc56-567b702cde9a#pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038
这个资源其实就是快照的一些详细信息,然后主要我们要知道的是,有了快照,怎么恢复呢?下面就是恢复数据的方法

4:使用NFS-CSI恢复备份的快照

# 找到要备份的名称

[root@k-m-1 ~]# kubectl get vs
NAME                 READYTOUSE   SOURCEPVC      SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS      .....
nginx-pvc-snapshot   true         data-nginx-0                           10643         csi-nfs-snapclass  ......

# 创建新的PVC从快照恢复数据
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: restore-nginx-pvc
spec:
  # 从这里指定快照
  dataSource:
    name: nginx-pvc-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
# 创建新的PVC并检查数据
[root@k-m-1 ~]# kubectl apply -f restore-nginx-pvc.yaml 
persistentvolumeclaim/restore-nginx-pvc created

# 检查新的PVC是否创建
[root@k-m-1 ~]# kubectl get pvc
NAME                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-nginx-0        Bound    pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038   1Gi        RWO            nfs            86m
restore-nginx-pvc   Bound    pvc-e4fb65b5-5898-4cd1-a0ad-7200864fef54   10Gi       RWO            nfs            9s

# 查看新的PVC的数据
[root@k-m-1 ~]# ls /data/
pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038/      pvc-e4fb65b5-5898-4cd1-a0ad-7200864fef54/      snapshot-dbc9d70e-7c1b-4d51-bc56-567b702cde9a/

# 查看快照内容
[root@k-m-1 ~]# ls /data/pvc-e4fb65b5-5898-4cd1-a0ad-7200864fef54/
outfile

# OK那么这就是基本上快照备份和恢复的功能啦,当然,我们也可以用于迁移存储,比如从nfs迁移到其他存储,这些都是可以的,当然我们需要知道一个道理,PVC是支持克隆功能的,但是这个功能也是需要CSI支持的,也就是从一个存在的PVC将数据克隆到另一个PVC,但是这个克隆操作是不可以跨命名空间的,这一点我们需要明白,下面我们来看看

5:克隆PVC

# 查看PVC
[root@k-m-1 ~]# kubectl get pvc
NAME                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-nginx-0        Bound    pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038   1Gi        RWO            nfs            95m
restore-nginx-pvc   Bound    pvc-e4fb65b5-5898-4cd1-a0ad-7200864fef54   10Gi       RWO            nfs            9m9s

# 我们的pvc在default的名称空间,我们将其克隆到其他命名空间
# 创建一个新的namespace
[root@k-m-1 ~]# kubectl create ns clone-namespace
namespace/clone-namespace created

# 创建PVC克隆Default的内的restore-nginx-pvc的数据
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: clone-of-default-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      # 此值一定要大于或者等于需要克隆的PVC,否则无法创建
      storage: 10Gi
  dataSource:
    kind: PersistentVolumeClaim
    name: restore-nginx-pvc
# 创建此PVC
[root@k-m-1 ~]# kubectl get pvc
NAME                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
clone-of-default-pvc   Bound    pvc-478731d8-f389-4d4f-a11a-5802d299ace8   10Gi       RWO            nfs            9s
data-nginx-0           Bound    pvc-1bdd032a-c7ee-4e03-8b81-fc04e4ea2038   1Gi        RWO            nfs            107m
restore-nginx-pvc      Bound    pvc-e4fb65b5-5898-4cd1-a0ad-7200864fef54   10Gi       RWO            nfs            21m

# 查看克隆的数据
[root@k-m-1 ~]# ls /data/pvc-478731d8-f389-4d4f-a11a-5802d299ace8/
outfile

# 可以看到一模一样的,那么这就是克隆PVC的功能,这就是NFS-CSI的基本功能了,其他更高级的功能,我们还可以去参考最上面我给出的几个开源存储,它们会基于CSI开发更多的功能,这个大家可以自己去探索了
posted @ 2023-08-11 05:50  Layzer  阅读(1857)  评论(0编辑  收藏  举报