kubernetes系列(十四) - 存储之PersistentVolume
- 1. PersistentVolume(PV)简介
- 2. PersistentVolume(PV)的分类
- 3. PersistentVolumeClaim(PVC)的保护
- 4. PersistentVolume(PV)支持的底层存储类型
- 5. PersistentVolume(PV)的资源清单
- 6. PersistentVolume(PV)的状态
- 7. 实验-持久化演示说明-NFS
- 8. 关于 Statefulset
1. PersistentVolume(PV)简介
1.1 为什么需要Persistent Volume(PV)
在将PersistentVolume(PV)
之前,我们需要先讲一下Volume
Volume详情可见上一章: kubernetes系列(十三) – 存储之Volume
Volume
是被定义在pod上的(emptyDir或者hostPath
),属于计算资源
的一部分。所以Volume
是有局限性的,因为在实际的运用过程中,我们通常会先定义一个网络存储,然后从中划出一个网盘并挂接到虚拟机上。
为了屏蔽底层存储实现的细节,让用户方便使用,同时让管理员方便管理。Kubernetes从V1.0版本就引入了PersistentVolume(PV)
和与之相关联的PersistentVolumeClaim(PVC)
两个资源对象来实现对存储的管理
1.2 PersistentVolume(PV)和Volume的区别
PV
可以被理解成kubernetes
集群中的某个网络存储对应的一块存储,它与Volume
类似,但是有如下的区别:
-
PV只能是网络存储,不属于任何
Node
,但是可以在每个Node
上访问 - PV不是被定义在pod上,而是独立在pod之外被定义的。
- 意味着
pod
被删除了,PV
仍然存在,这点与Volume
不同
- 意味着
1.3 PV和PVC更具体的概念和关系
1.3.1 PersistentVolume(PV)
PersistentVolume(PV)
是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV也是集群中的资源。PV是Volume之类的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS
、iSCSl
或特定于云供应商的存储系统。
1.3.2 PersistentVolumeClaim(PVC)
PersistentVolumeClaim(PVC)
是用户存储的请求。它与Pod相似。Pod消耗节点资源,PVC
消耗PV
资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或只读多次模式挂载)
1.3.3 PV和PVC的关系和图解
pvc
是一种pv
的请求方案,PVC定义我当前需要什么样类型的PV,然后会自动在当前存在的pv中选取一个匹配度最高的pv
一个PVC
只能绑定一个PV
!!
2. PersistentVolume(PV)的分类
2.1 静态PV
简单来说
由集群管理员手动创建的一些PV
完整的概念
集群管理员创建一些PV。它们带有可供群集用户使用的实际存储的细节。它们存在于KubernetesAPl中,可用于消费。
2.2 动态PV
简单来说
配置了允许动态PV的策略后,如果当前存在的PV无法满足PVC的要求,则会动态创建PV.
动态PV了解即可
完整的概念
当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim
时,集群可能会尝试动态地为PVC创建卷。此配置基于StorageClasses
,所以要启用基于存储级别的动态存储配置要求:
- PVC必须请求
StorageClasses
- 管理员必须创建并配置
StorageClasses
才能进行动态创建 - 声明该类为“”可以有效地禁用其动态配置
- 集群管理员需要启用
API server
上的DefaultStorageClass
[准入控制器]。例如,通过确保DefaultStorageClass
位于API server
组件的--admission-control
标志,使用逗号分隔的有序值列表中,可以完成此操作
3. PersistentVolumeClaim(PVC)的保护
PVC保护的目的是确保由pod正在使用的PVC不会从系统中移除,因为如果被移除的话可能会导致数据丢失 当启用PVC保护alpha功能时,如果用户删除了一个pod正在使用的PVC,则该PVC不会被立即删除。PVC的删除将被推迟,直到PVC不再被任何 pod使用
4. PersistentVolume(PV)支持的底层存储类型
PersistentVolume
类型以插件形式实现. kubernetes
目前支持以下类型(排名不分先后):
跟上一集中的volume支持的类型差不多
-
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
VMware
Photon
Portworx Volumes
Scalelo Volumes
StorageOS
5. PersistentVolume(PV)的资源清单
5.1 资源清单示例
apiVersion: v1
kind: PersistentVolume
metadata:
name:pve003
spec:
capacity:
# 卷的大小为5G
storage: 5Gi
# 存储卷的类型为:文件系统
volumeMode: Filesystem
# 访问策略:该卷可以被单个节点以读/写模式挂载
accessModes:
- ReadNriteOnce
# 回收策略:回收
persistentVolumeReclaimPolicy: Recycle
# 对应的具体底层存储的分级
# 比如有些固态或者其他存储类型比较快,就可以定义为strong
storageClassName: slow
# (可选的)挂载选项
mountOptions:
- hard
- nfsvers=4.1
# 具体对应的真实底层存储类型为nfs
# 挂载到172服务器下的/tmp目录
nfs:
path: /tmp
server: 172.17.0.2
5.2 PV的访问模式(spec.accessModes)
5.2.1 三种访问模式
访问模式accessModes
一共有三种:
-
ReadWriteOnce
: 该卷可以被单个节点以读/写模式挂载 -
ReadOnlyMany
: 该卷可以被多个节点以只读模式挂载 -
ReadWriteMany
: 该卷可以被多个节点以读/写模式挂载
在命令行cli中,三种访问模式可以简写为:
-
RWO
–ReadWriteOnce
-
ROX
–ReadOnlyMany
-
RWX
–ReadWriteMany
但不是所有的类型的底层存储都支持以上三种,每种底层存储类型支持的都不一样!!
5.2.2 各种底层存储具体支持的访问模式
Volume Plugin | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
AWSElasticBlockStore | ✓ | – | – |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | – | – |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | – | – |
FC | ✓ | ✓ | – |
FlexVolume | ✓ | ✓ | – |
Flocker | ✓ | – | – |
GCEPersistentDisk | ✓ | ✓ | – |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | – | – |
iSCSI | ✓ | ✓ | – |
PhotonPersistentDisk | ✓ | – | – |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | – |
VsphereVolume | ✓ | – | – |
PortworxVolume | ✓ | – | ✓ |
ScaleIO | ✓ | ✓ | – |
5.3 PV的回收策略(spec.persistentVolumeReclaimPolicy)
5.3.1 回收策略的三种策略
-
Retain
(保留): pv被删除后会保留内存,手动回收 -
Recycle
(回收): 删除卷下的所有内容(rm-rf /thevolume/*
) -
Delete
(删除): 关联的存储资产(例如AWS EBS、GCE PD、Azure Disk 和OpenStack Cinder卷)将被删除。即直接把卷给删除了
5.3.2 回收策略注意事项
- 当前,只有
NFS
和HostPath
支持Recycle
回收策略
最新版本中的
Recycle
已被废弃,截图如下附:具体官网文档详细说明链接点击此处
- AWS EBS、GCE PD、Azure Disk 和Cinder 卷支持
Delete
删除策略
6. PersistentVolume(PV)的状态
PV可以处于以下的某种状态:
-
Available
(可用): 块空闲资源还没有被任何声明绑定 -
Bound
(已绑定): 卷已经被声明绑定, 注意:但是不一定不能继续被绑定,看accessModes
而定 -
Released
(已释放): 声明被删除,但是资源还未被集群重新声明 -
Failed
(失败): 该卷的自动回收失败
命令行会显示绑定到PV的PVC的名称
7. 实验-持久化演示说明-NFS
注:以下内容笔者没有实际尝试过,仅做记录使用
7.1 安装NFS服务器
yum install -y nfs-common nfs-utils rpcbind
mkdir /nfsdata
chmod 777 /nfsdata
chown nfsnobody /nfsdata
cat /etc/exports /nfsdata *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs
7.2 在其他节点上安装客户端
yum -y install nfs-utils rpcbind
mkdir /test
showmount -e 192.168.66.100
mount -t nfs 192.168.66.100:/nfsdata /test/
cd /test/
ls
umount /test/
7.3 部署PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata
server: 192.168.66.100
7.4 创建服务并使用PVC
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
8. 关于 Statefulset
-
StatefulSet
为每个Pod副本创建了一个DNS域
名,这个域名的格式为:S(podname).(headless servername)
也就意味着服务间是通过Pod域名来通信而非PodIP,因为当Pod所在Node发生故障时,Pod会被飘移到其它 Node上,PodIP会发生变化,但是Pod域名不会有变化
-
StatefulSet
使用Headless服务
来控制Pod的域名,这个域名的FQDN为:S(servicename).$(namespace).svc.cluster.local
其中,“cluster.local”指的是集群的域名
- 根据
volumeClaimTemplates
,为每个Pod 创建一个pvo,pvc的命名规则匹配模式:(volumeClaimTemplates.name)-(pod_name)
比如上面的
volumeMounts.name=www,Podname-web-[0-2]
,因此创建出来的PVC是www-web-0、www-web-1、 www-web-2
- 删除 Pod 不会删除其pvc,手动删除 pvc将自动释放pv
- Statefulset的启停顺序:
- 有序部署:部罢Statefulset时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态。
- 有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。
- 有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。
- Statefulset使用场景:
- 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC 来实现。
- 稳定的网络标识符,即Pod 重新调度后其iPodName 和 HostName不变。
- 有序部署,有序扩展,基于init containers 来实现。
- 有序收缩。