存储简介
在Kubernetes中,存储是一个关键的部分,用于持久化应用程序的数据。Kubernetes的存储模型支持多种存储类型,并且能根据应用程序的需求动态地提供存储资源。以下是Kubernetes存储的基本概念和机制。
Kubernetes支持很多类型的卷。Pod可以同时使用任意数目的卷类型。临时卷类型的生命周期与Pod相同,但持久卷可以比Pod的存活期长。当Pod不再存在时,Kubernetes也会销毁临时卷;不过Kubernetes不会销毁持久卷。对于给定Pod中任何类型的卷,在容器重启期间数据都不会丢失。
存储类型
Kubernetes支持的主要存储类型包括:
临时存储(EphemeralStorage):
如Pod的EmptyDir卷,随着Pod的生命周期结束而丢失。
应用场景:缓存数据或临时文件,不需要持久化的场景。
持久化存储(PersistentStorage):
通过持久卷(PersistentVolume,PV)和持久卷声明(PersistentVolumeClaim,PVC)来管理。
应用场景:数据库、文件存储等需要持久化数据的场景。
临时卷
downwardAPI
downwardAPI的用法可以回顾 Kubernetes从零到精通(05-Pod)中的Downward API卷。在这类卷中,所公开的数据以纯文本格式的只读文件形式存在。
configMap、secret
用于挂载配置文件或敏感信息,如密码、令牌等。配置文件以键值对的方式存储,并且可以通过卷挂载到Pod中。用法可以回顾 Kubernetes从零到精通(13-Configmap、Secret)中的挂载文件。
emptyDir
每次Pod启动时创建一个新的空目录。Pod删除时,数据也会被删除。用于存储Pod运行时的临时数据。配置示例如下:
apiVersion: v1
kind: Pod
metadata:name: shared-pod
spec:containers:- name: container1image: busyboxcommand: ['sh', '-c', 'echo Hello from container1 > /usr/share/message && sleep 3600']volumeMounts:- mountPath: /usr/sharename: shared-volume- name: container2image: busyboxcommand: ['sh', '-c', 'cat /usr/share/message && sleep 3600']volumeMounts:- mountPath: /usr/sharename: shared-volumevolumes:- name: shared-volumeemptyDir: {} ##定义emptyDir类型
持久卷
存储的管理是一个与计算实例的管理完全不同的问题。 PersistentVolume子系统为用户和管理员提供了一组 API,将存储如何制备的细节从其如何被使用中抽象出来。 为了实现这点,引入了两个新的 API 资源:PersistentVolume和PersistentVolumeClaim。
PersistentVolume(PV,持久卷)
PV是集群中的持久存储资源,管理员预先创建并提供给集群中的应用使用。
PV是集群级别的资源,与Pod的生命周期无关,它独立存在,能够在Pod之间共享数据。
PV有两种方式创建:管理员手动创建、使用存储类(Storage Class)来动态制备。
PersistentVolumeClaim(PVC,持久卷声明)
PVC是用户请求存储的方式。用户通过声明一个PVC,向Kubernetes请求一块符合指定大小和访问模式的存储。
PVC绑定到一个PV时,Pod可以通过该PVC来访问持久化存储。
持久卷的类型
PV持久卷是用插件的形式来实现的。Kubernetes目前主要支持以下插件:
csi - 容器存储接口(CSI)
fc - Fibre Channel(FC)存储
hostPath - HostPath卷(仅供单节点测试使用;不建议在生产环境使用,涉及到安全等问题)
iscsi - iSCSI(IP上的 SCSI)存储
local - 节点上挂载的本地存储设备
nfs - 网络文件系统(NFS)存储
持久卷的访问模式
Kubernetes支持多种存储访问模式,允许用户根据具体需求选择存储的使用方式:
ReadWriteOnce (RWO):卷可以被单个节点以读写模式挂载。仍然可以被在同一节点上运行的多个Pod访问。
ReadOnlyMany (ROX):卷可以被多个节点以只读模式挂载。
ReadWriteMany (RWX):卷可以被多个节点以读写模式挂载。
ReadWriteOncePod (RWOP):卷可以被单个 Pod 以读写方式挂载。整个集群中只有一个Pod可以读取或写入。
不同的插件所能提供的访问模式有所不同,具体要看官方的更新说明。
持久卷的回收策略
目前的回收策略有:
Retain -- 手动回收。当删除pvc的时候,pv仍然存在,处于released状态,但是它不能被其他pvc绑定使用,里面的数据还是存在的。
Delete -- 删除存储卷。当删除pvc的时候,pv不存在。
持久卷的阶段Phase
每个持久卷会处于以下阶段(Phase)之一:
Available:卷是一个空闲资源,尚未绑定到任何pvc
Bound:该卷已经绑定到某pvc
Released:所绑定的pvc已被删除,但是关联存储资源尚未被集群回收
Failed:卷的自动回收操作失败
存储类(Storage Class)
StorageClass用于动态创建PV。它定义了存储提供者的类型和配置,如Amazon EBS、Google Persistent Disks、NFS等。
动态存储分配时,Kubernetes根据PVC和关联的StorageClass自动创建PV。不需要管理员提前手动创建PV。
持久卷配置示例
以下提供两个示例,一个不使用StorageClass,一个使用StorageClass。通用做法是使用StorageClass动态制备。
1.不使用StorageClass的静态制备
1.1 创建PV:
apiVersion: v1
kind: PersistentVolume
metadata:name: my-pv
spec:capacity: #PV的容量,设定为1Gistorage: 1GiaccessModes: #持久卷的访问模式- ReadWriteOncepersistentVolumeReclaimPolicy: Retain #持久卷的回收策略hostPath: #持久卷的类型path: "/mnt/data"
1.2 创建PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: my-pvc
spec:accessModes: #PVC请求与PV相同的访问模式- ReadWriteOnceresources:requests: #请求1Gi的存储容量storage: 1Gi
1.3 在Pod中使用PVC:
apiVersion: v1
kind: Pod
metadata:name: my-pod
spec:containers:- name: my-containerimage: nginxvolumeMounts: #PVC被挂载到容器中- mountPath: "/usr/share/nginx/html"name: my-volumevolumes:- name: my-volumepersistentVolumeClaim: #使用之前创建的PVCclaimName: my-pvc
2.使用StorageClass的动态制备
2.1 创建StorageClass:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: my-storage-class
provisioner: kubernetes.io/nfs #指定了存储供应器为NFS
parameters: #NFS服务器和路径等参数server: nfs-server.example.compath: /exported/path
2.2 创建PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: my-dynamic-pvc
spec:accessModes: #持久卷的访问模式- ReadWriteManyresources:requests:storage: 5Gi #请求5Gi的存储容量storageClassName: my-storage-class #使用上面的StorageClass来动态创建PV
2.3 在Pod中使用PVC:
apiVersion: v1
kind: Pod
metadata:name: dynamic-pod
spec:containers:- name: my-containerimage: nginxvolumeMounts: #PVC被挂载到容器中- mountPath: "/usr/share/nginx/html"name: dynamic-volumevolumes:- name: dynamic-volumepersistentVolumeClaim: #使用通过StorageClass动态创建的PVCclaimName: my-dynamic-pvc
卷快照
VolumeSnapshotContent、VolumeSnapshot是Kubernetes中用于管理和操作存储卷快照的关键CRD对象资源。快照是一种用于捕获持久卷(Persistent Volume,PV)特定时间点状态的技术,常用于备份和恢复数据的场景。卷快照仅支持树外CSI卷插件,树内卷插件已被弃用。
VolumeSnapshotContent
VolumeSnapshotContent是Kubernetes中用于存储快照实际内容的对象。它是快照的实际后端表示,通常由存储提供商创建并管理。它类似于持久卷(PV)。
同样的,快照可以通过两种方式进行制备:管理员手动创建的预制备、使用卷快照类VolumeSnapshotClass)的动态制备,从PVC中动态获取快照,而不用使用已经存在的快照。
VolumeSnapshot
VolumeSnapshot是用户发起的存储卷快照的对象。它代表了用户对特定持久卷(PV)的快照请求。VolumeSnapshot本身并不包含数据,它只是一个指向快照数据的抽象对象。它类似于持久卷声明(PVC)。
卷快照类(VolumeSnapshotClass)
VolumeSnapshotClass是定义快照特性和存储系统之间的配置类,也是CRD对象资源。它类似于StorageClass,用于定义如何管理存储系统中的快照。不同的存储系统可能支持不同的快照操作,如retain(保留快照)、delete(删除快照),以及其他特性。
卷快照配置示例
1.不使用VolumeSnapshotClass的静态制备
1.1 创建VolumeSnapshotContent:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:name: test-snapshot-content
spec:deletionPolicy: Delete driver: csi-hostpath source:snapshotHandle: xxxxxxxx #底层外部卷快照的唯一标识符,引用实际的存储快照volumeSnapshotRef:name: test-snapshotnamespace: default
1.2 创建VolumeSnapshot:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:name: test-snapshotnamespace: default
spec:source:volumeSnapshotContentName: test-snapshot-content #引用上面创建的资源
2.使用VolumeSnapshotClass的动态制备
2.1 创建VolumeSnapshotClass:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:name: csi-hostpath-snapclass
driver: csi-hostpath
deletionPolicy: Delete
2.2 创建VolumeSnapshot:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:name: new-snapshotnamespace: default
spec:volumeSnapshotClassName: csi-hostpath-snapclass #引用上面的class来动态创建VolumeSnapshotContentsource:persistentVolumeClaimName: pvc-test #pvc的名称
卷快照恢复
基于快照VolumeSnapshot恢复PVC,这对于备份和恢复场景非常有用,以下是示例:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc-test-v2 #从快照创建的新PVC的名称
spec:storageClassName: csi-hostpath-snapclass #创建快照的VolumeSnapshotClassdataSource:name: new-snapshot #VolumeSnapshot的名称kind: VolumeSnapshotapiGroup: snapshot.storage.k8s.ioaccessModes:- ReadWriteOnceresources:requests:storage: 10Gi
卷克隆
卷克隆是指创建一个现有卷的副本,不使用快照技术。这个副本可以像任何其他标准卷一样使用。同样,仅适用于CSI卷插件。以下是如何基于现有的PVC创建一个克隆卷的步骤:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: clone-of-pvc-1 #新创建的克隆卷的名称namespace: myns #源PVC和目标PVC必须在相同的命名空间中
spec:accessModes:- ReadWriteOncestorageClassName: cloning #存储类名称resources:requests:storage: 5Gi #新卷的存储请求大小,必须大于或等于源卷的大小dataSource:kind: PersistentVolumeClaimname: pvc-1 #源PVC必须处于Bound状态且可用(不在使用中)