欢迎访问我的博客,你的支持,是我最大的动力!

马哥_K8s进阶实战(5)存储卷与数据持久化

Docker 马从东 57℃ 评论
目录:
[显示]

存储卷与数据持久化

对于有状态应用,数据持久化是必然之需

Volume属于Pod资源级别,共享于Pod内所有容器,用于存储程序相关数据,甚至在Pod生命周期外实现数据持久化。存储卷定义在Pod资源上,可被其内部所有容器挂载

K8s支持非常多的存储卷类型
本地存储、网络存储系统、Secret、ConfigMap都属于存储资源

emptyDir和hostPath属于节点级别的卷类型,不具有持久性
emptyDir生命周期与Pod相同;使用hostPath的Pod一但重被调度至其他节点,将无法使用之前的数据

集群级别资源PersistentVolume,PV,由管理员配置存储系统;用户通过persistentVolumeClaim,PVC,申请使用,简化终端存储用户配置过程

Secret用于传递敏感信息;ConfigMap用于向Pod注入非敏感数据

存储卷的使用方式

在pods.spec.volumes中定义需要使用的卷列表,在pods.containers.volumeMounts中进行挂载(可不挂载任何存储卷)
多个容器可挂载同一个存储卷,此时即为共享目录
挂载相关参数:
name,必须,指定要挂载的存储的名称
mountPath,必须,挂载点
readOnly,boolean,是否挂载为只读
subPath,使用子路径挂载,即在mountPath指定路径的子路径作为挂载点

临时存储卷

emptyDir 生命周期与Pod相同,不能提供持久化存储能力
gitRepo 基于emptyDir构建,从Git仓库中复制相应数据到底层emptyDir中

emptyDir 存储卷

在Pod启动时被创建,在Pod移除时一并删除
spec.volumes.emptyDir.medium,存储介质类型,default 或 Memory
spec.volumes.emptyDir.sizeLimit,空间限额,默认为nil 注间,在类型为Memory时,一定要定义限额

两个容器都挂载了html

kubectl describe pods vol-emptydir-pod

gitRepo 存储卷

先创建一个空目录emptyDir并克隆一份指定Git仓库中的数据到该目录,之后再创建容器并挂载该存储卷
spec.volumes.gitRepo.repository,必须,Git仓库地址
spec.volumes.gitRepo.directory,目标目录名称,名称中不能包含 .. ,其中 . 表示将仓库中数据直接复制到卷目录中,否则复制到用户指定名称的子目录中
spec.volumes.gitRepo.revision,提交码
注意:使用gitRepo要求所运行的工作节点上安装有Git程序;自1.12起,gitRepo将被废弃(建议借助初始化容器InitContainer将仓库中数据复制到emptyDir上,并在主容器中使用此存储卷)
另,仅在Pod创建时拉取一次,可通过sidecar容器执行拉取操作,以追踪仓库的更新

节点存储卷 hostPath

使用节点上的目录或文件,具有持久性。尤适用于运行有管理任务的系统级Pod资源需要访问节点上的文件

spec.volumes.hostPath.path,必须,节点上的路径
spec.volumes.hostPath.type,存储卷类型,支持以下的值:
- DirectoryOrCreate,指定的路径不存在时自动创建,权限为0755,属主为kubelet
- Directory,必须存在的目录
- FileOrCreate,不存在时将自动创建的文件,权限为0644,属主为kubelet
- File,必须存在的文件路径
- Socket,必须存在的Socket文件路径
- CharDevice,必须存在的字符设备文件路径
- BlockDevice,必须存在的块设备文件路径
注意:
1、不同节点上的文件可能存在差异,对于要求事先必须存在的文件或目录,可能会出现不满足的情形
2、基于资源可用状态调度Pod时,hostPath的可用性不会被考虑
3、节点中创建的文件或目录默认仅root可写,若要在容器内也可写,须将容器运行为特权容器,或修改节点上目录的权限

日志采集的Pod,搜集本节点日志发送到Redis

网络存储卷

NFS 存储卷

NFS在Pod对象终止后仅被卸载不会删除,支持同时存在多路挂载请求
kubectl explain pods.spec.volumes.nfs
参数:
spec.volumes.nfs.path,必须,NFS的导出文件系统路径
spec.volumes.nfs.readOnly,boolean,是否以只读方式挂载,默认false
spec.volumes.nfs.server,必须,服务器IP或主机名

RBD 存储卷

