书籍来源:《CKA/CKAD应试指南:从Docker到Kubernetes完全攻略》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:CKA备考实验 | 汇总_热爱编程的通信人的博客-CSDN博客
NFS作为后端存储,用户需要自行配置nfs服务器。因为每个人都需要接触到后端存储,这样就带来了安全隐患,因为要配置存储,必须要用root用户,如果有人恶意删除或者拷贝其他人的存储数据,就会很麻烦。
Persistent Volume(持久性卷,简称pv)与指定后端存储关联,pv和后端存储都由专人来创建,pv不属于任何命名空间,全局可见。用户登录到自己的命名空间之后,只要创建pvc(Persistent Volume Claim,持久性卷声明)即可,pvc会自动和pv进行绑定,如图6-6所示。
这里创建了一个名字叫作pv01的pv和nfs服务器上的共享目录/zz相关联。某用户登录到自己项目ns01里,创建一个名字叫作pvc01的pvc和pv01绑定了。tom在ns01里创建了一个pod1,使用pvc01作为存储,往pod1里写的数据最终是写进存储服务器的/zz目录里了。
因为一个pv只能和一个pvc进行绑定,所以ns02里的pvc0x是不能和pv01绑定的(状态为Pending)。
PersistentVolume
本节讲解如何创建和删除pv,以及如何使用NFS作为后端存储的pv。
步骤1:请自行在192.168.26.30上创建共享目录/zz。
##########实操验证##########
[root@vms30 ~]# mkdir /zz
[root@vms30 ~]# chmod 666 /zz
[root@vms30 ~]# chown nfsnobody /zz
[root@vms30 ~]# cat /etc/exports
/123 *(rw,sync,no_root_squash)
/zz *(rw,sync,no_root_squash)
[root@vms30 ~]# exportfs -arv
exporting *:/zz
exporting *:/123
[root@vms30 ~]#
请特别注意权限,有选项no_root_squash。
步骤2:查看现有pv。
##########实操验证##########
[root@vms10 volume]# kubectl get pv
No resources found
[root@vms10 volume]#
步骤3:创建pv所需要的yaml文件pv1.yaml,内容如下。
##########实操验证##########
[root@vms10 volume]# cat pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /zz
server: 192.168.1.130
[root@vms10 volume]#
特别注意storage的大小和accessModes的值,这个是pvc和pv绑定的关键。accessModes有以下三个值。
ReadWriteOnce(RWO):仅允许单个节点挂载读写。
ReadOnlyMany(ROX):允许多个节点挂载只读。
ReadWriteMany(RWX):允许多个节点挂载读写。
如果pvc和pv的accessMode不一样,二者肯定是绑定不了的。
步骤4:创建并查看pv。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pv1.yaml
persistentvolume/pv01 created
[root@vms10 volume]#
[root@vms10 volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 5Gi RWO Recycle Available 12s
[root@vms10 volume]#
步骤5:查看此pv的属性。
##########实操验证##########
[root@vms10 volume]# kubectl describe pv pv01
Name: pv01
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass:
Status: Available
Claim:
Reclaim Policy: Recycle
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 5Gi
Node Affinity: <none>
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 192.168.1.130
Path: /zz
ReadOnly: false
Events: <none>
[root@vms10 volume]#
从这里可以看到,pv01所使用的后端存储类型是NFS,NFS的服务器是192.168.26.30,共享目录是/zz。
要删除pv,可以用下面的方法。
(1)kubectl delete -f pv1.yaml。
(2)kubectl delete pv pv名字。
步骤6:练习删除此pv。
##########实操验证##########
[root@vms10 volume]# kubectl delete -f pv1.yaml
persistentvolume "pv01" deleted
[root@vms10 volume]#
步骤7:再次创建出此pv。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pv1.yaml
persistentvolume/pv01 created
[root@vms10 volume]#
PersistentVolumeClaim
PersistentVolumeClaim是基于命名空间创建的,不同命名空间里的pvc互相隔离。
pvc通过storage的大小和accessModes的值与pv进行绑定,即如果pvc里storage的大小、accessModes的值和pv里storage的大小、accessModes的值都一样的话,那么pvc会自动和pv进行绑定。
步骤1:查看现有pvc。
##########实操验证##########
[root@vms10 volume]# kubectl get pvc
No resources found in nsvolume namespace.
[root@vms10 volume]#
步骤2:创建pvc所需要的yaml文件。
##########实操验证##########
[root@vms10 volume]# cat pvc1.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc01
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
[root@vms10 volume]#
这里创建一个名为pvc01的pvc,可以看到这里accessMode的值、storage大小完全和pv01的设置一样,所以pvc01可以绑定pv01。
步骤3:创建pvc并查看pvc和pv的绑定。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/pvc01 created
[root@vms10 volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Bound pv01 5Gi RWO 5s
[root@vms10 volume]#
此时pvc01和pv01进行了绑定。
步骤4:删除此pvc01。
##########实操验证##########
[root@vms10 volume]# kubectl delete -f pvc1.yaml
persistentvolumeclaim "pvc01" deleted
[root@vms10 volume]# kubectl get pvc
No resources found in nsvolume namespace.
[root@vms10 volume]#
步骤5:修改pvc01.yaml,把storage的大小改为6G。
##########实操验证##########
[root@vms10 volume]# cat pvc1.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc01
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 6Gi
[root@vms10 volume]#
这里storage的大小为6G,比pv里storage的5G要大,创建pvc并查看。
步骤6:创建并查看pvc。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/pvc01 created
[root@vms10 volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Pending 7s
[root@vms10 volume]#
可以看到pvc01并没有绑定到pv01上,状态为Pending。
步骤7:删除此pvc01并修改storage的大小为4G。
##########实操验证##########
[root@vms10 volume]# kubectl delete pvc pvc01
persistentvolumeclaim "pvc01" deleted
[root@vms10 volume]#
[root@vms10 volume]# cat pvc1.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc01
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 4Gi
[root@vms10 volume]#
步骤8:再次创建pvc并查看。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/pvc01 created
[root@vms10 volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Bound pv01 5Gi RWO 4s
[root@vms10 volume]#
结论:在pv和pvc的accessModes值相同的情况下,如果pv的storage大小大于等于pvc的storage的大小的话,是可以绑定的,如果pv的storage的大小小于pvc的storage的大小,是不能绑定的。
步骤9:删除pv01和pvc01。
storageClassName
现在存在一个问题,一个pv只能和一个pvc绑定,现在存在一个名叫pv01的pv,然后在不同的命名空间里创建了多个pvc(因为它们互相隔离,并不知道相互的设置),这些pvc的storage的大小与accessModes的值都能和pv01进行绑定,但是只有一个pvc能和pv绑定,其他都处于Pending状态,如图6-7所示,哪个pvc能和pv01绑定呢?
如果要控制哪个pvc能和pv01进行绑定,可以通过storageClassName进行控制。
在pv和pvc的storageClassName相同的情况下,再次去对比storage的大小和accessModes的值。
步骤1:创建pv的yaml文件。
##########实操验证##########
[root@vms10 volume]# cat pv2.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
storageClassName: xx
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /zz
server: 192.168.1.130
[root@vms10 volume]#
这里将pv的storageclassname设置为xx。
步骤2:创建pv并查看。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pv2.yaml
persistentvolume/pv01 created
[root@vms10 volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 5Gi RWO Recycle Available xx 9s
[root@vms10 volume]#
步骤3:创建pvc的yaml文件。
##########实操验证##########
[root@vms10 volume]# cat pvc2.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc01
spec:
storageClassName: yy
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
[root@vms10 volume]#
这里pvc的storageclassname设置为了yy。
从这里可以看到,pvc01的storage的大小和accessModes的值与pv01完全匹配,但是storageClassName的值不一样。
步骤4:创建pvc并查看。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pvc2.yaml
persistentvolumeclaim/pvc01 created
[root@vms10 volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Pending yy 12s
[root@vms10 volume]#
可以看到此pvc根本无法和pv01进行绑定。
步骤5:删除此pvc01,并把storageClassName的值改为xx,和pv01的值一样。
##########实操验证##########
[root@vms10 volume]# kubectl delete pvc pvc01
persistentvolumeclaim "pvc01" deleted
[root@vms10 volume]#
[root@vms10 volume]# cat pvc2.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc01
spec:
storageClassName: xx
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
[root@vms10 volume]#
步骤6:创建pvc并查看pvc。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pvc2.yaml
persistentvolumeclaim/pvc01 created
[root@vms10 volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Bound pv01 5Gi RWO xx 3s
[root@vms10 volume]#
现在已经绑定起来了。
使用持久性存储
如果要在pod里使用pvc的话,就需要在pod的yaml文件里创建一个pvc类型的卷,然后在pod的容器里挂载这个卷即可。
步骤1:创建pod所需要的yaml文件。
##########实操验证##########
[root@vms10 volume]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx1
spec:
volumes:
- name: myv
persistentVolumeClaim:
claimName: pvc01
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: "/mnt"
name: myv
[root@vms10 volume]#
在这个yaml文件里,创建了一个名字为myv的卷,此卷使用名字为pvc01的pvc。
pod里包含一个名字叫nginx的容器,容器使用刚刚定义的myv这个卷,并挂载到容器的/mnt里。
步骤2:创建pod并查看。
##########实操验证##########
[root@vms10 volume]# kubectl apply -f pod.yaml
pod/nginx1 created
[root@vms10 volume]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx1 1/1 Running 0 4s
[root@vms10 volume]#
步骤3:往nginx1的/mnt里拷贝一个文件。
##########实操验证##########
[root@vms10 volume]# kubectl cp /etc/services nginx1:/mnt
[root@vms10 volume]#
按照分析,往pod里写的东西就是往pv01里写,即往存储服务器写。
步骤4:切换到vms30,查看/zz里的内容。
##########实操验证##########
[root@vms30 ~]# ls /zz
services
[root@vms30 ~]#
可见和预期是一样的。
步骤5:自行删除此pod、pv、pvc。
pv回收策略
前面创建pv的时候,有一句persistentVolumeReclaimPolicy: Recycle,这句是用来指定pv回收策略的,即删除pvc之后pv是否会释放。有以下两种策略。
Recycle:删除pvc之后,会生成一个pod回收数据,删除pv里的数据,删除pvc之后,pv可复用,pv状态由Released变为Available。
Retain:不回收数据,删除pvc之后,pv依然不可用,pv状态长期保持为Released。需要手动删除pv,然后重新创建。但是删除pv的时候并不会删除里面的数据。