爱数AnyRobot采用K8S集群环境,在搭建好的AnyRobot环境中,存在许多Pod,其中有一部分Pod数据是需要长久保存的,在K8S中,长久数据一般存储在PV中,那Pod是如何实现,如何把自身数据存储在PV里面的呢?本文讲重点讲解该方面知识。
在整个k8s集群中,有一些存储资源,比如说NFS、CIFS等存储,这些存储都是由集群管理人员提前去创建的,不同的存储方式不一样, 如果都掌握才可以使用,则很不方便 ,对运维人员能力要求也高,所以在k8s中提供了新的对象资源叫做PV(Persistent Volume)和PVC(Persistent Volume Claim),更方便用户直接进行使用 。
一:相关技术概念
在了解Pod数据如何存储在PV中,需要了解以下几个概念:
- PV (Persistent Volume):PV俗称持久卷,是集群中由管理员配置的一段网络存储,它是集群的一部分资源和底层存储密切相关,对象包含存储实现的细节,即对接NFS、CIFS等存储系统 ;不同的PV会对应到不用的存储资源,这样在部署Pod的时候直接调用集群内部的PV即可 ;PV没有命名空间隔离概念 ;
- PVC (Persistent Volume Claim):PVC 也称作持久卷声明 ,假如存在很多PV, k8s要用PV的时候直接调用某个PV的话,那如果需要的是存储能力比较大存储资源,所以这个时候需要一个一个去对比PV,这样很耗费资源(因为要满足需求) ;PVC是用户存储的一种声明, PVC 可以请求特定的存储空间和访问模式,PVC 消耗的是 PV 资源 ;PVC必须与对应的PV建立关系,PVC会根据定义的PV去申请 ;创建Pod的时候会附带一个PVC的请求,PVC的请求相当于就是去寻找一个合适的PV ,如下图对应关系所示:
- StorageClass:PV和PVC方法虽然能实现屏蔽底层存储,但是PV创建比较复杂(可以看到PV中csi字段的配置很麻烦),通常都是由集群管理员管理,这非常不方便。Kubernetes解决这个问题的方法是提供动态配置PV的方法,可以自动创PV。管理员可以部署PV配置器(provisioner),然后定义对应的StorageClass,这样开发者在创建PVC的时候就可以选择需要创建存储的类型,PVC会把StorageClass传递给PV provisioner,由provisioner自动创建PV,在声明PVC时加上StorageClassName,就可以自动创建PV,并自动创建底层的存储资源。
- CSI:Kubernetes提供了CSI接口(Container Storage Interface,容器存储接口),基于CSI这套接口,可以开发定制出CSI插件,从而支持特定的存储,达到解耦的目的,有了这些驱动就可以使用EVS、SFS、OBS存储。
二:相关技术原理
如果要求Pod重新调度后仍然能使用之前读写过的数据,就只能使用网络存储了,网络存储种类非常多且有不同的使用方法,通常一个云服务提供商至少有块存储、文件存储、对象存储三种。Kubernetes解决这个问题的方式是抽象了PV(PersistentVolume)和PVC(PersistentVolumeClaim)来解耦这个问题,从而让使用者不用关心具体的基础设施,当需要存储资源的时候,只要像CPU和内存一样,声明要多少即可。
Kubernetes管理员设置好网络存储的类型,提供对应的PV描述符配置到Kubernetes,使用者需要存储的时候只需要创建PVC,然后在Pod中使用Volume关联PVC,即可让Pod使用到存储资源,它们之间的关系如下图所示。
三、AnyRobot Pod数据存储到PV实现过程
下面将通过AnyRobot中名为fine-report-0的Pod,如何实现数据自动存储到PV里面。
1、首先查看目前存在名为fine-report-pv的PV
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/bound-by-controller: "yes"
finalizers:
- kubernetes.io/pv-protection
labels:
app: fine-report
name: fine-report-pv ---PV名为fine-report-pv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 2Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: data-fine-report-0 ---被名为data-fine-report-0引用
namespace: anyrobot
local:
path: /mnt/data1/fine-report ---为本地/mnt/data1/fine-report路径
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node109
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage ---使用local-storage storageClassName
volumeMode: Filesystem
status:
phase: Bound
2、查看名为data-fine-report-0 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
pv.kubernetes.io/bind-completed: "yes"
pv.kubernetes.io/bound-by-controller: "yes"
finalizers:
- kubernetes.io/pvc-protection
labels:
anyrobot-module: fine-report
cluster: anyrobot
fine-report-anyrobot-service: "true"
name: data-fine-report-0 ---PVC名为data-fine-report-0
namespace: anyrobot
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi --请求大小为2G
selector:
matchLabels:
app: fine-report
storageClassName: local-storage
volumeMode: Filesystem
volumeName: fine-report-pv ---PV名字
status:
accessModes:
- ReadWriteOnce
capacity:
storage: 2Gi
phase: Bound
3、查看对应StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"storage.k8s.io/v1","kind":"StorageClass","metadata":{"annotations":{},"name":"local-storage"},"provisioner":"kubernetes.io/no-provisioner","volumeBindingMode":"WaitForFirstConsumer"}
name: local-storage ---SC名字
resourceVersion: "8201"
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Delete ---回收相关策略
volumeBindingMode: WaitForFirstConsumer
4、查看fine-report-0 Pod如何实现数据存储(仅列出部分yaml文件)
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: data
persistentVolumeClaim:
claimName: data-fine-report-0 # PVC名称
5、通过以上方式,即可以实现Pod数据动态存储到PV里,其他Pod也可以通过同样的方式把数据存储到PV里面。