Kubernetes(k8s)存储管理之数据卷volumes(五):动态制备-存储类StorageClass - 人生的...
source link: https://www.cnblogs.com/renshengdezheli/p/16972814.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
一.系统环境
服务器版本 | docker软件版本 | Kubernetes(k8s)集群版本 | CPU架构 |
---|---|---|---|
CentOS Linux release 7.4.1708 (Core) | Docker version 20.10.12 | v1.21.9 | x86_64 |
Kubernetes集群架构:k8scloude1作为master节点,k8scloude2,k8scloude3作为worker节点
服务器 | 操作系统版本 | CPU架构 | 进程 | 功能描述 |
---|---|---|---|---|
k8scloude1/192.168.110.130 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master节点 |
k8scloude2/192.168.110.129 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
k8scloude3/192.168.110.128 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
Kubernetes(k8s)数据卷volumes类型众多,本文介绍使用存储类StorageClass动态制备持久卷Persistent Volume,关于静态制备持久卷Persistent Volume,请查看博客《Kubernetes(k8s)存储管理之数据卷volumes(四):持久卷Persistent Volume》。
使用数据卷volumes的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》。
三.静态制备和动态制备
创建持久卷Persistent Volume有两种方法:静态制备和动态制备 。
静态制备(集群管理员创建若干 PV 卷。这些卷对象带有真实存储的细节信息, 并且对集群用户可用。PV 卷对象存在于 Kubernetes API 中,可供用户消费使用),简言之就是需要先创建pv,然后才能创建PVC。
动态制备 (如果管理员所创建的所有静态 PV 卷都无法与用户的 PersistentVolumeClaim 匹配, 集群可以尝试为该 PVC 申领动态制备一个存储卷。 这一制备操作是基于 StorageClass 来实现的:PVC 申领必须请求某个 存储类, 同时集群管理员必须已经创建并配置了该类,这样动态制备卷的动作才会发生。 如果 PVC 申领指定存储类为 "",则相当于为自身禁止使用动态制备的卷)。
为了基于存储类完成动态的存储制备,集群管理员需要在 API 服务器上启用 DefaultStorageClass 准入控制器。 举例而言,可以通过保证 DefaultStorageClass 出现在 API 服务器组件的 --enable-admission-plugins 标志值中实现这点;该标志的值可以是逗号分隔的有序列表。
简言之就是我们可以使用存储类StorageClass实现动态制备,不需要提前创建PV,只要创建好存储类StorageClass,用户创建PVC之后,存储类StorageClass会自动创建一个PV和PVC进行绑定。
四.存储类StorageClass
4.1 存储类StorageClass概览
StorageClass 为管理员提供了描述存储 "类" 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 "配置文件"。
4.2 StorageClass 资源
每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态制备 PersistentVolume 时会使用到。
存储制备器provisioner:每个 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。 该字段必须指定。
回收策略reclaimPolicy:由 StorageClass 动态创建的 PersistentVolume 会在类的 reclaimPolicy 字段中指定回收策略,可以是 Delete 或者 Retain。如果 StorageClass 对象被创建时没有指定 reclaimPolicy,它将默认为 Delete。通过 StorageClass 手动创建并管理的 PersistentVolume 会使用它们被创建时指定的回收策略。
允许卷扩展allowVolumeExpansion:PersistentVolume 可以配置为可扩展。将此功能设置为 true 时,允许用户通过编辑相应的 PVC 对象来调整卷大小。此功能仅可用于扩容卷,不能用于缩小卷。
挂载选项mountOptions:由 StorageClass 动态创建的 PersistentVolume 将使用类中 mountOptions 字段指定的挂载选项。如果卷插件不支持挂载选项,却指定了挂载选项,则制备操作会失败。 挂载选项在 StorageClass 和 PV 上都不会做验证,如果其中一个挂载选项无效,那么这个 PV 挂载操作就会失败。
卷绑定模式volumeBindingMode:volumeBindingMode 字段控制了卷绑定和动态制备应该发生在什么时候。
- Immediate 模式:默认情况下,Immediate 模式表示一旦创建了 PersistentVolumeClaim 也就完成了卷绑定和动态制备。 对于由于拓扑限制而非集群所有节点可达的存储后端,PersistentVolume 会在不知道 Pod 调度要求的情况下绑定或者制备。
- WaitForFirstConsumer 模式:集群管理员可以通过指定 WaitForFirstConsumer 模式来解决此问题。 该模式将延迟 PersistentVolume 的绑定和制备,直到使用该 PersistentVolumeClaim 的 Pod 被创建。 PersistentVolume 会根据 Pod 调度约束指定的拓扑来选择或制备。 这些包括但不限于资源需求、 节点筛选器、 Pod 亲和性和互斥性、 以及污点和容忍度。
注意:如果你选择使用 WaitForFirstConsumer,请不要在 Pod 规约中使用 nodeName 来指定节点亲和性。 如果在这种情况下使用 nodeName,Pod 将会绕过调度程序,PVC 将停留在 pending 状态。相反,在这种情况下,你可以使用节点选择器nodeSelector指定主机名。
参数parameters:Storage Classes 的参数描述了存储类的卷。取决于制备器,可以接受不同的参数。 例如,参数 type 的值 io1 和参数 iopsPerGB 特定于 EBS PV。 当参数被省略时,会使用默认值。一个 StorageClass 最多可以定义 512 个参数。这些参数对象的总长度不能超过 256 KiB, 包括参数的键和值。
五.创建存储类StorageClass
5.1 配置NFS服务端以及共享目录
在一台机器上安装NFS服务端,k8s的两个worker安装NFS客户端。
etcd1机器作为NFS的服务端,安装NFS。
[root@etcd1 ~]# yum -y install nfs-utils
[root@etcd1 ~]# rpm -qa | grep nfs
libnfsidmap-0.25-19.el7.x86_64
nfs-utils-1.3.0-0.68.el7.2.x86_64
启动NFS
#使nfs开机自启动并现在就启动
[root@etcd1 ~]# systemctl enable nfs-server --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
#查看nfs状态
[root@etcd1 ~]# systemctl status nfs-server
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; vendor preset: disabled)
Active: active (exited) since 二 2022-01-18 17:24:24 CST; 8s ago
Process: 1469 ExecStartPost=/bin/sh -c if systemctl -q is-active gssproxy; then systemctl reload gssproxy ; fi (code=exited, status=0/SUCCESS)
Process: 1453 ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS (code=exited, status=0/SUCCESS)
Process: 1451 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
Main PID: 1453 (code=exited, status=0/SUCCESS)
CGroup: /system.slice/nfs-server.service
1月 18 17:24:24 etcd1 systemd[1]: Starting NFS server and services...
1月 18 17:24:24 etcd1 systemd[1]: Started NFS server and services.
先在NFS服务端创建/dongtaijuandongying,并把目录/dongtaijuandongying共享出去
#在NFS服务端创建共享目录/dongtaijuandongying
[root@etcd1 ~]# mkdir /dongtaijuandongying
[root@etcd1 ~]# vim /etc/exports
#把/dongtaijuandongying目录共享出去
[root@etcd1 ~]# cat /etc/exports
/dongtaijuandongying *(rw,async,no_root_squash)
[root@etcd1 ~]# exportfs -arv
exporting *:/dongtaijuandongying
5.2 配置NFS客户端
在k8s集群的worker节点安装nfs的客户端
[root@k8scloude3 ~]# yum -y install nfs-utils
#安装nfs的客户端
[root@k8scloude2 ~]# yum -y install nfs-utils
查看etcd1(192.168.110.133)机器共享出来的目录是哪个?
[root@k8scloude2 ~]# showmount -e 192.168.110.133
Export list for 192.168.110.133:
/dongtaijuandongying *
5.3 配置StorageClass支持NFS
NFS类型的StorageClass没有内部制备器provisioner,但可以使用外部制备器。 也有第三方存储供应商提供自己的外部制备器。Kubernetes 不包含内部 NFS 驱动。你需要使用外部驱动为 NFS 创建 StorageClass。
由于k8s默认不支持nfs类型的StorageClass,需要修改参数然后自定义nfs StorageClass
[root@k8scloude1 volume]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
#添加参数如下
[root@k8scloude1 volume]# cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep RemoveSelfLink
- --feature-gates=RemoveSelfLink=false
重启kubelet使配置生效
[root@k8scloude1 volume]# systemctl restart kubelet
[root@k8scloude1 volume]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since 三 2022-01-19 18:11:09 CST; 6s ago
Docs: https://kubernetes.io/docs/
Main PID: 89887 (kubelet)
Memory: 37.4M
CGroup: /system.slice/kubelet.service
├─89887 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-in...
└─90152 [find]
下载git
[root@k8scloude1 volume]# yum -y install git
下载扩展存储卷yaml文件
[root@k8scloude1 volume]# git clone https://github.com/kubernetes-incubator/external-storage.git
[root@k8scloude1 volume]# ls
external-storage
[root@k8scloude1 volume]# cd external-storage/nfs-client/
[root@k8scloude1 nfs-client]# cd deploy/
[root@k8scloude1 deploy]# ls
class.yaml deployment-arm.yaml deployment.yaml objects rbac.yaml test-claim.yaml test-pod.yaml
因为deployment.yaml文件里需要NFS制备器镜像:nfs-client-provisioner:latest镜像,可以提前下载下来镜像
[root@k8scloude1 deploy]# cat deployment.yaml | grep image
image: quay.io/external_storage/nfs-client-provisioner:latest
#在master和worker上都下载好镜像
[root@k8scloude1 deploy]# docker pull quay.io/external_storage/nfs-client-provisioner:latest
[root@k8scloude2 ~]# docker pull quay.io/external_storage/nfs-client-provisioner:latest
[root@k8scloude3 ~]# docker pull quay.io/external_storage/nfs-client-provisioner:latest
[root@k8scloude1 deploy]# docker images | grep nfs-client-provisioner
quay.io/external_storage/nfs-client-provisioner latest 16d2f904b0d8 3 years ago 45.5MB
安装NFS制备器
[root@k8scloude1 deploy]# pwd
/root/volume/external-storage/nfs-client/deploy
#当前的namespace为:volume
[root@k8scloude1 deploy]# kubens
default
kube-node-lease
kube-public
kube-system
ns1
ns2
pod
volume
[root@k8scloude1 deploy]# ls
class.yaml deployment-arm.yaml deployment.yaml objects rbac.yaml test-claim.yaml test-pod.yaml
#修改namespace
[root@k8scloude1 deploy]# sed -i 's/namespace: default/namespace: volume/g' rbac.yaml
[root@k8scloude1 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@k8scloude1 deploy]# grep image deployment.yaml
image: quay.io/external_storage/nfs-client-provisioner:latest
[root@k8scloude1 deploy]# vim deployment.yaml
#修改NFS的服务器地址和共享目录,设置镜像下载策略为: imagePullPolicy: IfNotPresent:本地有镜像就不下载
[root@k8scloude1 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: volume
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
#镜像下载策略要修改
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
#NFS服务器地址
- name: NFS_SERVER
value: 192.168.110.133
#NFS共享目录
- name: NFS_PATH
value: /dongtaijuandongying
volumes:
- name: nfs-client-root
nfs:
#NFS服务器地址
server: 192.168.110.133
#NFS共享目录
path: /dongtaijuandongying
[root@k8scloude1 deploy]# kubectl apply -f deployment.yaml
deployment.apps/nfs-client-provisioner created
#可以看到nfs制备器nfs-client-provisioner-76c576954d-5x7t2
[root@k8scloude1 deploy]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-76c576954d-5x7t2 1/1 Running 0 17s 10.244.112.129 k8scloude2 <none> <none>
5.4 创建StorageClass
查看StorageClass
[root@k8scloude1 deploy]# kubectl get sc
No resources found
配置StorageClass
[root@k8scloude1 deploy]# vim class.yaml
#archiveOnDelete参数表示:If it exists and has a false value, delete the directory. if onDelete exists, archiveOnDelete will be ignored.
[root@k8scloude1 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"
创建storageclass
[root@k8scloude1 deploy]# kubectl apply -f class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
[root@k8scloude1 deploy]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
managed-nfs-storage fuseim.pri/ifs Delete Immediate false 10s
5.5 创建持久卷申领PersistentVolumeClaim(PVC)
现在没有pv和PVC
[root@k8scloude1 deploy]# kubectl get pv
No resources found
[root@k8scloude1 deploy]# kubectl get pvc
No resources found in volume namespace.
配置PVC
[root@k8scloude1 deploy]# vim pvc1.yaml
#storageClassName要和刚才创建的storageClass一样
[root@k8scloude1 deploy]# cat pvc1.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
创建PVC
[root@k8scloude1 deploy]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/mypvc created
[root@k8scloude1 deploy]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pvc-4b73eeaa-1530-4599-b2c8-6057bb16658a 1Gi RWO managed-nfs-storage 6s
创建PVC之后,pv也自动创建了
[root@k8scloude1 deploy]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-4b73eeaa-1530-4599-b2c8-6057bb16658a 1Gi RWO Delete Bound volume/mypvc managed-nfs-storage 9s
查看pv的详细信息
[root@k8scloude1 deploy]# kubectl describe pv pvc-4b73eeaa-1530-4599-b2c8-6057bb16658a
Name: pvc-4b73eeaa-1530-4599-b2c8-6057bb16658a
Labels: <none>
Annotations: pv.kubernetes.io/provisioned-by: fuseim.pri/ifs
Finalizers: [kubernetes.io/pv-protection]
StorageClass: managed-nfs-storage
Status: Bound
Claim: volume/mypvc
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 1Gi
Node Affinity: <none>
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 192.168.110.133
Path: /dongtaijuandongying/volume-mypvc-pvc-4b73eeaa-1530-4599-b2c8-6057bb16658a
ReadOnly: false
Events: <none>
删除pvc,PV也自动删除
[root@k8scloude1 deploy]# kubectl delete pvc mypvc
persistentvolumeclaim "mypvc" deleted
[root@k8scloude1 deploy]# kubectl get pv
No resources found
[root@k8scloude1 deploy]# kubectl get pvc
No resources found in volume namespace.
重新创建PVC
[root@k8scloude1 deploy]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/mypvc created
[root@k8scloude1 deploy]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pvc-7d17891d-f95a-417f-abf4-06f9e84dc82e 1Gi RWO managed-nfs-storage 6s
[root@k8scloude1 deploy]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-7d17891d-f95a-417f-abf4-06f9e84dc82e 1Gi RWO Delete Bound volume/mypvc managed-nfs-storage 9s
六.把卷挂载到pod
配置pod把PVC挂载到容器的/xx目录
[root@k8scloude1 deploy]# vim pvcpod.yaml
[root@k8scloude1 deploy]# cat pvcpod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pvcshare
name: pvcshare
spec:
#nodeName指定pod运行在k8scloude3节点
nodeName: k8scloude3
terminationGracePeriodSeconds: 0
volumes:
- name: v1
#卷类型为PVC
persistentVolumeClaim:
claimName: mypvc
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: h1
resources: {}
volumeMounts:
- name: v1
mountPath: /xx
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
创建pod
[root@k8scloude1 deploy]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-76c576954d-5x7t2 1/1 Running 0 15m
[root@k8scloude1 deploy]# kubectl apply -f pvcpod.yaml
pod/pvcshare created
[root@k8scloude1 deploy]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-76c576954d-5x7t2 1/1 Running 0 15m 10.244.112.129 k8scloude2 <none> <none>
pvcshare 1/1 Running 0 5s 10.244.251.195 k8scloude3 <none> <none>
进入pod,创建文件
[root@k8scloude1 deploy]# kubectl exec -it pvcshare -- bash
root@pvcshare:/# ls /xx/
root@pvcshare:/# touch /xx/{1..10}.txt
root@pvcshare:/# ls /xx/
1.txt 10.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
root@pvcshare:/# exit
exit
NFS服务器对应目录下也有文件
[root@etcd1 ~]# ls /dongtaijuandongying/volume-mypvc-pvc-7d17891d-f95a-417f-abf4-06f9e84dc82e/
10.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
删除pod
[root@k8scloude1 deploy]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-76c576954d-5x7t2 1/1 Running 0 17m
pvcshare 1/1 Running 0 2m9s
[root@k8scloude1 deploy]# kubectl delete -f pvcpod.yaml
pod "pvcshare" deleted
[root@k8scloude1 deploy]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-76c576954d-5x7t2 1/1 Running 0 18m
删除PVC
[root@k8scloude1 deploy]# kubectl delete -f pvc1.yaml
persistentvolumeclaim "mypvc" deleted
[root@k8scloude1 deploy]# kubectl get pv
No resources found
[root@k8scloude1 deploy]# kubectl get pvc
No resources found in volume namespace.
pvc被删除之后,NFS服务端文件也没了,是因为回收策略RECLAIM POLICY为Delete
[root@etcd1 ~]# ls /dongtaijuandongying/volume-mypvc-pvc-7d17891d-f95a-417f-abf4-06f9e84dc82e/
ls: 无法访问/dongtaijuandongying/volume-mypvc-pvc-7d17891d-f95a-417f-abf4-06f9e84dc82e/: 没有那个文件或目录
当配置了存储类StorageClass,PVC可以进行动态扩容,关于PVC动态扩容请查看博客《troubleshoot:PVC动态扩容报错》。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK