Kubernetes的持久化存储
- 前言
- 卷的类型
- emptyDir
- emptyDir的用法
- hostPath
- hostPath的用法
- PersistentVolume(PV)和PersistentVolumeClaim(PVC)
- 概念
- 静态PV和动态PV
- 静态PV
- 动态PV
- 绑定
- 持久卷声明的保护
- 持久卷类型
- PV的访问模式
- 回收策略
- 状态
- 持久化演示说明--NFS
- 安装NFS服务器
- 部署PV
- 创建服务并使用PVC
- 关于StatefulSet
前言
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet会重启它,但是容器中的文件将会丢失----容器以干净的状态(镜像最初的状态)重新启动。其次在Pod中同时运行多个容器是,这些容器之间通常需要共享文件。Kubernetes中的Volume抽象就很好的解决了这些问题。
Kubernetes中的卷有明确的寿命,与封装它的Pod相同。所以,卷的生命比Pod中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当Pod不再存在时,卷也不复存在。Kubernetes支持多种类型的卷,Pod也可以同时使用任意数量的卷。
卷的类型
Kubernetes支持以下类型的卷:
-
awsElasticBlockStore
azureDisk
azureFile
cephfs
csi
downwardAPI
emptyDir
-
fc
flocker
gcePersistentDisk
gitRepo
glusterfs
hostPath
iscsi
local
nfs
-
persistentVolumeClaim
projected
portworxVolume
quobyte
rbd
scaleIO
secret
-
storageos
vsphereVolume
emptyDir
当Pod被分配给节点时,首先会创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件。尽管该卷可以挂载到每个容器中的相同或者不同路径上。当出于任何原因从节点中删除Pod时,emptyDir中的数据将被永久删除。
注意: 容器崩溃不会从节点移除Pod,因此emptyDir卷中的数据在容器崩溃时是安全的。
emptyDir的用法
- 暂存空间,例如基于磁盘的合并序列
- 用作长时间计算崩溃恢复时的检查点
- Web服务器容器提供数据时,保存内容管理容器提取的文件
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
hostPath
hostPath卷将主机节点的文件系统中的文件或者目录挂载到集群中
hostPath的用法
- 运行需要访问的Docker内部的容器;使用/var/lib/docker的hostPath
- 在容器中运行cAdvisor;使用/dev/cgroup的hostPath
- 允许Pod指定给定的hostPath是否应该在Pod运行前存在,是否应该创建,以及它应该以什么形式存在
除了所需的path属性外,用户还可以为hostPath卷指定type
值 | 行为 |
空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。 | |
| 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。 |
| 给定的路径下必须存在目录 |
| 如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。 |
| 给定的路径下必须存在文件 |
| 给定的路径下必须存在 UNIX 套接字 |
| 给定的路径下必须存在字符设备 |
| 给定的路径下必须存在块设备 |
使用hostPath卷需要注意的是:
- 由于每个节点上的文件都不同,具有相同配置的Pod在不同节点上的行为可能会有所不同
- 当Kubernetes按照计划添加资源感知调度时,将无法考虑hostPath使用的资源
- 在底层主机上创建的文件或者目录只能由root写入。管理员需要在特权容器中以root身份运行进程,或修改主机上的文件权限以便写入hostPath卷
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# 本机的目录
path: /data
# 类型可以随意选择
type: Directory
PersistentVolume(PV)和PersistentVolumeClaim(PVC)
概念
PV是由管理员设置的存储,它是集群的一部分。就像就节点是集群中的资源一样,PV也是集群中的资源。PV是volume的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS、iSCSI、或特定的云供应商的存储系统.
PVC是用户存储的请求。它与Pod相似。Pod消耗节点资源,PVC消耗PV资源.Pod可以请求特定级别的资源,例如CPU和内存。声明可以请求特定的大小和访问方式(例如,可以读/写一次或者 只读多次模式挂载)
静态PV和动态PV
静态PV
集群管理员创建一些PV。他们带有可供集群用户使用的实际存储的细节。他们存在于Kubernetes API中,可用于消费
动态PV
当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试动态地为PVC创建卷。此配置基于StorageClasses:PVC必须请求[存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为 “” 可以有效地禁止其动态配置
如果要启用基于存储级别的动态存储配置,集群管理员需要启用API Server上的 DefaultStorageClass[准入控制器]。在API Server组件的 "–admission-control"的有序列表中插入DefaultStorageClass
绑定
master中的控制环路监视新的PVC,寻找匹配大的PV,并将他们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将该PV绑定到PVC。负责,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦PV和PVC绑定后,PVC绑定时排他性的,不管他们时如何绑定的。PVC跟PV绑定是一对一的映射。
持久卷声明的保护
PVC保护的目的是确保由Pod正在使用的PVC不会从系统中移除,因为如果被移除的话可能会导致数据丢失
注意:
- 当Pod状态为 Pending 并且 Pod已经分配给节点或Pod为Running状态时,PVC处于活动状态。
- 当启用PVC保护alpha功能时,如果用户删除了一个Pod正在使用的PVC,则该PVC不会被立即删除。PVC的删除将被推迟,知道PVC不再被任何Pod使用
持久卷类型
PV类型以插件形式实现。Kubernetes目前支持以下插件类型:
- 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 ScaleIO Volumes StorageOS
PV的访问模式
PV可以以资源提供者支持的任何方式挂载到主机上。。供应商具有不同的功能,每个PV的访问模式都将被设置为该卷支持的特定模式。例如,NFS可以支持多个读/写客户端,但特定的NFS PV可能以只读方式导出到服务器上。每个PV都有一套自己的用来描述特定功能的访问模式。
- RWO ReadWriteOnce:该卷可以被单个节点以读/写模式挂载
- ROX ReadOnlyMany:该卷可以被多个节点以只读模式挂载
- RWX ReadWriteMany:该卷可以被多个节点以读/写模式挂载
注意:一个卷一次只能使用一种访问模式挂载,即使它支持很多访问模式。例如,GCEPersistentDisk 可以由单个节点作为
ReadWriteOnce 模式挂载,或由多个节点以 ReadOnlyMany 模式挂载,但不能同时挂载
Volume 插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
AWSElasticBlockStoreAWSElasticBlockStore | ✓ | - | - |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | - | - |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | - | - |
FC | ✓ | ✓ | - |
FlexVolume | ✓ | ✓ | - |
Flocker | ✓ | - | - |
GCEPersistentDisk | ✓ | ✓ | - |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | - | - |
iSCSI | ✓ | ✓ | - |
PhotonPersistentDisk | ✓ | - | - |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | - |
VsphereVolume | ✓ | - | - (当 pod 并列时有效) |
PortworxVolume | ✓ | - | ✓ |
ScaleIO | ✓ | ✓ | - |
StorageOS | ✓ | - | - |
回收策略
- Retain(保留) —手动回收
- Recycle(回收) — 基本擦除(rm -rf /thevolume/*)
- Delete(删除) —关联的存储资源(例如 AWS EBS GCE Azure Disk 和 OpenStack Cinder卷)将被删除
当前,只有NFS和HostPath支持回收策略。AWS EBS GCE Azure Disk 和 OpenStack Cinder卷支持删除策略
状态
卷可以处于以下的某种状态:
- Available(可用)----一块空闲资源还没有被任何声明绑定
- Bound(已绑定) ----卷已经被声明绑定
- Released(已释放) ----声明被删除,但是资源没未被集群重新声明
- Failed(失败) ----该卷的自动回收失败
kubectl get pvc
可以显示绑定到的PV的PVC的名称
持久化演示说明–NFS
安装NFS服务器
##安装nfs和rpcbind
yum -y install nfs-common nfs-utils rpcbind
##创建共享目录,修改权限
mkdir /nfsdata/{1..5}
chown nfsnobody /nfsdata -R
chmod 666 /nfsdata -R
##声明nfs配置文件
/nfsdata/1 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/2 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/3 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/4 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/5 *(rw,no_root_squash,no_all_squash,sync)
##说明
- rw 可读写
- no_root_squash root有完全读写权限
- no_all_squash 保留UID,GID
sync 同步刷新
##启动服务,设置开机自启动
systemctl start rpcbind
systemctl enable nfs
systemctl stert rpcbind
部署PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/1
server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv2
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/2
server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv3
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/3
server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv4
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/4
server: 192.168.2.80
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv5
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/5
server: 192.168.2.80
###
kubectl apply -f nfs-pv.yaml
创建服务并使用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
###
kubectl apply -f nfs-pvc.yaml
关于StatefulSet
- 配置Pod name的模式为 $(StatefulSet Name)+序号
- SatefulSet为每个Pod副本创建了DNS域名,这个域名格式为:$(Pod Name).(Headless ServerName),这就意味着服务间是通过Pod域名来访问而非Pod IP,因为Pod当前所在的Node节点发生故障时,Pod会漂移到其他Node上,Pod IP会发生改变,但是Pod域名不会变化。
- StatefulSet使用Headless服务来控制Pod的域名,这个域名的 FQDN为:(namespace).svc.cluster.local 。其中”cluster.local“就是集群的域名。
- 根据PVC,为每个Pod创建一个pvc,pvc的命令规则匹配模式:volumeClaimTemplates.name-Pod_name
- 删除Pod不会删除其PVC,手动删除PVC将自动释放PV