容器服务 Kubernetes 版CSI支持subpath方式和filesystem方式两种类型的NAS动态存储卷挂载,您可以通过容器服务控制台或kubectl两种方式进行挂载。本文介绍如何使用阿里云NAS动态存储卷,以及如何验证NAS存储卷的持久化存储与共享存储特性。
前提条件
已创建ACK集群。具体操作,请参见创建Kubernetes托管版集群。
ACK集群中CSI组件已升级至最新版本。更多信息,请参见管理CSI组件。
使用场景
对磁盘I/O要求较高的应用。
读写性能相对于对象存储OSS高。
实现跨主机文件共享,例如可作为文件服务器。
注意事项
NAS为共享存储,可以同时为多个Pod提供共享存储服务,即一个PVC可以同时被多个应用使用。关于NAS并发写入的一些限制条件,请参见如何避免多进程或多客户端并发写同一日志文件可能出现的异常?和如何解决向NFS文件系统中写入数据延迟问题?
在使用极速NAS文件系统时,配置动态存储卷StorageClass中的
path
需要以/share为父目录。例如,0cd8b4a576-g****.cn-hangzhou.nas.aliyuncs.com:/share/subpath
表示Pod挂载的NAS文件系统子目录为/share/subpath
。NAS PVC的容量仅在文件系统类型为通用型NAS,且StorageClass设置
allowVolumeExpansion
为true
时才会生效。此时,CSI将按照PVC容量设置NAS目录配额。NAS目录配额单位为GiB,实际设置的容量上限为PVC容量按GiB单位向上取整。NAS配额的生效是异步的,即PV动态创建后,目录配额不能保证立即生效,且快速连续写入大量数据可能会超出设置的容量上限。关于NAS目录配额的更多信息,请参见目录配额。
若您在应用模板中配置了securityContext.fsgroup参数,kubelet在存储卷挂载完成后会执行
chmod
或chown
操作,导致挂载时间延长。说明若已配置
securityContext.fsgroup
参数,并且需要减少挂载时间,请参见NAS存储卷挂载时间延长。
NAS动态存储卷的挂载方式为subpath类型时,您需要手动创建NAS文件系统和挂载点。
创建NAS文件系统和挂载点。
创建StorageClass。
创建并复制以下内容到alicloud-nas-subpath.yaml文件中。
allowVolumeExpansion: true apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: alicloud-nas-subpath mountOptions: - nolock,tcp,noresvport - vers=3 parameters: volumeAs: subpath server: "0cd8b4a576-g****.cn-hangzhou.nas.aliyuncs.com:/k8s/" provisioner: nasplugin.csi.alibabacloud.com reclaimPolicy: Retain
参数
描述
allowVolumeExpansion
仅通用型NAS文件系统支持设置此参数。开启时,该StorageClass动态创建的PV将会被配置NAS目录配额,并支持通过编辑PVC进行卷容量扩容。
mountOptions
挂载NAS的
options
参数在mountOptions
中配置,包括NFS协议版本。volumeAs
可选
subpath
、filesystem
,分别表示创建子目录类型的PV和文件系统类型的PV。server
表示创建子目录类型的PV时,NAS文件系统的挂载点地址。
重要此处需替换为实际的挂载点地址,关于如何查看挂载点地址,请参见查看挂载点地址。
provisioner
驱动类型。本例中取值为
nasplugin.csi.alibabacloud.com
,表示使用阿里云NAS CSI插件。reclaimPolicy
PV的回收策略,默认为
Delete
,支持Retain
。Delete模式:需配合
archiveOnDelete
一起使用。当
archiveOnDelete
为true
时,删除PVC时,PV和NAS文件只会被重命名,不会被删除。当
archiveOnDelete
为false
时,删除PVC时,PV和NAS文件会被真正删除。
Retain模式:删除PVC的时候,PV和NAS文件系统不会被删除,需要您手动删除。
如果数据安全性要求高,推荐使用
Retain
方式以免误删数据。archiveOnDelete
表示在
reclaimPolicy
为Delete
时,是否删除后端存储。因为NAS为共享存储,添加此选项进行双重确认。在参数parameters
下配置。默认为
true
,表示不会真正删除目录或文件,而是将其重命名,格式为archived-{pvName}.{timestamp}
。若配置为
false
,表示会真正删除后端对应的存储资源。
说明业务流量非常大时,不建议配置为false。更多信息,请参见使用NAS动态存储卷时Controller的任务队列已满且无法创建新的PV。
执行以下命令创建StorageClass。
kubectl create -f alicloud-nas-subpath.yaml
执行以下命令创建PVC。
创建并复制以下内容到pvc.yaml文件中。
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nas-csi-pvc spec: accessModes: - ReadWriteMany storageClassName: alicloud-nas-subpath resources: requests: storage: 20Gi
参数
说明
name
PVC的名称。
accessModes
配置访问模式。默认为
ReadWriteMany
,也可选择ReadWriteOnce
或ReadOnlyMany
。storageClassName
StorageClass的名称,用于绑定StorageClass。
storage
声明应用存储使用量。
重要此处设置的容量值不会限制应用实际可以使用的容量,且不会自动扩容。仅当使用通用型NAS,且StorageClass的
allowVolumeExpansion
为true时,才会为NAS目录设置配额。执行以下命令创建PVC。
kubectl create -f pvc.yaml
执行以下命令创建应用。
创建应用nginx-1和nginx-2共享NAS存储卷的同一个子目录。
创建并复制以下内容到nginx-1.yaml文件中。
apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nas-1 labels: app: nginx-1 spec: selector: matchLabels: app: nginx-1 template: metadata: labels: app: nginx-1 spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: nas-pvc mountPath: "/data" volumes: - name: nas-pvc persistentVolumeClaim: claimName: nas-csi-pvc
mountPath
:NAS在容器中挂载的位置。claimName
:PVC的名称,用于绑定PVC。本例中为nas-csi-pvc。
创建并复制以下内容到nginx-2.yaml文件中。
apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nas-2 labels: app: nginx-2 spec: selector: matchLabels: app: nginx-2 template: metadata: labels: app: nginx-2 spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: nas-pvc mountPath: "/data" volumes: - name: nas-pvc persistentVolumeClaim: claimName: nas-csi-pvc
mountPath
:NAS在容器中挂载的位置。本例为/data。claimName
:输入与nginx-1应用相同的PVC名称,本例为nas-csi-pvc。
执行以下命令创建应用nginx-1和nginx-2。
kubectl create -f nginx-1.yaml -f nginx-2.yaml
执行以下命令查看Pod信息。
kubectl get pod
预期输出:
NAME READY STATUS RESTARTS AGE deployment-nas-1-5b5cdb85f6-n**** 1/1 Running 0 32s deployment-nas-2-c5bb4746c-4**** 1/1 Running 0 32s
说明NAS存储卷的
0cd8b4a576-g****.cn-hangzhou.nas.aliyuncs.com:/share/nas-79438493-f3e0-11e9-bbe5-00163e09****
会同时挂载到deployment-nas-1-5b5cdb85f6-n****
和deployment-nas-2-c5bb4746c-4****
的/data目录下。其中:/share
:StorageClass中指定的subpath。nas-79438493-f3e0-11e9-bbe5-00163e09****
:PV的名称。
如果您需要为不同的Pod挂载同一个NAS文件系统的不同子目录,则需要分别创建pvc-1和nginx-1以及pvc-2和nginx-2。
验证NAS的持久化存储
NAS提供了持久化存储服务,当某个Pod删除时,重新部署的Pod将自动同步之前Pod的所有数据。
根据以下示例验证NAS的持久化存储特性:
查看部署应用的Pod和NAS文件。
执行以下命令,查看部署的应用所在Pod的名称。
kubectl get pod
预期输出:
NAME READY STATUS RESTARTS AGE deployment-nas-1-5b5cdb85f6-n**** 1/1 Running 0 32s deployment-nas-2-c5bb4746c-4**** 1/1 Running 0 32s
执行以下命令,查看任意一个Pod/data路径下的文件,本文以名为
deployment-nas-1-5b5cdb85f6-n****
的Pod为例。kubectl exec deployment-nas-1-5b5cdb85f6-n**** -- ls /data
无返回结果,表明/data路径下无文件。
执行以下命令,在名为
deployment-nas-1-5b5cdb85f6-n****
的Pod/data路径下创建文件nas。kubectl exec deployment-nas-1-5b5cdb85f6-n**** -- touch /data/nas
执行以下命令,查看名为
deployment-nas-1-5b5cdb85f6-n****
的Pod/data路径下的文件。kubectl exec deployment-nas-1-5b5cdb85f6-n**** -- ls /data
预期输出:
nas
执行以下命令,删除Pod。
kubectl delete pod deployment-nas-1-5b5cdb85f6-n****
同时在另一个窗口中,执行以下命令,查看Pod删除及Kubernetes重建Pod的过程。
kubectl get pod -w -l app=nginx
验证删除Pod后,NAS里创建的文件是否还存在。
执行以下命令,查看Kubernetes重建的Pod名称。
kubectl get pod
预期输出:
NAME READY STATUS RESTARTS AGE deployment-nas-1-5b5cdm2g5-m**** 1/1 Running 0 32s deployment-nas-2-c5bb4746c-4**** 1/1 Running 0 32s
执行以下命令,查看名为
deployment-nas-1-5b5cdm2g5-m****
的Pod/data路径下的文件。kubectl exec deployment-nas-1-5b5cdm2g5-m**** -- ls /data
预期输出:
nas
nas
文件仍然存在,说明NAS的数据可持久化保存。
验证NAS存储卷的共享存储
NAS存储卷支持同时被多个Pod挂载,当某个Pod修改数据时,其余Pod将自行实现数据的同步。
根据以下示例验证NAS存储卷的共享存储特性:
查看部署的应用所在的Pod和NAS文件。
执行以下命令,查看应用所在的Pod名称。
kubectl get pod
预期输出:
NAME READY STATUS RESTARTS AGE deployment-nas-1-5b5cdb85f6-n**** 1/1 Running 0 32s deployment-nas-2-c5bb4746c-4**** 1/1 Running 0 32s
执行以下命令,查看2个Pod/data路径下的文件。
kubectl exec deployment-nas-1-5b5cdb85f6-n**** -- ls /data kubectl exec deployment-nas-2-c5bb4746c-4**** -- ls /data
执行以下命令,在任意一个Pod的/data路径下创建文件nas。
kubectl exec deployment-nas-1-5b5cdb85f6-n**** -- touch /data/nas
执行以下命令,查看2个Pod/data路径下的文件。
执行以下命令,查看名为
deployment-nas-1-5b5cdb85f6-n****
的Pod/data路径下的文件。kubectl exec deployment-nas-1-5b5cdb85f6-n**** -- ls /data
预期输出:
nas
执行以下命令,查看名为
deployment-nas-2-c5bb4746c-4****
的Pod /data路径下的文件。kubectl exec deployment-nas-2-c5bb4746c-4**** -- ls /data
预期输出:
nas
在任意一个Pod的/data下创建的文件,两个Pod下的/data路径下均存在此文件,说明两个Pod共享一个NAS。
支持用户或用户组隔离
使用以下YAML内容,在容器组内使用nobody用户启动进程,创建的目录UID和GID为65534。
apiVersion: apps/v1 kind: StatefulSet metadata: name: nas-sts spec: selector: matchLabels: app: busybox serviceName: "busybox" replicas: 1 template: metadata: labels: app: busybox spec: securityContext: fsGroup: 65534 #创建目录/文件时,UID/GID为65534(nobody用户)。 fsGroupChangePolicy: "OnRootMismatch" #只有根目录的属主与访问权限与卷所期望的权限不一致时, 才改变其中内容的属主和访问权限。 containers: - name: busybox image: busybox command: - sleep - "3600" securityContext: runAsUser: 65534 #所有容器内的进程都使用用户ID为65534(nobody用户)来运行。 runAsGroup: 65534 #所有容器中的进程都以主组ID为65534(nobody用户)来运行。 allowPrivilegeEscalation: false volumeMounts: - name: nas-pvc mountPath: /data volumeClaimTemplates: - metadata: name: nas-pvc spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "alicloud-nas-subpath" resources: requests: storage: 100Gi
执行以下命令,在容器中启动
top
命令,查看USER是否为nobody。kubectl exec nas-sts-0 -- "top"
预期输出:
Mem: 11538180K used, 52037796K free, 5052K shrd, 253696K buff, 8865272K cached CPU: 0.1% usr 0.1% sys 0.0% nic 99.7% idle 0.0% io 0.0% irq 0.0% sirq Load average: 0.76 0.60 0.58 1/1458 54 PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND 49 0 nobody R 1328 0.0 9 0.0 top 1 0 nobody S 1316 0.0 10 0.0 sleep 3600
预期输出表明,是
nobody
用户执行的top
命令。执行以下命令,验证在NAS挂载目录下创建的目录和文件是否为
nobody
。kubectl exec nas-sts-0 -- sh -c "touch /data/test; mkdir /data/test-dir; ls -arlth /data/"
预期输出:
total 5K drwxr-xr-x 1 root root 4.0K Aug 30 10:14 .. drwxr-sr-x 2 nobody nobody 4.0K Aug 30 10:14 test-dir -rw-r--r-- 1 nobody nobody 0 Aug 30 10:14 test drwxrwsrwx 3 root nobody 4.0K Aug 30 10:14 .
预期输出表明,在
/data
下创建的test文件和test-dir目录中,UID和GID对应的用户均为nobody用户。
- 本页导读 (1)