PersistentVolume(PV)是 K8S 集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源同样。 PV 是容量插件,如 Volumes,但其生命周期独立于使用 PV 的任何单个 Pod。 此 API 对象捕获存储实现的详细信息,包括 NFS,iSCSI 或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC)是 K8S 中由用户进行存储的请求。 它相似于 Pod。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 能够请求特定级别的资源(CPU和内存)。声明能够请求特定的大小和访问模式(例如,能够一次读/写或屡次只读)。
经过 storageClassName 参数来指定使用对应名字的 StorageClass,也就是 PVC 与 PV 具备相同的storageClassName,PVC 才能绑定到这个对应的 PV。PVC 能够不指定storageClassName,或者将该值设置为空,若是打开了准入控制插件,而且指定一个默认的 StorageClass,则 PVC 会使用默认的 StorageClass,不然就绑定到没有 StorageClass 的 PV 上。node
PV 是 K8S 群集中的资源。PVC 是对这些资源的请求,而且还充当对资源的检查。PV 和 PVC 之间的相互做用遵循如下生命周期:nginx
Provisioning ——> Binding ——> Using ——> Releasing ——> Recyclingdocker
注:目前只有 NFS 和 HostPath 类型卷支持回收策略,AWS EBS、GCE PD、Azure Disk、Cinder 支持删除 (Delete) 策略。vim
# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME test01 Ready master 17d v1.14.0 192.168.127.133 CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://18.9.3 test02 Ready 17d v1.14.0 192.168.127.135 CentOS Linux 7 (Core) 3.10.0-957.el7.x86_64 docker://18.9.3
PV 支持的类型不少,好比:RBD、CephFS、Glusterfs、NFS 等,这里使用 nfs 类型的 PV,并使用 Job 对象来验证 PV 建立以及 PVC 资源的申请与绑定。api
# yum install nfs-utils rpcbind -y # mkdir -p /data/nfs # vim /etc/exports /data/nfs *(rw,sync) # systemctl start nfs-server.service
并在 K8S node 上安装 nfs 客户端:# yum install nfs-utils -y
服务器
# cat pv_nfs.yml apiVersion: v1 kind: PersistentVolume metadata: name: nfspv1 spec: # 指定 PV 的容量为1Gi capacity: storage: 1Gi # 指定访问模式 accessModes: # PV 能以 readwrite 模式 mount 到单个节点 - ReadWriteOnce # 指定 PV 的回收策略,即 PVC 资源释放后的事件,recycle (不建议,使用动态供给代替)删除 PVC 的全部文件 persistentVolumeReclaimPolicy: Recycle # 指定 PV 的 class 为 mynfs,至关于为 PV 分类,PVC 将指定 class 申请 PV storageClassName: mynfs # 指定 PV 为 nfs 服务器上对应的目录 nfs: path: /data/nfs server: 192.168.127.133
应用 PV 配置:网络
# kubectl apply -f pv_nfs.yml persistentvolume/nfspv1 created
查看 PV 资源:app
# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE nfspv1 1Gi RWO Recycle Available
# cat pvc_nfs.yml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nfspvc1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: mynfs
应用 PVC 配置:ide
# kubectl apply -f pvc_nfs.yml persistentvolumeclaim/nfspvc1 created
查看 PVC 资源,经过下面的结果能够看到 nfspvc1 已经与 PV 为 nfspv1 绑定:学习
# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE nfspvc1 Bound nfspv1 1Gi RWO mynfs 25s </pre>
# cat pvjob.yml apiVersion: batch/v1 kind: Job metadata: name: pvjob spec: template: spec: containers: - name: bbox1 image: busybox command: ["/bin/sh","-c","echo 'hello pv' > /mydata/hello"] volumeMounts: - mountPath: "/mydata" name: mydata restartPolicy: Never volumes: - name: mydata persistentVolumeClaim: claimName: nfspvc1
该 job 将在 nfs 的 volume 建立一个 hello 文件,打印 hello pv 字符串。
应用该 Job 配置文件:
# kubectl apply -f pvjob.yml job.batch/pvjob created
确认容器状态是 Completed 状态:
# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deploy-nginx-684b85cd79-kv5sg 1/1 Running 2 10d 10.244.1.14 test02 pvjob-gljl7 0/1 Completed 0 39s 10.244.1.33 test02
确认 master 上 nfs 的 /data/nfs 目录,检查实验结果:
# cat /data/nfs/hello hello pv
在此次实验中出现了几个错误:
使用 PVC 存储的 Pod 一直处于 pending 状态,没法启动,经过命令 kubectl describe pod podname
查看对应报错的 Pod 的信息,部分报错信息以下:
# dmesg | tail or so. Warning FailedMount 118s kubelet, test02 MountVolume.SetUp failed for volume "nfspv1" : mount failed: exit status 32 Mounting command: systemd-run Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/d25895f2-8220-11e9-820c-000c295ab742/volumes/kubernetes.io~nfs/nfspv1 --scope -- mount -t nfs 192.168.127.133:/data/nfs /var/lib/kubelet/pods/d25895f2-8220-11e9-820c-000c295ab742/volumes/kubernetes.io~nfs/nfspv1 Output: Running scope as unit run-15184.scope. mount: wrong fs type, bad option, bad superblock on 192.168.127.133:/data/nfs, missing codepage or helper program, or other error (for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount. helper program
注意到报错信息:wrong fs type, bad option, bad superblock on 192.168.127.133:/data/nfs,若是没有安装 nfs-utils 软件包,没法识别 nfs 类型的文件系统,也没法做为 nfs 的客户端使用。
解决方案:
安装 nfs-utils 软件包,删除以前建立失败的 Job 资源并从新建立。
# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deploy-nginx-684b85cd79-kv5sg 1/1 Running 2 10d 10.244.1.14 test02 pvjob-4dp29 0/1 Error 0 3m10s 10.244.1.35 test02 pvjob-f6lpp 0/1 Error 0 2m33s 10.244.1.37 test02 pvjob-l8q6z 0/1 Error 0 2m13s 10.244.1.38 test02 pvjob-qbxx6 0/1 Error 0 53s 10.244.1.39 test02 pvjob-zcx6l 0/1 Error 0 2m56s 10.244.1.36 test02
经过查看执行失败 Pod 的 log 日志,发现是容器没有权限写文件到挂载的 nfs 目录中:
# kubectl logs pvjob-4dp29 /bin/sh: can't create /mydata/hello: Permission denied
解决方案:
Permission denied 多见于普通用户执行高权限命令失败,不过 busybox 容器自己使用的就是 root 用户,所以不存在这个问题。在 nfs 中,nfs 服务端没有权限访问挂载的目录也会致使这个问题。
更改目录属主为 nfsnobody:# chown nfsnobody /data/nfs
删除原来 Job 并从新建立后,Job 就能执行成功:
# kubectl delete -f pvjob.yml # kubectl apply -f pvjob.yml # kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES deploy-nginx-684b85cd79-kv5sg 1/1 Running 2 10d 10.244.1.14 test02 pvjob-gljl7 0/1 Completed 0 39s 10.244.1.33 test02