容器内的目录和宿主机目录进行挂载。
容器在系统上的生命周期是短暂的。
k8s用控制器创建的pod。delete相当于重启。容器的状态也会恢复到初始状态。一旦恢复到初始状态,所有的后天编辑的文件都会消失
容器和节点之间创建一个可以持久化保存容器内文件的存储卷。即使容器被摧毁、删除、重启,节点上存储卷的数据依旧存在。后续也可以继续使用。可以继续讲容器内的目录和宿主机挂载。保存的数据可以继续使用。
存储卷的方式
-
emptyDir:
-
hostPath:
-
NFS:
emptyDir
emptyDir:容器内部共享存储卷。在k8s中表示一个pod当中的多个容器共享一个存储卷目录。
emptyDir卷可以使pod当中的容器在这个存储卷上读取和写入。
emptyDir不能挂载到节点。随着pod生命周期结束。emptyDir也会结束。数据不会保留
主要用于容器内部共享数据
实验举例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx1
name: nginx1
spec:
replicas: 3
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- image: nginx:1.22
name: nginx1
volumeMounts:
#开始创建挂载卷
- name: html
#定义存储卷的名称
mountPath: /usr/share/nginx/html
#mountPath:定义容器内的挂载点。或者其他容器的共享目录
- image: nginx:1.22
name: nginx2
volumeMounts:
- name: html
#需要和上面定义的名称保持一致
mountPath: /data
#引用上一个挂载的名称。
#表示我将使用/data目录和/usr/share/nginx/html这个目录挂载
command: ["/bin/bash", "-c", "while true; do echo $(data) >> /data/index.html; sleep 2; done"]
volumes:
- name: html
emptyDir: {}
hostPath
hostPath:将容器内的挂载点和节点上的目录进行挂载。hostPath可以实现数据持久。node节点被销毁,那么数据也会丢失。
污点设置为NoExecute时节点上的pod会被驱逐。文件数据在不在?
文件数据肯定在的。只是pod节点被销毁了。并不是node节点被销毁。所有数据还保留在节点上。
只有基于控制器创建的pod会在其他节点重新部署。他又会在其他节点生成一个新的存储卷。数据依然可以持久化。
驱逐不会使文件数据丢失
实验举例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx1
name: nginx1
spec:
replicas: 3
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- image: nginx:1.22
name: nginx1
volumeMounts:
#开始创建挂载卷
- name: html
#定义存储卷的名称
mountPath: /usr/share/nginx/html
#mountPath:定义容器内的挂载点。或者其他容器的共享目录
- image: nginx:1.22
name: nginx2
volumeMounts:
- name: html
#需要和上面定义的名称保持一致
mountPath: /data
#引用上一个挂载的名称。
#表示我将使用/data目录和/usr/share/nginx/html这个目录挂载
command: ["/bin/bash", "-c", "while true; do echo $(date) >> /data/index.html; sleep 2; done"]
volumes:
- name: html
hostPath:
path: /opt/test
type: DirectoryOrCreate
#如果节点上没有这个目录则帮你创建这个目录
实现nginx1、nginx2、节点是平级关系实现三方同步
相同pod不同容器的信息
kubectl exec -it pod名称 -c 容器名称 bash
#进入相同pod中的不同容器
kubectl logs pod名称 -c 容器名称
#查看相同pod中的不同容器的日志
nfs共享存储
所有pod内的目录都和节点上的nfs共享目录形成数据卷。所有的数据文件都保存在共享目录当中。集中方便管理
nfs共享的工作流程图:
创建nfs共享目录
mkdir /data/volumes
chmod 777 /data/volumes
vim /etc/exports
/data/volumes 20.0.0.0/24(rw,no_root_squash)
#rw,no_root_squash:给客户机访问本地提供本地root权限
实验举例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx1
name: nginx1
spec:
replicas: 3
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- image: nginx:1.22
name: nginx1
volumeMounts:
#开始创建挂载卷
- name: html
#定义存储卷的名称
mountPath: /usr/share/nginx/html
#mountPath:定义容器内的挂载点。或者其他容器的共享目录
- image: nginx:1.22
name: nginx2
volumeMounts:
- name: html
#需要和上面定义的名称保持一致
mountPath: /data
#引用上一个挂载的名称。
#表示我将使用/data目录和/usr/share/nginx/html这个目录挂载
command: ["/bin/bash", "-c", "while true; do echo $(date) >> /data/index.html; sleep 2; done"]
volumes:
- name: html
nfs:
path: /data/volumes
#表示将容器和节点目录进行挂载
server: 20.0.0.35
#这里可以使用IP地址也可以使用主机名来替代。但是需要做主机名映射
基于yaml文件删除:
kubectl delete -f 文件名称.yaml
#如果是基于这个yaml文件创建的pod。可以使用这种方式删除deployment。
工作中最常见的是hostPath和NFS。推荐使用NFS
PVC和PV
PV:全程Persistent Volume 持久化存储卷。用来描述和定义一个存储卷。
PV是由运维人员来定的。
PVC:全程Persistent Volume Claim 是存储化存储的请求。
PVC是用来描述或者声明我希望使用什么样的PV来进行存储。
PVC和PV是一一对应的关系(描述、存储)
描述:期望的PV的类型是什么
存储:PV存储的大小是什么
PVC请求PV到NFS
PVC发起请求
PV是满足请求的存储卷
在k8s中PVC和PV都是虚拟化的概念。是一种虚拟存储资源。
PVC和PV的结构图:
PVC提供读写方式、存储空间等等。
PV的虚拟存储会通过NFS共享存储的方式挂载到提供共享目录的服务器
PVC发起请求的读写方式会和PV保持一致。
PVC会匹配最完整、最优路径。如果pv3被占用了,则会选择pv4。
PV和PVC静态请求的工作流程:
1、 pod内设定声明一个PVC请求。
2、 PVC请求会找一个最合适的PV来作为pod的存储卷。
3、 PV和共享目录在一一映射。
4、 最终由NFS共享目录来提供实际物理上的共享存储空间。
PV是集群当中的存储资源。PVC请求存储资源。也是对存储资源的一个检索(检查索引),选择一个最合适的PV来存储资源。
PV和PVC的生命周期管理:
-
Provisioning(配置)配置两种方式选择动态还是静态PVC
-
PVC请求request
-
检索。找一个合适的PV
-
PVC和PV会binding(绑定):就是将PV分配给PVC
-
然后开始使用:就是pod通过PVC使用存储资源NFS
删除pod时:
-
pod被删除
-
PV会releasing(释放):pod解除和volume共享挂载卷的关系,删除PVC
-
最后recycling(回收资源):保留PV。保证下一个PVC也可以使用。
PV的状态
-
Available:可用,没有被任何PVC绑定。
-
Bound:绑定,PV已经绑定了PVC,绑定即使用。
-
released:PVC已经被删除了,但是PV的存储资源还没有被集群回收
-
Failed:表示PV的资源回收失败。而且PV不可用状态。
PVC支持的读写方式
ReadWriteOnce:简称RWO。配置文件中是全称。表示存储PV可读可写。但是只能被单个pod挂载
ReadOnlyMany:简称ROX。在配置文件中是全称。表示存储PV可用以只读的方式被多个pod挂载。
ReadWriteMany: 简称RWX。在配置文件中是全称。表示存储可以支持读写的方式被多个pod共享。
NFS:可以支持三种读写和挂载方式
hostPath:只支持ReadWriteOnce方式
SCSI:
ISCSI:不支持ReadWriteMany
环境检擦
lsscsi
#查看当前设备上的SCSI设备
iscsiadm -m session -P 3
#查看服务器是否有iscsi设备
#-m session:指定操作的会话模块,管理iscsi的会话
#-P 3:显示详细信息的级别。级别是3.显示详细信息。
集群回收PV资源的方式
-
Retain:表示保留。pod和挂载点的数据不会被删除。默认方式。
-
Recycle:表示回收。PV上的数据将会被删除。挂载点的数据也会被删除。
-
Delete:表示删除。解绑时自动删除PV上的数据。本地硬盘不能使用只有云平台可以使用(AWS/EBS/GCE)。支持动态卷可用。PV不再使用(云平台自己处理)
当pod运行之后通过PVC请求到PV之后,除非pod被销毁,否则无法删除PVC
PVC和PV静态实验举例:
master01:20.0.0.32
node01:20.0.0.34
node02:20.0.0.35
k8s4主机:20.0.0.36
k8s5主机:
mkdir v{1,2,3,4,5}
vim /etc/exports
/data/v1 20.0.0.0/24(rw,no_root_squash)
/data/v2 20.0.0.0/24(rw,no_root_squash)
/data/v3 20.0.0.0/24(rw,no_root_squash)
/data/v4 20.0.0.0/24(rw,no_root_squash)
/data/v5 20.0.0.0/24(rw,no_root_squash)
exportfs -arv
#发布出去
showmount -e
#在每个节点上查看
到master01主节点上创建PV.yaml文件
vim pv.yaml
apiVersion: v1
kind: PersistentVolume
#PersistentVolume就是PV但是yaml文件中要用全称
metadata:
name: pv001
labels:
name: pv001
spec:
#设定pv的参数
nfs:
path: /data/v1
#定义pv的挂载位置
server: 20.0.0.36
#声明pv来自哪个IP地址
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
#ReadWriteMany表示支持多个pod挂载
#ReadWriteOnly表示只支持单个pod挂载
#支持多种挂载方式
capacity:
storage: 1Gi
#定义pv的大小
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/v2
server: 20.0.0.36
accessModes: ["ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/v3
server: 20.0.0.36
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/v4
server: 20.0.0.36
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/v5
server: 20.0.0.36
accessModes: ["ReadWriteMany", "ReadWriteOnce", "ReadOnlyMany"]
capacity:
storage: 5Gi
kubectl apply -f pv.yaml
#创建PV
kubectl get pv
#查看PV状态
定义一个请求向PV发起请求
vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
#定义这是PVC请求类型
metadata:
name: mypvc
spec:
#定义参数
accessModes: ["ReadWriteMany"]
#这里表示PVC期望请求的PV的读写挂载类型是什么。我希望能和PV请求到的是ReadWriteMany模式
resources:
requests:
storage: 2Gi
#PVC期望请求PV的存储大小是2Gi
#期望的PV的读写权限模式是ReadWriteMany,并且存储大小最好是2Gi。
#最好是2G。只能比2G不能比2G小
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx2
name: nginx2
spec:
replicas: 3
selector:
matchLabels:
app: nginx2
template:
metadata:
labels:
app: nginx2
spec:
containers:
- image: nginx:1.22
name: nginx2
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc
#定义pvc的名称.由mypc获取PV
kubectl get pv
#查看PV状态
表示请求成功
到k8s
kubectl get pv
cd v3
echo 123 > index.html
回到master01主机
kubectl get pod -o wide
curl nginx副本IP测试
PVC发起请求选择使用哪个PV的存储
PV通过挂载的方式和物理存储做映射
最终由物理设备提供存储卷
资源回收的方式实验举例:
保留策略:
kubectl delete pvc mypvc
#pod还存在无法删除PVC
kubectl delete deployment nginx
#删除pod后再删除PVC即可
出现released表示回收完毕
回到k8s5主机查看共享文件是否存在
kubectl edit pv pv003
把claimRef字段的内容全部删除保存推测出即可
kubectl get pv
---
回收策略:
回到pv.yaml添加回收策略
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/v3
server: 20.0.0.36
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
persistenVolumeReclaimPolicy: Recycle
capacity:
storage: 2Gi
kubectl apply -f pv.yaml
kubectl get pv
到k8s5
echo 123 > index.html
回到master01
开始删除
kubectl delete deployment nginx
kubectl delete pvc mypvc
#先删除相关联的pod再删除pvc
kubectl get pv
一段时间之后会自动变成正常状态
再回到k8s5查看资源是否被回收
---
delete策略:
delete只能在云平台且支持动态卷。本地硬盘并不支持。只能使用无法删除
回到pv.yaml添加回收策略
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/v3
server: 20.0.0.36
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
persistenVolumeReclaimPolicy: Delete
capacity:
storage: 2Gi
kubectl apply -f pv.yaml
kubectl get pv
回到k8s5
echo 123 > index.html
回到master01
开始删除
kubectl delete deployment nginx
kubectl delete pvc mypvc
#先删除相关联的pod再删除pvc
kubectl get pv
这时会变为Failled状态
kubectl edit pv pv003
把claimRef字段的内容全部删除保存推测出即可
kubectl get pv
PV状态恢复正常
实验完成!!!
总结
k8s中存储卷的模式:
-
emptyDir:容器内存储卷,锁着pod被销毁,他也会被销毁。数据不保留
-
hostPath:节点目录的存储卷,可用实现持久化存储。数据在每个节点上都有。不方便集中管理
-
nfs:共享目录存储卷。既可以实现持久化也可也实现数据集中在一个目录。这样方便管理。
PV和PVC:
-
PVC是一种请求。请求的是PV的存储资源。PV通过挂载的方式与硬盘空间共享资源
-
NFS支持PVC的所有挂载方式和读写模式
-
hostPath只支持ReadWriteOnce模式
-
PVC是以检索的方式找到匹配的PV资源
检索挂载方式和读写模式
检索PV能提供的存储资源的大小
谁合适选谁
资源回收的三种方式:
-
保留:默认可用不写
-
回收:自动回收,节点上的数据会被删除
-
删除:PV会变成failed模式。此时是不可用状态。数据也会被删除。
PVC和PV之间静态请求。一旦成百个PVC负载能力将会下降,这就需要使用动态PVC
静态比较麻烦。动态PVC实现自动的匹配PV资源