目录
emptyDir
emptyDir用法:
- 暂存空间,例如用于基于磁盘的合并排序
- 用作长时间计算崩溃恢复时的检查点
- Web服务器容器需要提供一些固定数据,保存内容管理器的容器提取的文件
例子:
vim emptyVolume-demo-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: empty-volume
spec:
containers:
- image: nginx:1.16
name: nginx-empty-demo
volumeMounts:
- mountPath: /cache # 容器里的挂载地址
name: cache-volume # 指定volume,即通过哪个目录进行挂载的
volumes:
- name: cache-volume
emptyDir: {}
运行并查看
kubectl apply -f emptyVolume-demo-pod.yaml
也可以查看pod的描述进行确认
kubectl describe pod empty-volume
注意:当创建的Pod中存在两个或者多个container的时候,所有的container共享emptyDir,进入一个container在挂载目录下创建一个文件,其他container查看时,都会看到文件变化了。
想做实验的可以copy如下配置文件,直接apply即可。
apiVersion: v1
kind: Pod
metadata:
name: empty-volume2
spec:
containers:
- image: nginx:1.16
name: nginx-empty-demo
volumeMounts:
- mountPath: /cache
name: cache-volume
- image: busybox:latest
name: busybox-empty-demo
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 6000s"]
volumeMounts:
- mountPath: /test # cahnge mount dir
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
hostPath
hostPath卷是将主机节点中的文件系统中的文件或者目录挂载到集群中
hostPath用途如下:
- 运行需要访问Docker内部的容器;使用/var/lib/docker的hostPath
- 在容器中运行cAdvisor; 使用/dev/cgroups的hostPath
除了所需path之外,用户还可以为hostPath指定type
值 | 行为 |
空 | 空字符串(默认)用于向后兼容,这意味着在挂载hostPath卷之前不会执行任何检查 |
DirectoryOrCreate | 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为0755,与kubectl具有相同的组合所有权 |
Directory | 给定的路径下必须存在目录 |
FireOrCreate | 如果给定的路径没有东西,则创建一个空文件,权限设置为0644,与kubectl 具有相同的组和所有权 |
File | 给定的路径下必须存在文件 |
socket | 给定的路径下必须存在 unix套接字 |
charDevice | 给定的路径下必须存在字符设备 |
BlockDevice | 给定的路径下必须存在块设备 |
例子:
vim hostpath-demo-01.yaml
apiVersion: v1
kind: Pod
metadata:
# 这里注意,pod name的命名规则是小写
name: hostpath-demo
spec:
containers:
- image: nginx:1.16
name: nginx-container
volumeMounts:
- mountPath: /test-hp
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /opt/data
# this field is optional
type: Directory
运行并查看,在运行起来后,可以进入创建的容器,并在容器中/test-hp挂载目录下创建一个文件,这时候可以看到Node物理机的/opt/data目录下也会出现该文件。
试着删除该pod,宿主机上的文件并不会被删除,重启启动pod后,可以继续使用该文件,但是不同的宿主机都在各自的目录下,有一份自己的文件,并没有做到唯一性。如果想要做到统一存储,就要用到PV-PVC。
kubectl apply -f hostpath-demo-01.yaml
存储PV-PVC
PersistentVolume(PV)
是由管理员设置的存储,是集群的一部分,就像 节点是集群的资源一样,pv也是集群的资源。PV是Volume之类的卷插件,但具有独立于使用PV的Pod的声明周期。此API对象包含存储实现的细节,即NFS、iSCSI或特定于云供应商的存储系统。
PersistentVolumeClaim(PVC)
是用户存储的请求,它与Pod相似。Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以读/写一次或只读多次模式挂载)
静态PV
集群管理员创建一些PV,他们带有可供集群用户使用的实际存储的细节。他们存在于Kubernetes API 中,可用于消费。
动态
当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试动态地为PVC创建卷。此配置基于StorageClasses:PVC必须请求(存储类),并且管理员必须创建并配置该类才能进行动态地创建。声明该类为“”可以有效的禁用其动态配置。
要启动基于存储级别的动态存储配置,集群管理员需要启用API server上的DefaultStorageClass[准入控制器]。例如,通过确保[DefaultStorageClass]位于API server组件的--admission-control标志,使用逗号分隔的有序值列表中,可以完成此操作。
绑定
master中的控制环路监视新的PVC,寻找匹配的PV,并将他们绑定在一起,如果为新的PVC动态调配PV,则该环路将时钟将该PV绑定到PVC。否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数据,一旦PV和PVC绑定后,PersistentVolumeClaim绑定是排他性的,不管他们是如何绑定的,PVC跟PV绑定是一对一的映射。
持久化卷声明的保护
PVC保护的目的是确保由Pod正在使用的PVC不会从系统中移除,因为如果被移除的话可能会导致数据丢失。
当pod状态为pending并且pod已经分配给节点或pod为running状态时,PVC处于活动状态。
当启用PVC保护alpha功能时,如果用户删除了一个pod正在使用的PVC,则该PVC不会被立即删除。PVC的删除将被推迟,直到PVC不再被任何pod所使用。
PV的访问模式
每个pv都有一套自己的用来描述特定功能的访问模式
- ReadWriteOnce 该卷可以被单个节点以读写的模式挂载
- ReadOnlyMany 该卷可以被多个节点以只读模式挂载
- ReadWriteMany 该卷可以被多个节点以读写模式挂载
回收策略 persistentVolumeReclaimPolicy
- retain(保留) 手动回收
- Recycle (回收) 基本擦除 (rm -rf /volume/*)
- delete(删除) 关联的存储资产将被删除
pv卷支持的多种状态
- available 一块空闲资源还没有被任何声明绑定
- bound 卷已经被绑定了
- released 声明被删除,但是资源还未被集群重新声明
- failed 自动回收失败
原理图
示例:
远程的nfs已经创建完成,并且在k8s的node节点可以正常挂载。
vim pv-volume-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce # only one role can read or write
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /data/syn # 远程nfs创建的目录
server: 188.2.139.31 # 远程nfs的IP地址
创建PV
kubectl create -f pv-volume-demo.yaml
删除PV时,在pod未占用PV的情况下,通过删除PVC可以自动删除PV,注意创建完成PV后,并不会自动创建PVC,只有创建pod时,k8s才会创建PVC绑定pod跟相关的PV
kubectl delete pvc --all
# 也可以指定PVC进行删除
kubectl get pvc
kubectl delete pvc [pvc-name]
查看:
[root@aa /home/k8s_config/volume/pv]# kubectl get pv -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
nfspv1 1Gi RWO Retain Available nfs 4m10s Filesystem
[root@aa /home/k8s_config/volume/pv]# kubectl describe pv nfspv1
Name: nfspv1
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass: nfs
Status: Available
Claim:
Reclaim Policy: Retain
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 1Gi
Node Affinity: <none>
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 188.2.139.31
Path: /data/syn
ReadOnly: false
Events: <none>
创建一个StatefulSet
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: nginx:1.16
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"] # 前面创建的PV也要时rwo
storageClassName: "nfs" # 要与前面创建的PV保持一致
resources:
requests:
storage: 1Gi
查看,发现第一个pod已经绑定了,第二个pod状态时pending,第三个pod还未创建,前一个pod运行成功后,才创建下一个pod。
可以创建多个PV来实现同类型的不同pod绑定。
再创建两个PV,可以看到三个pod运行均正常了
再查看PV,可以看到三个PV都绑定到对应的PVC上了
注意:StatefulSet创建的pod删除后,k8s会自动重建,并且创建后的pod name不会变,但是cluster IP会变,并且保存在nfs存储中的文件并不会丢失。这是因为服务间是通过域名来通信的而非Pod IP,当Pod所在Node发生故障时,Pod会漂移到其他的Node上,Pod IP会发生变化,但是Pod域名不会发生变化。
想做上面的实现的话,执行下面的配置文件即可
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: nginx:1.16
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
- image: busybox:latest
name: busybox-empty-demo
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 6000s"]
volumeMounts:
- mountPath: /test # cahnge mount dir
name: www
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
删除Pod并不会删除其PVC,手动删除PVC将会自动释放PV。删除顺序是,删除StatefulSet-->删除PVC-->系统会自动释放PV。所有的资源需要手动删除。