陈同学
微服务
Accelerator
About
# K8s 存储(PV、PVC、StorageClass) 容器数据随着容器销毁而销毁,而应用数据经常需要落盘,应用重启后可恢复使用,多应用也可共享。 K8s 抽象出 **"Volume"** 概念来处理存储问题。Volume 意为 "容量、卷",可理解为存储介质,在Linux上就是一个目录,Pod中容器可访问这个目录。 ## Volume 的种类 > [K8s storage doc](https://kubernetes.io/zh/docs/concepts/storage/) K8s支持多种存储介质,下面例举几个: ### emptyDir emptyDir的特性是只要Pod在节点运行,卷就会一直存在,可提供一个缓存空间。当Pod调度到某个节点时,首先会创建一个emptyDir卷。 下面是官网Demo ```yaml apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: # 指定卷的名称和类型 - name: cache-volume emptyDir: {} ``` ### hostPath hostPath卷可将机器上的文件或目录挂载到Pod中,需要注意文件的权限。 ```yaml apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: path: /data type: Directory ``` hostPath的type可为空,主要可选类型有: * DirectoryOrCreate、Directory:卷是一个目录 * FileOrCreate、File:卷是一个文件 * Socket:卷是一个UNIX 套接字 ### nfs nfs卷可以将 NFS存储挂载到Pod,这是非常常用的方式。私有化部署时可以采用本地的nfs服务,云上时可直接采购nfs类型的存储介质。 ```yaml apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /test-pd name: nfs-volume volumes: - name: nfs-volume nfs: path: /k8s-nfs/redis/data # 阿里云nas例子 # server: xxx.cn-qingdao.nas.aliyuncs.com # 本地nfs服务例子 server: 192.168.8.150 ``` ## PV PV全称PersistentVolum,指持久化卷,是K8s对存储的一种抽象,开发者可不关注存储实现的细节。PV可以由运维人员创建或通过K8s的 **"Storage Class"** 动态提供。 下面是 [官网一个nfs Demo](https://github.com/kubernetes/examples/blob/master/staging/volumes/nfs/nfs-pv.yaml). ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: nfs spec: capacity: # 单位: Mi, Gi storage: 1Mi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Recycle nfs: server: nfs-server.default.svc.cluster.local path: "/" ``` PV 是对存储的一种描述,可当作存储资源供上层对象使用,nfs 卷作为具体的存储介质。 ### accessModes 访问模式 对卷的访问模式包含: * ReadWriteOnce:读写权限,但是只能被单个节点挂载 * ReadOnlyMany:只读权限,可以被多个节点挂载 * ReadWriteMany:读写权限,可以被多个节点挂载 注意:不同类型的PV支持的访问模式不同,例如:hostPath类型只支持ReadWriteOnce,nfs类型支持所有模式。 ### Reclaiming 回收策略 Volume 用完后,可以进行回收。回收策略包含: * Retain:保留数据,数据需要管理员手工清理。 * Delete:删除数据,会删除PV和数据。 * Recycle:回收,相当于执行 `rm -rf yourDir`,但PV还可继续使用。 推荐使用 **Retain**,甚删数据。 ### status 状态 * Available:还未被任何PVC绑定,可使用 * Bound:已被PVC绑定 * Released:已释放,PVC已删除,可重新被使用 * Failed:PV自动回收失败 ## PVC PVC 全称 "Persistent Volume Claim",是对存储的声明,是更高级别的抽象,和 Spring 的 IoC有点异曲同工之妙。 PVC 仅对所需存储的属性做一个声明(和Java中的接口一个含义),可以不管具体的实现,全部由K8s根据 "期望值" 自动搞定。 下图的PVC声明需要10G的容量,当集群中存在合适的PV时,PVC将自动和PV完成绑定。 ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs spec: accessModes: - ReadWriteMany storageClassName: "" resources: requests: storage: 10Gi ``` ### PVC 的原理 PVC这种 **"伸手要资源"** 的傲娇是如何被满足的呢? * 首先,需要有容量(storage)合适的PV,PV storage >= PVC storage * 其次,PV和PVC的storageClassName需要保持一致 * 如果没有合适的PV可使用,Pod 启动会报错。此时若运维人员及时创建PV,Pod会自动恢复。 下面是一个Pod对PVC的使用: ```yaml apiVersion: v1 kind: Pod spec: containers: - name: busybox image: busybox volumeMounts: - name: nfs mountPath: "/hello" volumes: - name: nfs persistentVolumeClaim: claimName: nfs ``` 当Pod创建之后,kubelet 会把PVC对应的PV挂载到容器的 `/hello` 目录。 ### PersistentVolumeController PV和PVC的绑定有该控制器搞定,它会不断轮询PVC,查到是否已经完成绑定。 ## StorageClass 当存储较少时,运维人员手工创建PV是OK的,但当所需存储成千上万时,就需要动态创建的能力。 K8s 提供了动态创建PV的机制即 Dynamic Provisioning,Provision意为"提供者"。 StorageClass起到一个模板的作用,像Java中的class与实例的关系。通过StorageClass这个模板对PV的属性进行描绘,PVC就可以通过这个模板动态创建PV,当然自动创建的实现会有专门的插件搞定。 下面是官网的Demo: ```yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: standard # 存储分配器, 也就是动态创建PV的具体实现商 provisioner: kubernetes.io/aws-ebs parameters: type: gp2 # PV 回收策略 reclaimPolicy: Retain # 可拓展时允许用户编辑PVC来调整卷的大小, 但只有部分Volume支持。 allowVolumeExpansion: true # 卷绑定模式, Immediate 表示创建PVC后立马绑定PV, WaitForFirstConsumer表示等待Pod创建时再绑定 volumeBindingMode: Immediate ``` 每个 StorageClass 包含:provisioner、parameters、reclaimPolicy字段。 # 挂载时使用 subPath ```yaml apiVersion: v1 kind: Pod metadata: name: auth-service spec: containers: - image: k8s.gcr.io/test-webserver name: auth-service volumeMounts: - mountPath: /java/heapdump name: heapdump subPath: auth-service volumes: - name: heapdump hostPath: path: /data type: Directory ``` 容器内的 /java/heapdump 目录会对应到 volume 的 /data/auth-service 目录。 所有服务的JVM配置保持一致 -XX:HeapDumpPath=/java/heapdump,实际存储到了服务具体的目录。
本文由
cyj
创作,可自由转载、引用,但需署名作者且注明文章出处。
文章标题:
K8s 存储(PV、PVC、StorageClass)
文章链接:
https://chenyongjun.vip/articles/135
扫码或搜索 cyjrun 关注微信公众号, 结伴学习, 一起努力