K8s - 目录
管理存储是管理计算的一个明显问题。该 PersistentVolume 子系统为用户和管理员提供了 一个 API,用于抽象如何根据消费方式提供存储的详细信息。为此,我们引入了两个新的 API 资源: PersistentVolume 和 PersistentVolumeClaim。
PersistentVolume(PV) 是集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源一样。 PV 是容量插件,如 Volumes,但其生命周期独立于使用 PV 的任何单个 pod。 此 API 对象捕获存储实现的详细信息,包括 NFS,iSCSI 或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC) 是由用户进行存储的请求。 它类似于 pod。 Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存) 。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读) 。
虽然 PersistentVolumeClaims 允许用户使用抽象存储资源,但是 PersistentVolumes 对于不同的问题,用户通常需要具有不同属性(例如性能) 。群集管理员需要能够提供各种 PersistentVolumes 不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有 StorageClass 资源。
StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes 本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。
PVC 和 PV 是一 一对应的。
PV 是群集中的资源。PVC 是对这些资源的请求,并且还充当对资源的检查。PV 和 PVC 之间 的相互作用遵循以下生命周期:
Provisioning ==> Binding ==> Using ==> Releasing ==> Recycling
供应准备 Provisioning:通过集群外的存储系统或者云平台来提供存储持久化支持。
绑定 Binding:用户创建 PVC 并指定需要的资源和访问模式。在找到可用PV 之前,PVC 会保持未绑定状态。
使用 Using:用户可在 pod 中像 volume 一样使用 PVC。
释放 Releasing:用户删除 PVC 来回收存储资源,PV 将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他 PVC 使用。
回收 Recycling:PV 可以设置三种回收策略: 保留(Retain) ,回收(Recycle) 和删除 (Delete) 。
GCEPersistentDisk
AWSElasticBlockStore
AzureFile
AzureDisk
FC (Fibre Channel)
Flexvolume
Flocker
NFS
iSCSI
RBD (Ceph Block Device)
CephFS
Cinder (OpenStack block storage)
Glusterfs
VsphereVolume
Quobyte Volumes
HostPath (仅单节点测试 - 不支持任何方式的本地存储,并且不会在多节点集群中工作)
Portworx Volumes
ScaleIO Volumes
StorageOS
状态 | 说明 |
---|---|
Available | 资源尚未被 claim 使用。 |
Bound | 卷已经被绑定到 claim 了。 |
Released | claim 被删除,卷处于释放状态,但未被集群回收。 |
Failed | 卷自动回收失败。 |
状态 | 全称 | 说明 |
---|---|---|
RWO | ReadWriteOnce | 有读写权限且只能被单个node挂载。 |
ROX | ReadOnlyMany | 只读权限允许被多个node挂载。 |
RWX | ReadWriteMany | 有读写权限允许被多个node挂载。 |
当Pod指定到某个节点上时,首先创建的是一个emptyDir卷,并且只要Pod在该节点上运行,卷就一直存在。就像它的名称表示的那样,卷最初是空的。尽管Pod中的容器挂载emptyDir卷的路径可能相同也可能不同,但是这些容器都可以读写emptyDir卷中相同的文件。当Pod因为某些原因被从节点上删除时,emptyDir卷中的数据也会永久删除。
注意:
/etc/nginx/conf.d/
中原本有文件 default.conf
,挂载目录中没有文件,那么容器目录中的文件 default.conf
会被清空。后续再将自定义的的 nginx 子配置文件放入挂载目录下,文件会自动同步到容器目录下。emptyDir的一些用途:
默认情况下,emptyDir卷存储在支持该节点所使用的介质上;这介质可以是磁盘或SSD或网络存储,这取决于环境。
nginx pod 增加一个 emptyDir 类型的 Volume 存储卷,并分别挂载 html 目录、conf 目录。
# nginx-emptyDir-volume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-emptyDir-volume
spec:
replicas: 2
selector:
matchLabels:
app: nginx-emptyDir-volume
template:
metadata:
name: nginx-emptyDir-volume
labels:
app: nginx-emptyDir-volume
spec:
volumes:
- name: emptyDir-volume # 增加一个名为 emptyDir-volume 的 volume 存储卷。
emptyDir: { } # pod 分配到 node 时创建的,k8s 自动分配的一个目录,pod 从 node 移除时 emptyDir 中的数据永久删除。
containers:
- image: nginx
name: nginx
volumeMounts:
- name: emptyDir-volume
mountPath: /home/nginx/html # 挂载 nginx 静态页面
- name: emptyDir-volume
mountPath: /etc/nginx/conf.d/ # 挂载 nginx 配置文件
pod 内多容器之间的数据共享
// TODO
官方文档
注意:
hostPath 卷能将宿主节点文件系统上的文件或目录挂载到 Pod 中。虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
例如,hostPath 的一些用途:
除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type:
值 | 行为 |
---|---|
空字符串(默认)是为了向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate | 如果给定路径不存在任何内容,则会根据需要在此处创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。 |
Directory | 目录必须存在于给定路径 |
FileOrCreate | 如果给定路径不存在任何内容,则会根据需要在此处创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。 |
File | 文件必须存在于给定路径 |
Socket | 给定路径中必须存在 UNIX 套接字 |
CharDevice | 字符设备必须存在于给定路径中 |
BlockDevice | 块设备必须存在于给定路径 |
使用这种类型的时需要注意,因为:
# nginx-hostPath-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-hostpath-volume
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
- name: file
mountPath: /usr/share/nginx/html/index.html
- name: conf
mountPath: /etc/nginx/conf.d
volumes:
- name: html
hostPath:
path: /data/hostPath/data/nginx-hostpath-volume/html # 主机上目录的路径。如果路径是符号链接,它将跟随链接到真实路径。
type: DirectoryOrCreate # 如果给定路径不存在任何内容,则会根据需要在此处创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。
- name: file
hostPath:
path: /data/hostPath/data/nginx-hostpath-volume/html/index.html # 主机上目录的路径。如果路径是符号链接,它将跟随链接到真实路径。
type: FileOrCreate # 如果给定路径不存在任何内容,则会根据需要在此处创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。
- name: conf
hostPath:
path: /data/hostPath/data/nginx-hostpath-volume/conf
type: DirectoryOrCreate
官方文档
nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。
注意: 在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用。
# nginx-nfs-volume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-nfs-volume
spec:
replicas: 2
selector:
matchLabels:
app: nginx-nfs-volume
template:
metadata:
name: nginx-nfs-volume
labels:
app: nginx-nfs-volume
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
server: 192.168.80.200
path: /data/nfs/data # 此路径必须存在,否则 pod 将无法启动。
要了解更多详情请参考 NFS 示例。
官方文档
persistentVolumeClaim 卷用来将持久卷(PersistentVolume) 挂载到 Pod 中。 持久卷申领(PersistentVolumeClaim)是用户在不知道特定云环境细节的情况下"申领"持久存储 (例如 GCE PersistentDisk 或者 iSCSI 卷)的一种方法。
更多详情请参考持久卷示例。
官方文档
创建5个不同配置的 PV:
# pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/nfs/data/v1
server: 192.168.80.200
accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/nfs/data/v2
server: 192.168.80.200
accessModes: [ "ReadWriteOnce" ]
capacity:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/nfs/data/v3
server: 192.168.80.200
accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
capacity:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/nfs/data/v4
server: 192.168.80.200
accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
capacity:
storage: 15Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/nfs/data/v5
server: 192.168.80.200
accessModes: [ "ReadWriteMany","ReadWriteOnce" ]
capacity:
storage: 20Gi
执行创建命令
kubectl apply -f pv-damo.yaml
查询验证
kubelet get pv
输出内容:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 2Gi RWO,RWX Retain Available 5s
pv002 5Gi RWO Retain Available 5s
pv003 10Gi RWO,RWX Retain Available 5s
pv004 15Gi RWO,RWX Retain Available 5s
pv005 20Gi RWO,RWX Retain Available 5s
编写 yaml 文件,并创建 PVC
创建一个 PVC,需要 6G 存储。所以不会匹配 pv001、pv002。
# pvc-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nginx
namespace: default
spec:
accessModes: [ "ReadWriteMany" ]
resources:
requests:
storage: 6Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pvc-nginx
namespace: default
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
persistentVolumeClaim:
claimName: pvc-nginx
执行命令创建
kubectl apply -f pvc-demo.yaml
查询验证
查询 pvc:
kubectl get pvc
输出内容:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-nginx Bound pv003 10Gi RWO,RWX 13s
查询 PV:
kubectl get pv
输出内容:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 2Gi RWO,RWX Retain Available 11m
pv002 5Gi RWO Retain Available 11m
pv003 10Gi RWO,RWX Retain Bound default/pvc-nginx 11m
pv004 15Gi RWO,RWX Retain Available 11m
pv005 20Gi RWO,RWX Retain Available 11m
注意:
released
状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他 PVC 使用。删除 PVC
注意:PVC 在被 pod 使用时是无法删除的。
删除 pod:
kubectl delete -f pvc-demo.yaml
输出内容:
persistentvolumeclaim "pvc-nginx" deleted
pod "pvc-nginx" deleted
查询 PVC:
No resources found in default namespace.
查询 PV:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 2Gi RWO,RWX Retain Available 38m
pv002 5Gi RWO Retain Available 38m
pv003 10Gi RWO,RWX Retain Released default/pvc-nginx 62s
pv004 15Gi RWO,RWX Retain Available 2m2s
pv005 20Gi RWO,RWX Retain Available 38m
删除 PV
kubectl delete pv pv003
输出内容:
persistentvolume "pv003" deleted
查看 PV:
kubectl get pv
输出内容:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 2Gi RWO,RWX Retain Available 41m
pv002 5Gi RWO Retain Available 41m
pv004 15Gi RWO,RWX Retain Available 4m40s
pv005 20Gi RWO,RWX Retain Available 41m
PV 回收策略:
当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除,从而允许 该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群,当其被 从申领中释放时如何处理该数据卷。 目前,数据卷可以被 Retained(保留)、Recycled(回收,Recycle 已被废弃)或 Deleted(删除)。
保留(Retain)
回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象 被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为”已释放(released)”。 由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:
删除(Delete)
对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。 动态供应的卷会继承其 StorageClass 中设置的回收策略,该策略默认 为 Delete。 管理员需要根据用户的期望来配置 StorageClass;否则 PV 卷被创建之后必须要被 编辑或者修补。参阅更改 PV 卷的回收策略。