Ceph是一个专注分布式、弹性可扩展、高可靠、性能优异的存储系统平台,支持提供块设备、文件系统、API存储接口,有命令行界面,还包含鉴证和授权功能。

使用的前置条件:有Ceph RBD存储集群,集群中有能满足Pod需要的存储映像image,K8s各节点上需安装Ceph客户端程序(ceph-common)

kubectl explain pods.spec.volumes.rbd
参数:
spec.volumes.rbd.fsType,要挂载的存储卷的文件系统,必须是节点支持的文件系统,如ext4/xfs/ntfs,默认ext4
spec.volumes.rbd.image,必须,rados image的名称
spec.volumes.rbd.keyring,RBD认证的keyring文件路径,默认/etc/ceph/keyring
spec.volumes.rbd.monitors,必须,Ceph存储监视器,逗号分隔的字符串列表
spec.volumes.rbd.pool,存储池名称,默认为RBD
spec.volumes.rbd.readOnly,是否挂载为只读
spec.volumes.rbd.secretRef,用户认证时使用的保存有认证信息的Secret对象,会覆盖keyring提供的密钥信息
spec.volumes.rbd.user,用户名,默认为admin

GlusterFS 存储卷

ClusterFS有强大的横向扩展能力,能支持PB级容量和千级客户端

前置条件:有GlusterFS存储集群,集群中创建有能满足Pod需要的卷,K8s各节点上安装GlusterFS客户端(glusterfs和glusterfs-fuse)
另,若要使用GlusterFS存储卷动态供给机制,还需部署heketi (为GlusterFS提供RESTful风格管理接口)

kubectl explain pods.spec.volumes.glusterfs
参数:
spec.volumes.glusterfs.endpoints,必须,Endpoints资源名称,用于提供Gluster集群的部分节点信息作为访问入口
# 此Endpoints需要在K8s集群中事先创建
spec.volumes.glusterfs.path,必须,GlusterFS卷路径
spec.volumes.glusterfs.readOnly,是否挂载为只读

Cinder 存储卷

Cinder是OpenStack Block Storage,通过驱动架构支持多种后端存储方式,如LVM,NFS,Ceph等,用于K8s部署于OpenStack构建的IaaS环境中

kubectl explain pods.spec.volumes.cinder
参数有:fsType,readOnly,secretRef,volumeID

持久存储卷

目的是使存储系统的配置和使用解耦
PersistentVolume,PV,由集群管理员配置提供的某存储系统上的一段存储空间,PV是集群级别的资源,不属于任何命名空间
PersistentVolumeClaim,PVC,用户从PV申请资源完成绑定,创建PVC存储卷

为了提供差异化的PV,引入新的资源对象 StorageClass ,用于将存储资源定义为具有显著特性的类别,而不是具体的PV
如 fast slow glod silver bronze等
用户通过PVC直接向意向类别发出申请,匹配由管理员事先创建的PV,或由其按需为用户动态创建PV
PV对存储系统的支持通过插件来实现
创建的PV不会验证可用性,即可直接创建,没有

创建PV

kubectl explain PersistentVolume.spec
参数:
spec.capacity,当前PV的容量
spec.accessModes,访问模式。
# ReadWriteOnce,RWO,仅可被单个节点读写挂载
# ReadOnlyMany,ROX,可被多节点同时只读挂载
# ReadWriteMany,RWX,可被多节点同时读写挂载
spec.persistentVolumeReclaimPolicy,PV被释放时的处理机制
# Retain,保持不动,由管理员手动回收
# Recycle,空间回收,删除所有文件,仅NFS和hostPath支持
# Delete,删除存储卷,仅部分云端存储支持
spec.volumeMode,卷模型,默认为Filesystem,可为Block 块设备
spec.storageClassName,默认为空,PV所属的StorageClass
spec.mountOptions,挂载选项组成的列表,如 ro、soft、hard等

kubectl get pv pv-nfs-0001
# 其中STATUS为Available 表示尚未被PVC资源所绑定
# 状态说明:
## Available 可用状态的自由资源,未被PVC绑定
## Bound 已绑定至PVC
## 绑定的PVC已被删除,但资源尚未被集群回收
## 因自动回收资源失败而处于故障状态

创建PVC

PersistentVolumeClaim,PVC,通过申请占用某PV而创建,与PV是一对一关系
kubectl explain PersistentVolumeClaim.spec
spec.accessMode,访问模式
spec.resources,当前PVC占用存储卷最小值
spec.selector,绑定时对PV应用的标签选择器
spec.storageClassName,存储类名称
spec.volumeMode,卷模型,默认为Filesystem,可为块设备 Block
spec.volumeName,直接指定要绑定的PV卷名

