容器持久化
容器持久化,是指在容器宿主机上的目录,具备“持久性”。即,这个目录里面的内容,既不会因为容器的删除而被清理掉,也不会跟当前的宿主机绑定。当容器重启或者迁移重建,也依然可以访问到这个 Volume。
在多数情况下,持久化 Volume 的实现,依赖于远程存储服务,比如 NFS、GlusterFS、远程块存储等。
两阶段处理
在具体的 Volume 插件的实现接口上, Kubernetes 分别给这两个阶段提供两种不同的参数列表
Attach:是由 Volume Controller 负责维护的,这个控制循环的名字叫作:AttachDetachController。必须在 master 节点上。
Mount:必须发生在 Pod 对应的宿主机上,所以它必须是 kubelet 组件的一部分。这个控制循环的名字,叫作:VolumeManagerReconciler
Dynamic Provisioning
通过 StorageClass 的 API 对象,创建 PV 模板。通过确定 PV 属性,以及 PV 需要的存储插件。然后根据用户提交的 PVC,找到对应 StorageClass 创建 PV。
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:name: block-serviceprovisioner: kubernetes.io/gce-pd # 存储插件parameters: # PV 参数type: pd-ssd
k8s 默认支持的存储插件:https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner
-
PV PVC storageClass
PVC 描述的,是 Pod 想要使用的持久化存储的属性,比如存储的大小、读写权限等。
- PV 描述的,则是一个具体的 Volume 的属性,比如 Volume 的类型、挂载目录、远程存储服务器地址等。
- 而 StorageClass 的作用,则是充当 PV 的模板。并且,只有同属于一个 StorageClass 的 PV 和 PVC,才可以绑定在一起。
本地化存储
Local Persistent Volume 是指 K8S 直接使用宿主机上的本地磁盘,使用这个应用时,必须具备数据备份和恢复的能力。
磁盘选择
一个 Local Persistent Volume 对应的存储介质,是一块额外挂载在宿主机的磁盘或者块设备。即一个 PV 一块盘的原则。
Pod 访问存储
在开始使用 Local Persistent Volume 之前,你首先需要在集群里配置好磁盘或者块设备,并且让整个 Kubernetes。在 Kubernetes 的调度器里,有个叫 VolumeBindingChecker 的过滤条件专门负责在调度的时候考虑 Volume 分布情况。
PV 定义参考
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/vol1 # 指定本地存储路径
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-1 # 指定了 PV 和 Node 的关系,也是 k8s 实现调度的主要方法
创建一个 StorageClass 来描述这个 PV
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner # LPV 不支持 dynamic provisioning
volumeBindingMode: WaitForFirstConsumer # 延迟绑定
延迟绑定
在 Local Persistent Volume 创建过程中,需要先创建 PV, PVC 在提交之后,通过 StorageClass 立刻找到对应的 PV,与之绑定。然后出现这么一种情况, PV-1 定义在 node1 节点,而提交 PVC 后, k8s 很快匹配了两者关系,但是在创建 Pod 时,如果添加了 node 的限制,不允许 pod 运行在 node 1 节点上的话,就会出现 Pod 调用失败的情况。
所以通过延迟绑定,推迟到调度的时候,再开始绑定。这样可以找到 Pod 定义的 Node 的节点上。
声明 PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: example-local-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: local-storage
Pod 引用 PVC
kind: Pod
apiVersion: v1
metadata:
name: example-pv-pod
spec:
volumes:
- name: example-pv-storage
persistentVolumeClaim:
claimName: example-local-claim
containers:
- name: example-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: example-pv-storage
PV 删除流程
上述创建 PV 的方式,是 Static 的 PV 管理方式,在删除 PV 时需要按照一定流程操作:
- 删除使用这个 PV 的 Pod;
- 从宿主机移除本地磁盘(比如,umount 它);
- 删除 PVC;
- 删除 PV。
