书籍来源:《CKA/CKAD应试指南:从Docker到Kubernetes完全攻略》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:CKA备考实验 | 汇总_热爱编程的通信人的博客-CSDN博客
前面讲持久性存储的时候,是要先创建pv,然后才能创建pvc。如果不同的命名空间里同时要创建不同的pvc,那么就需要提前把pv创建好,这样才能为pvc提供存储。这种操作方式太过于麻烦,所以可以通过storageClass(简称为sc)来解决这个问题。
最终的效果是,管理员不需要提前创建pv,只要创建好storageClasss之后就不用管pv了,用户创建pvc的时候,storageClass会自动创建出来一个pv和这个pvc进行绑定。
storageClass的工作流程
定义storageClass时必须要包含一个分配器(provisioner),不同的分配器指定了动态创建pv时使用什么后端存储。先看下面的三个例子。
第一个例子,分配器使用aws的ebs作为pv的后端存储。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
第二个例子,分配器使用lvm作为pv的后端存储。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-lvm
provisioner: lvmplugin.csi.alibabacloud.com
parameters:
vgName: volumegroup1
fsType: ext4
reclaimPolicy: Delete
第三个例子,使用hostPath作为pv的后端存储。
apiVersion: storage.k8s.io/vi
kind: StorageClass
metadata:
name: csi-hostpath-sc
provisioner: hostpath.csi.k8s.io
reclaimPolicy: Delete
#volumeBindingMode: Immediate
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
这三个例子里,三个storageClass分别使用了不同的分配器,这些分配器有的是以aws-ebs作为pv的后端存储,有的是以lv作为pv的后端存储,有的是以hostPath作为pv的后端存储。
上面三个例子里所使用的分配器中,有的是kubernetes内置的分配器,比如http://kubernetes.io/aws-ebs,其他两个分配器不是kubernetes自带的。kubernetes自带的分配器包括如下几种。
http://kubernetes.io/glusterfs;
http://kubernetes.io/vsphere-volume;
http://kubernetes.io/azure-disk;
http://kubernetes.io/azure-file;
http://kubernetes.io/portworx-volume;
http://kubernetes.io/storageos;
http://kubernetes.io/no-provisioner。
在用storageClass动态创建pv的时候,根据使用后端存储的不同,应该选择一个合适的分配器,但是像http://lvmplugin.csi.alibabacloud.com和http://hostpath.csi.k8s.io这样的分配器,既然不是kubernetes自带的,那是哪里来的呢?
这些非内置的分配器暂且称为外部分配器,这些外部分配器由第三方提供,是通过自定义CSIDriver(容器存储接口驱动)来实现的分配器。
所以整个流程就是,管理员创建storageClass时会通过.provisioner字段指定分配器。管理员创建好storageClass之后,用户在定义pvc时需要通过.spec.storageClassName指定使用哪个storageClass,如图6-8所示。
当创建pvc的时候,系统会通知storageClass,storageClass会通过它所关联的分配器来获取后端存储类型,然后动态地创建一个pv和此pvc进行绑定。
利用nfs创建动态卷供应
前面已经用NFS配置过共享文件夹了,因为配置起来相对简单,所以这里以NFS作为后端存储来配置动态卷供应。
步骤1:自行在存储服务器192.168.26.30上创建一个目录/vdisk,并共享这个目录。
##########实操验证##########
[root@vms30 ~]# mkdir /vdisk
[root@vms30 ~]# chmod 666 /vdisk
[root@vms30 ~]# chown nfsnobody /vdisk
[root@vms30 ~]# cat /etc/exports
/123 *(rw,async,no_root_squash)
/zz *(rw,async,no_root_squash)
/vdisk *(rw,async,no_root_squash)
[root@vms30 ~]# exportfs -avr
exporting *:/vdisk
exporting *:/zz
exporting *:/123
[root@vms30 ~]#
因为kubernetes里,NFS没有内置分配器,所以需要下载相关插件来创建NFS外部分配器。
步骤2:在vms10上先安装git客户端工具。
##########实操验证##########
[root@vms10 volume]# yum install git -y
步骤3:克隆项目并进入目录。
##########实操验证##########
# 该项目已经过期,在github下载ZIP包后传到vms10机器上
[root@vms10 volume]# unzip external-storage-master.zip
[root@vms10 volume]# cd external-storage-master/nfs-client/deploy/
[root@vms10 deploy]#
步骤4:部署rbac权限。
关于权限的设置后面章节会讲解,因为是在命名空间nsvolume里的,所以需要把rbac.yaml里指定的命名空间更换为nsvolume,然后部署rbac。
##########实操验证##########
[root@vms10 deploy]# sed -i 's/namespace: default/namespace: nsvolume/g' rbac.yaml
[root@vms10 deploy]#
[root@vms10 deploy]# kubectl apply -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
[root@vms10 deploy]#
注意:上述命令namespace: 后面有一个空格。
步骤5:修改/etc/kubernetes/manifests/kube-apiserver.yaml。
在kubernetes v1.20及之后的版本里,还需要修改/etc/kubernetes/manifests/kube-apiserver.yaml,增加:
##########实操验证##########
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
- --feature-gates=RemoveSelfLink=false
image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.21.1
然后重启kubelet。
部署NFS分配器
因为NFS分配器不是自带的,所以这里需要先把NFS分配器创建出来。
步骤1:用vim编辑器打开deployment.yaml,修改如下内容。
##########实操验证##########
[root@vms10 deploy]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: nsvolume
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 192.168.1.130
- name: NFS_PATH
value: /vdisk
volumes:
- name: nfs-client-root
nfs:
server: 192.168.1.130
path: /vdisk
[root@vms10 deploy]#
(1)因为当前是在命名空间nsvolume里的,所以要把namespace的值改为nsvolume。
(2)image后面的镜像需要提前在所有节点上pull下来,并修改镜像下载策略。
(3)env字段里,PROVISIONER_NAME用于指定分配器的名字,这里是fuseim.pri/ifs,NFS_SERVER和NFS_PATH分别指定这个分配器所使用的存储信息。
(4)在volumes的server和path里指定共享服务器和目录。
步骤2:部署NFS分配器。
##########实操验证##########
[root@vms10 deploy]# kubectl apply -f deployment.yaml
deployment.apps/nfs-client-provisioner created
[root@vms10 deploy]#
步骤3:查看pod的运行情况。
##########实操验证##########
[root@vms10 deploy]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-655cd6cd54-twpx7 1/1 Running 0 69s
[root@vms10 deploy]#
部署storageClass
创建了NFS分配器之后,下面开始创建一个使用这个分配器的storageClass。
步骤1:创建storageClass。
在当前目录里有一个名为class.yaml的文件,用于创建storageClass,内容如下。
##########实操验证##########
[root@vms10 deploy]# cat class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "false"
[root@vms10 deploy]#
这里provisioner的值fuseim.pri/ifs是由deployment.yaml文件里指定的分配器的名字,这个yaml文件的意思是创建一个名字是managed-nfs-storage的storageClass,使用名字为fuseim.pri/ifs的分配器。
步骤2:查看现在是否存在storageClass。
##########实操验证##########
[root@vms10 deploy]# kubectl get sc
No resources found
[root@vms10 deploy]#
步骤3:部署并查看storag Class。
##########实操验证##########
[root@vms10 deploy]# kubectl apply -f class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
[root@vms10 deploy]#
[root@vms10 deploy]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
managed-nfs-storage fuseim.pri/ifs Delete Immediate false 6s
[root@vms10 deploy]#
步骤4:查看当前是否存在pvc和pv。
##########实操验证##########
[root@vms10 deploy]# kubectl get pvc
No resources found in nsvolume namespace.
[root@vms10 deploy]# kubectl get pv
No resources found
[root@vms10 deploy]#
当前不存在任何pv和pvc。
步骤5:下面开始创建pvc。
##########实操验证##########
[root@vms10 deploy]# cp test-claim.yaml pvc1.yaml
[root@vms10 deploy]# cat pvc1.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
[root@vms10 deploy]#
这里在annotations里指定了使用哪个storageClass,也可以写成如下内容。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
storageClassName: managed-nfs-storage
步骤6:下面开始创建pvc。
##########实操验证##########
[root@vms10 deploy]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/test-claim created
[root@vms10 deploy]#
步骤7:查看是否创建出来了pvc。
##########实操验证##########
[root@vms10 deploy]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pvc-29465736-900f-4256-a777-c687cae46327 1Mi RWX managed-nfs-storage 6s
[root@vms10 deploy]#
步骤8:查看pv。
##########实操验证##########
[root@vms10 deploy]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-29465736-900f-4256-a777-c687cae46327 1Mi RWX Delete Bound nsvolume/pvc1 managed-nfs-storage 18s
[root@vms10 deploy]#
从这里可以看到,不仅把pvc1创建出来了,也创建出来一个名字叫作pvc-29465736-900f-4256-a777-c687cae46327的pv,并且和pvc1关联在一起了。
步骤9:查看这个pv的属性。
##########实操验证##########
[root@vms10 deploy]# kubectl describe pv pvc-29465736-900f-4256-a777-c687cae46327
Name: pvc-29465736-900f-4256-a777-c687cae46327
Labels: <none>
Annotations: pv.kubernetes.io/provisioned-by: fuseim.pri/ifs
Finalizers: [kubernetes.io/pv-protection]
StorageClass: managed-nfs-storage
Status: Bound
Claim: nsvolume/pvc1
Reclaim Policy: Delete
Access Modes: RWX
VolumeMode: Filesystem
Capacity: 1Mi
Node Affinity: <none>
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 192.168.1.130
Path: /vdisk/nsvolume-pvc1-pvc-29465736-900f-4256-a777-c687cae46327
ReadOnly: false
Events: <none>
[root@vms10 deploy]#
可以看到这个pv所使用的存储类型为NFS。