在Pod中使用PVC

Pod中通过persistentVolumeClain引用PVC,注意,PVC是隶属于名称空间的

存储类

按一定标准将PV分类,但K8s自身无法理解类别,可以理解为方便管理员管理的特性描述
存储类支持PV的动态创建

kubectl explain StorageClass  # 注,没有spec字段
参数:
provisioner,必须,提供存储资源的存储系统,以kubernetes.io为前缀
parameters,参数,描述要关联到的存储卷
reclaimPolicy,回收策略,默认Delete 可为Retain,由管理员手工创建的PV的回收策略由它们自身定义
volumeBindingMode,如何为PVC完成供给和绑定,默认 VolumeBindingImmediate,仅对启用了存储卷调度功能时才生效
mountOptions,挂载选项列表

kubectl get storageclasses.storage.k8s.io glusterfs -o yaml --export

说明:parameters.resturl用于指定Gluster存储系统的RESTful接口。Gluster本身并不支持这种访问方式,需要部署heketi配合Gluster以提供此类服务接口。Heketi支持认证访问,只有在restauthenabled为"true"时,restuser和restuserkey才会启用

动态PV供给

要启用PV动态供给,需要事先由管理员创建至少一个存储类。并非所有都支持PV动态供给
支持PV动态供给的存储系统可以在定义存储类后由PVC动态申请使用

# 从glusterfs存储类中申请使用5Gi存储空间

说明:PVC使用存储类有两种方式:一是使用spec.storageClassName字段;另一种是使用 volume.beta.kubernetes.io/storage-class 注解信息

PV和PVC的生命周期

1、存储供给
静态供给,由管理员手动创建的PV
动态供给,不存在静态的PV匹配到用户的PVC申请时,K8s会尝试为PVC动态创建符合需求的PV。PVC必须向存储类发起动态分配PV的请求
注:为支持使用动态供给机制,需要为准入控制器 admission controller 启用 DefaultStorageClass 选项,通过API的--admission-control配置

2、存储绑定
存储使用,Pod基于persistentVolumeClaim使用存储卷
PVC保护,启用该特性后,若有用户删除了仍处于某Pod使用中的PVC时,不会立即移除,而是推迟到不再被任何Pod资源使用后才执行删除操作
# 处于该阶段的PVC的status字段为Termination,Finalizers字段包含kubernetes.io/pvc-protection

3、存储回收
回收策略:
留存Retain PV资源需要管理员手动执行删除操作(删除PV后,手工清除存储系统上留存的数据或删除存储卷);
回收Recycle 该策略将废弃
删除Delete 存储类的默认策略是Delete

4、扩展PVC
PersistentVolumeClaimResize 支持空间大小扩展,使用时需要将allowVolumeExpansion字段值设置为 true
支持空间调整的文件系统仅有 XFS EXT3/4

downwardAPI存储卷

Pod中的容器化应用可通过环境变量或downwardAPI存储卷访问Pod对象的IP、主机名、标签、注解、UID、CPU及内存限额等
其中,标签、注解仅支持通过存储卷暴露给容器

环境变量式元数据注入

环境变量不支持中途更新操作
在valueFrom字段中嵌套fieldRef或resourceFieldRef字段引用相应数据

可通过 fieldRef 字段引用的信息:
spec.nodeName 节点名称
status.hostIP 节点IP
metadata.name Pod名称
metadata.namespace 所属名称空间
status.podIP Pod的IP
spec.serviceAccountName
metadata.uid
metadata.labels['keyname']
metadata.annotations['keyname']
可通过resourceFieldRef字段引用的信息:
# 资源请求和限额
requests.cpu limits.cpu requests.memory limits.memory

kubectl logs env-test-pod | grep "^MY_"

未定义资源请求值和限额时,获取的值为节点的可分配CPU及内存资源量

存储卷式元数据注入

将配置的字段数据映射为文件并可通过容器中的挂载点进行访问

kubectl exec dapi-vol-pod -- ls -l /etc/podinfo

标签和注解支持运行时修改
kubectl label pods dapi-vol-pod env=test
kubectl exec dapi-vol-pod -- cat /etc/podinfo/pod_labels

 

转载请注明:轻风博客 » 马哥_K8s进阶实战(5)存储卷与数据持久化

喜欢 (0)or分享 (0)