Contents
StorageClass¶
之前介绍了PV及PVC的使用方式,读者从中可以发现,这是一种静态创建PV的方法,先要创建各种固定大小的PV,而这些PV都是手动创 建的,过程非常麻烦。有时开发人员在申请PVC资源时,不一定有匹配条件的PV可用,这又带来了新的问题。
为了解决这类问题,Kubernetes提供了StorageClass抽象来动态创建PV,StorageClass大大简化了PV的创建过程。
当申请PVC资源时,如果匹配到满足条件的StorageClass,就会自动为PVC创建对应大小的PV并进行绑定。
StorageClass是通过存储分配器(provisioner)来动态分配PV的,但是Kubernetes官方内置的存储分配器并不支持NFS,所以需要额 外安装NFS存储分配器。
参考文献:
1. 安装存储分配器¶
NFS 存储分配器的安装过程并不复杂。首先,执行以下命令,下载 NFS 存储分配器的deployment.yaml配置。
$ git clone https://github.com/kubernetes-retired/external-storage.git
$ cd external-storage/nfs-client/deploy/
下载完成后,使用以下命令编辑yaml配置文件。修改文件中的部分配置,然后保存,具体修改内容参见下方粗体 代码。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: default
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.60
- name: NFS_PATH
value: /nfstest
volumes:
- name: nfs-client-root
nfs:
server: 192.168.1.60
path: /nfstest
在env属性中,PROVISIONER_NAME表示存储分配器的名称,nfs-gitee-test。
NFS_SERVER表示NFS服务器地址,在本例中为之前配置的192.168.1.60。
NFS_PATH表示NFS共享目录地址,在本例中为/nfstest。在volumes属性中,也将server与path改为之前配置的NFS服务器地址和共享目录。
class.yaml中的provisioner要与deployment.yaml中一致
安装完成后可以创建StorageClass了。首先,创建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"
该模板的主要含义如下。
apiVersion表示使用的API版本,storage.k8s.io/v1表示使用Kubernetes API的稳定版本。
kind表示要创建的资源对象,这里使用关键字StorageClass。
metadata中的name属性定义了当前资源的名称。
provisioner表示存储分配器的名称。这里需要使用之前在Deployment模板中配置的PROVISIONER_NAME,即 fuseim.pri/ifs。
parameters表示该资源对象的参数。若archiveOnDelete为false,表示与之关联的PVC在删除时,它所绑定的PV不会被存储 分配器保留;若为true,则相反
接下来修改测试pvc和pod,用于验证
test-claim.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
test-pod.yaml
kind: Pod
apiVersion: v1
metadata:
name: test-pod
spec:
containers:
- name: test-pod
image: busybox:latest
command:
- "/bin/sh"
args:
- "-c"
- "touch /mnt/SUCCESS && exit 0 || exit 1"
volumeMounts:
- name: nfs-pvc
mountPath: "/mnt"
restartPolicy: "Never"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim
接下来,执行以下命令,创建StorageClass。
$ kubectl apply -f external-storage/nfs-client/deploy/
创建完成后,可以通过以下命令查看StorageClass
$ kubectl get sc|grep managed-nfs-storage
managed-nfs-storage fuseim.pri/ifs Delete Immediate false 55s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim Bound pvc-86a26712-ea2e-4c92-9075-6dc38343247e 1Mi RWX managed-nfs-storage 2m32s
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-client-provisioner 1/1 1 1 2m4s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-6794dc7784-7frn7 1/1 Running 0 2m55s
test-pod 0/1 Completed 0 2m54s
使用以下命令,可以查询StorageClass资源的详情。
$ kubectl describe sc managed-nfs-storage
Name: managed-nfs-storage
IsDefaultClass: No
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{},"name":"managed-nfs-storage"},"parameters":{"archiveOnDelete":"false"},"provisioner":"fuseim.pri/ifs"}
Provisioner: fuseim.pri/ifs
Parameters: archiveOnDelete=false
AllowVolumeExpansion: <unset>
MountOptions: <none>
ReclaimPolicy: Delete
VolumeBindingMode: Immediate
Events: <none>
此时可通过$ kubectl describe pv命令查看详情。可以看到该动态PV在NFS服务器的共享目录上创建了一个专属于它的子目录,
$ kubectl describe pv pvc-86a26712-ea2e-4c92-9075-6dc38343247e
Name: pvc-86a26712-ea2e-4c92-9075-6dc38343247e
Labels: <none>
Annotations: pv.kubernetes.io/provisioned-by: fuseim.pri/ifs
Finalizers: [kubernetes.io/pv-protection]
StorageClass: managed-nfs-storage
Status: Bound
Claim: default/test-claim
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.60
Path: /nfstest/default-test-claim-pvc-86a26712-ea2e-4c92-9075-6dc38343247e
ReadOnly: false
Events: <none>
在本例中为/nfstest/default-test-claim-pvc-86a26712-ea2e-4c92-9075-6dc38343247e
我们查看nfs的数据如下
$ ll /data/nfs/nfstest/default-test-claim-pvc-86a26712-ea2e-4c92-9075-6dc38343247e/SUCCESS
-rw-r--r-- 1 root root 0 Apr 17 20:39 /data/nfs/nfstest/default-test-claim-pvc-86a26712-ea2e-4c92-9075-6dc38343247e/SUCCESS
接下来,删除PVC。先执行$ kubectl delete pvc exampleforstorageclass命令,然后再执行$ kubectl get pv命令获取PV。可以发现,当删除PVC时,它所绑定的动态PV也会自动删除。
$ kubectl delete -f external-storage/nfs-client/deploy/
删除动态PV后,NFS服务器的共享目录上创建的专属子目录也会被删除。
1.1 使用nfs-server-provisioner¶
kubernetes部署nfs-subdir-external-provisioner
kubernetes部署nfs-server-provisioner
https://blog.csdn.net/networken/article/details/105945174
使用 helm 安装 nfs-client-provisioner
1.2 在Kubernetes中部署nfs storageClass¶
1.3 NFS动态存储卷报错问题记录¶
我的问题:
创建pvc后状态一直是pending
排查步骤: 1.通过kubectl describe命令查看错误提示信息,信息中有:
waiting for a volume to be created, either by external provisioner “fuseim.pri/ifs” or manually created by system administrator。
2.通过kubectl logs命令查看pod(nfs-client-provisioner)日志,日志中有:
unexpected error getting claim reference: selfLink was empty, can’t make reference。
3.使用第二步骤的信息去网上查找,原来是1.20版本(我的是1.20.2)默认禁止使用selfLink。
解决方法
1.如果是通过yaml文件部署kube-apiserver的(我的是这种方式)
(1) 通过find / -name kube-apiserver.yaml 命令,找到kube-apiserver.yaml文件
(2)在文件中添加 - --feature-gates=RemoveSelfLink=false,
# 然后重启kube-api的pod让其生效
kubectl delete pod/kube-apiserver-gitee-k8s-m1 -n kube-system
kubectl delete pod/kube-apiserver-gitee-k8s-m2 -n kube-system
kubectl delete pod/kube-apiserver-gitee-k8s-m3 -n kube-system
2.如果是通过二进制部署kube-apiserver (我的是这种方式)
(1)systemctl status kube-apiserver 通过这个命令找到 kube-apiserver.service文件
(2)最好先备份,然后再修改,即在 kube-apiserver.service中添加 --feature-gates=RemoveSelfLink=false
2. PV和PVC的生命周期¶
PV是Kubernetes集群的存储资源,而PVC则代表着资源需求。创建PVC时对PV发起的使用申请,即为“绑定”。PV和PVC是一一对应的关系,可用于响应PVC申请的PV必须要能够容纳PVC的请求条件,它们二者的交互遵循如下生命周期。
2.1 存储供给¶
存储供给(Provisioning)是指为PVC准备可用PV的机制。Kubernetes支持两种PV供给方式:静态供给和动态供给。
(1)静态供给
静态供给是指由集群管理员手动创建一定数量的PV的资源供应方式。这些PV负责处理存储系统的细节,并将其抽象成易用的存储资源供用户使用。静态提供的PV可能属于某存储类(StorageClass),也可能没有存储类,这一点取决于管理员的设定。
(2)动态供给
不存在某静态的PV匹配到用户的PVC申请时,Kubernetes集群会尝试为PVC动态创建符合需求的PV,此即为动态供给。这种方式依赖于存储类的辅助,PVC必须向一个事先存在的存储类发起动态分配PV的请求,没有指定存储类的PVC请求会被禁止使用动态创建PV的方式。
另外,为了支持使用动态供给机制,集群管理员需要为准入控制器(admission controller)启用“DefaultStorageClass”选项,这一点通过“–admission-control”命令行选项为API Server进行设定即可,后文会对准入控制器予以描述。
2.2 存储绑定¶
用户基于一系列存储需求和访问模式定义好PVC后,Kubernetes系统的控制器即会为其查找匹配的PV,并于找到之后在此二者之间建立起关联关系,而后它们二者之间的状态即转为“绑定”(Binding)。若PV是为PVC而动态创建的,则该PV专用于其PVC。
若是无法为PVC找到可匹配的PV,则PVC将一直处于未绑定(unbound)状态,直到有符合条件的PV出现并完成绑定方才可用。
(1)存储使用(Using)
Pod资源基于persistenVolumeClaim卷类型的定义,将选定的PVC关联为存储卷,而后即可为内部的容器所使用。对于支持多种访问模式的存储卷来说,用户需要额外指定要使用的模式。一旦完成将存储卷挂载至Pod对象内的容器中,其应用即可使用关联的PV提供的存储空间。
(2)PVC保护(Protection)
为了避免使用中的存储卷被移除而导致数据丢失,Kubernetes自1.9版本起引入了“PVC保护机制”。启用了此特性后,万一有用户删除了仍处于某Pod资源使用中的PVC时,Kubernetes不会立即予以移除,而是推迟到不再被任何Pod资源使用后方才执行删除操作。
处于此种阶段的PVC资源的status字段为“Termination”,并且其Finalizers字段中包含“kubernetes.io/pvc-protection”。
2.3 存储回收(Reclaiming)¶
完成存储卷的使用目标之后,即可删除PVC对象以便进行资源回收。不过,至于如何操作则取决于PV的回收策略。目前,可用的回收策略有三种:Retained、Recycled和Deleted。
(1)留存(Retain)
留存策略意味着在删除PVC之后,Kubernetes系统不会自动删除PV,而仅仅是将它置于“释放”(released)状态。不过,此种状态的PV尚且不能被其他PVC申请所绑定,因为此前的申请生成的数据仍然存在,需要由管理员手动决定其后续处理方案。这就意味着,如果想要再次使用此类的PV资源,则需要由管理员按下面的步骤手动执行删除操作。
1)删除PV,这之后,此PV的数据依然留存于外部的存储之上。
2)手工清理存储系统上依然留存的数据。
3)手工删除存储系统级的存储卷(例如,RBD存储系统上的image)以释放空间,以便再次创建,或者直接将其重新创建为PV。
(2)回收(Recycle)
如果可被底层存储插件支持,资源回收策略会在存储卷上执行数据删除操作并让PV资源再次变为可被Claim。另外,管理员也可以配置一个自定义的回收器Pod模板,以便执行自定义的回收操作。不过,此种回收策略行将废弃。
(3)删除(Delete)
对于支持Deleted回收策略的存储插件来说,在PVC被删除后会直接移除PV对象,同时移除的还有PV相关的外部存储系统上的存储资产(asset)。支持这种操作的存储系统有AWS EBS、GCE PD、Azure Disk或Cinder。动态创建的PV资源的回收策略取决于相关存储类上的定义,存储类上相关的默认策略为Delete,大多数情况下,管理员都需要按用户期望的处理机制修改此默认策略,以免导致数据非计划内的误删除。
2.4 扩展PVC¶
Kubernetes自1.8版本起增加了扩展PV空间的特性,截至目前,它所支持的扩展PVC机制的存储卷共有以下几种。
gcePersistentDisk
awsElasticBlockStore
Cinder
glusterfs
rbd
“PersistentVolumeClaimResize”准入插件负责对支持空间大小变动的存储卷执行更多的验证操作,管理员需要事先启用此插件才能使用PVC扩展机制,那些将“allowVolume Expansion”字段的值设置为“true”的存储类即可动态扩展存储卷空间。随后,用户改动Claim请求更大的空间即能触发底层PV空间扩展从而带来PVC存储卷的扩展。
对于包含文件系统的存储卷来说,只有在有新的Pod资源基于读写模式开始使用PVC时才会执行文件系统的大小调整操作。换句话说,如果某被扩展的存储卷已经由Pod资源所使用,则需要重建此Pod对象才能触发文件系统大小的调整操作。支持空间调整的文件系统仅有XFS和EXT3/EXT4。