庖丁解牛 Kubernetes 1.14 本地持久卷GA特性
在Kubernetes最新1.14版本中,本地持久卷(Local Persistent Volume,本文简称LPV)已经正式GA,代表Kubernetes使用者可以使用该功能及其API用于生产环境。LPV alpha版本是在Kubernetes 1.7版中引进,在1.10版中升级为beta版,1.14版正式GA。
什么是 Kubernetes的Volume?
正文前,我们先来了解什么是Volume;
在Docker中也有一个docker Volume的概念 ,Docker的Volume只是磁盘中的一个目录,生命周期不受管理。当然Docker现在也提供Volume将数据持久化存储,但支持功能比较少。
另一方面,Kubernetes Volume具有明确的生命周期 - 与pod相同。同时,Volume的生命周期比Pod中运行的任何容器要持久,在容器重新启动时能可以保留数据,当然,当Pod被删除不存在时,Volume也将消失。注意,Kubernetes支持许多类型的Volume,Pod可以同时使用任意类型/数量的Volume。
内部实现中,一个Volume只是一个目录,目录中可能有一些数据,pod的容器可以访问这些数据。至于这个目录是如何产生的、支持它的介质、其中的数据内容是什么,这些都由使用的特定Volume类型来决定。
要使用Volume,pod需要指定Volume的类型和内容(spec.volumes
字段),和映射到容器的位置(spec.containers.volumeMounts
字段)。
什么是Local Persistent Volume?
LPV就是直接给Kubernetes节点上Pod中数据进行本地磁盘存储。
Kubernetes提供了一个功能强大的Volume插件系统,使Kubernetes工作负载能够使用各种块与文件系统存储来保存数据。这些插件中的大多数是远程存储。而远程存储无法提供像本地存储这样高性能和高可靠性的保障。
例如像分布式文件系统和数据库,这些都需要高性能和可靠性,比如在云的环境里,本地 SSD 比挂载的数据盘性能高出许多;另外,本地磁盘在多数情况下成本更低,适合数据量大的场景。
LPV与HostPath Volume有什么不同?
为了更好地理解LPV的优点,我们拿HostPath Volume进行比较。HostPath Volume是将文件或目录从主节点的文件系统挂载到Pod中。而LPV是将本地磁盘或分区安装到Pod中。
最大的区别是Kubernetes调度程序能确保LPV所在的节点的唯一性。如果使用HostPath Volume,调度程序可能会将引用HostPath Volume的pod移动到其他node节点,从而导致数据丢失。所以使用LPV,Kubernetes调度程序可确保LPV的Pod安排到同一节点。
LPV GA增加了什么新功能?
LPV从1.10开始,主要致力于提高功能的稳定性和可扩展性,以便生产就绪。
1.14版本中唯一的主要功能是能够指定原始块设备并让Kubernetes自动格式化并挂载文件系统。这减少了在将设备提供给Kubernetes之前必须格式化和装载设备的先前负担。
GA的局限性
GA版中,本地持久卷不支持动态卷配置(动态卷配置允许按需创建存储卷,如果没有动态卷配置,集群管理员必须手动创建)但是,增加了一个外部控制器,可用于帮助管理节点上各个磁盘的LPV生命周期,包含创建PersistentVolume对象,清理并重用磁盘。
ml
数据安全风险
LPV仍受node节点可用性方面的限制,因此并不适用于所有应用程序。 如果node节点变得不健康,则LPV也将变得不可访问,使用这个LPV的Pod也将无法运行。 使用LPV的应用程序必须能够容忍这种降低的可用性以及潜在的数据丢失,是否会真得导致这个后果将取决于node节点底层磁盘存储与数据保护的具体实现了。
LPV最佳实践
为了更好的IO隔离效果,建议将一整块磁盘作为一个存储卷使用;
为了得到存储空间的隔离,建议为每个存储卷使用一个独立的磁盘分区;
在仍然存在指定了某个node节点的亲和性关系的旧PV时,要避免重新创建具有相同节点名称的node节点。 否则,系统可能会认为新节点包含旧的PV。
对于具有文件系统的存储卷,建议在fstab条目和该卷的mount安装点的目录名中使用它们的UUID(例如ls -l /dev/disk/by-uuid的输出)。 这种做法可确保不会安装错误的本地卷,即使其设备路径发生了更改(例如,如果/dev/sda1在添加新磁盘时变为/dev/sdb1)。 此外,这种做法将确保如果创建了具有相同名称的另一个节点时,该节点上的任何卷仍然都会是唯一的,而不会被误认为是具有相同名称的另一个节点上的卷。
对于没有文件系统的原始块存储卷,请使用其唯一ID作为符号链接的名称。 根据您的环境,/dev/disk/by-id/中的卷ID可能包含唯一的硬件序列号。 否则,应自行生成一个唯一ID。 符号链接名称的唯一性将确保如果创建了另一个具有相同名称的节点,则该节点上的任何卷都仍然是唯一的,而不会被误认为是具有相同名称的另一个节点上的卷。
如何使用LPV?
可以使用与远程存储后端相同的PersistentVolumeClaim接口来请求LPV。这样可以轻松地跨群集,云和本地环境交换存储后端。
创建一个StorageClass,设置volumeBindingMode: WaitForFirstConsumer为启用卷拓扑感知调度。此模式指示Kubernetes等待绑定PVC,直到安排使用它的Pod为止。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
可以配置并运行外部静态配置程序,在节点上本地磁盘创建PV。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
local-pv-27c0f084 368Gi RWO Delete Available local-storage 8s
local-pv-3796b049 368Gi RWO Delete Available local-storage 7s
local-pv-3ddecaea 368Gi RWO Delete Available local-storage 7s
使用volumeClaimTemplates创建PVC和Pod,通过StatefulSet来定义PV。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: local-test
spec:
serviceName: "local-service"
replicas: 3
selector:
matchLabels:
app: local-test
template:
metadata:
labels:
app: local-test
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command:
- "/bin/sh"
args:
- "-c"
- "sleep 100000"
volumeMounts:
- name: local-vol
mountPath: /usr/test-pod
volumeClaimTemplates:
- metadata:
name: local-vol
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "local-storage"
resources:
requests:
storage: 368Gi
StatefulSet启动并运行,PVC全部被绑定:
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
local-vol-local-test-0 Bound local-pv-27c0f084 368Gi RWO local-storage 3m45s
local-vol-local-test-1 Bound local-pv-3ddecaea 368Gi RWO local-storage 3m40s
local-vol-local-test-2 Bound local-pv-3796b049 368Gi RWO local-storage 3m36s
当不需要磁盘时,可以删除PVC。外部静态配置器将清理磁盘并使PV可再次使用。
$ kubectl patch sts local-test -p '{"spec":{"replicas":2}}'
statefulset.apps/local-test patched
$ kubectl delete pvc local-vol-local-test-2
persistentvolumeclaim "local-vol-local-test-2" deleted
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
local-pv-27c0f084 368Gi RWO Delete Bound default/local-vol-local-test-0 local-storage 11m
local-pv-3796b049 368Gi RWO Delete Available local-storage 7s
local-pv-3ddecaea 368Gi RWO Delete Bound default/local-vol-local-test-1 local-storage 19m
停用LPV的方法
当您想要停用本地卷时,这是一个可行的工作流程。
1、关闭使用这些卷的Pods;
2、从node节点上移除LPV(比如unmounting, 拔出磁盘等等);
3、手动删除相应的PVCs对象;
4、Provisioner将尝试清理卷,但会由于卷不再存在而失败;
5、手动删除相应的PVs对象。
注:以上工作也是拜我们所使用的外部静态配置器所赐。
参考文档:
https://kubernetes.io/blog/2019/04/04/kubernetes-1.14-local-persistent-volumesga/
http://docs.kubernetes.org.cn/429.html
https://blog.csdn.net/watermelonbig/article/details/84108424
https://kubernetes.io/docs/concepts/storage/volumes/#local
K8S培训推荐
Kubernetes线下实战培训,采用3+1+1新的培训模式(3天线下实战培训,1年内可免费再次参加,每期前10名报名,可免费参加价值3600元的线上直播班;),资深一线讲师,实操环境实践,现场答疑互动,培训内容覆盖:Docker方面:Docker架构、镜像、数据存储、网络、以及最佳实践。Kubernetes实战内容,Kubernetes设计、Pod、常用对象操作,Kuberentes调度系统、QoS、Helm、网络、存储、CI/CD、日志监控等。
北京:5月10-12日
报名链接:https://www.bagevent.com/event/2376547
上海:5月17-19日
报名链接:https://www.bagevent.com/event/2409655
深圳:5月24-26日
报名链接:https://www.bagevent.com/event/2409699
推荐阅读
点击阅读原文直达报名链接!