K8s 存储之volumes
因此,Kubernetes引入了PV和PVC这两种资源对象,将底层的存储实现细节进行屏蔽,使得用户只需要关心存储需求即可。Containers中的磁盘文件是短暂的,当容器崩溃时,kubelet会已最干净的状态去重启容器。PV(Persistent Volume)是持久化存储卷,是对底层的共享存储的一种抽象。PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需
文章目录
Volumes
Containers中的磁盘文件是短暂的,当容器崩溃时,kubelet会已最干净的状态去重启容器。另外当一个Pod运行多个container时,各个容器需要共享这些文件,Kubernetes的Volume可以解决两个问题
一些需要持久化的数据才会用到volume,或者一些需要共享数据的容器需要volumes
详情可参考: volumes 官网文档地址
EmptyDir
emptyDir官方文档
生命周期和Pod一致、如果Pod删除了,emptyDir的数据也会被删除
emptyDir 卷最初是空的,主要共享数据
在创建pod时、卷会自动创建在pod对应的node上,默认路径一般都在/var/lib/kubelet/pods/podid下 ,则容器内emptydir的大小应该也是受到/var大小的限制
EmptyDir能实现共享数据的前提:
必须在同一个node上、不管你是同Pod还是不同Pod
# 尝试找到empdir对应的宿主机目录
[root@k8s-master01 pods]# kubectl exec -it dp-cm-66c5664bbc-k7pmm -- sh
/ # cd /cache/
/cache # ls
whtest
[root@k8s-master01 pods]# find / -name whtest -type f
/var/lib/kubelet/pods/731600ab-a710-4dcb-9fdc-d90c287b03c5/volumes/kubernetes.io~empty-dir/cache-volume/whtest
# 这里是pod的id 不是容器的id
容器ID查询方法
kubectl describe pods/AA | grep "Container ID"
ctr -n k8s.io containers ls | grep "Container ID"
PodID查询方法
kubectl get pods/dp-cm-66c5664bbc-k7pmm -o jsonpath='{.metadata.uid}'
EmtyDir使用
为容器提供空目录
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: dp-cm
name: dp-cm
spec:
replicas: 1
selector:
matchLabels:
app: dp-cm
template:
metadata:
labels:
app: dp-cm
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
[root@k8s-master01 ~]# kubectl exec -it dp-cm-67c6d7fffc-fcj5m -- sh
/ # cd /cache/
/cache # ls
多容器共享数据
# 一个Pod创建两个容器 测试数据共享
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: dp-cm
name: dp-cm
spec:
replicas: 1
selector:
matchLabels:
app: dp-cm
template:
metadata:
labels:
app: dp-cm
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx
volumeMounts:
- mountPath: /cache
name: cache-volume
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx2
command: ['sleep','3600'] # 因为同pod共享网络名称空间,镜像都是nginx、都拉起会端口占用
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
# 测试数据共享
[root@k8s-master01 pod]# kubectl exec -it dp-cm-84b8877cd7-7phtp -c nginx -- sh
/ # touch /cache/sharedir
/ # [root@k8s-master01 pod]# kubectl exec -it dp-cm-84b8877cd7-7phtp -c nginx2 -- ls /cache/
sharedir
生命周期验证
- 如果容器被销毁、数据就没了
- 使用emptydir共享的目录,生命周期和容器一致
- 容器重启没事 ,只要容器id不变 基本上数据就不会丢
# 创建test文件
[root@k8s-master01 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINE
dp-cm-6c669f8688-l4vb2 1/1 Running 0 7s 172.25.92.90 k8s-master02 <none> <none>
[root@k8s-master01 pod]# kubectl exec -it dp-cm-6c669f8688-l4vb2 -- sh
/ # cd /mnt
/mnt # ls
/mnt # touch test
# 删除pod
[root@k8s-master01 pod]# kubectl delete deploy/dp-cm
# 重新创建查看是否还有test
[root@k8s-master01 pod]# kubectl create -f dp-cm.yaml
[root@k8s-master01 pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
dp-cm-6c669f8688-s9ztg 1/1 Running 0 23s
[root@k8s-master01 pod]# kubectl exec -it dp-cm-6c669f8688-s9ztg -- sh
/ # cd /mnt
/mnt # ls
/mnt #
Hostpath
- 将宿主机的目录或文件映射到容器中、受节点限制使用较少
hostPath官网地址
hostpath使用
- hostpath卷则是将主机节点的文件系统中的文件或目录挂载到集群中。当Pod删除时,hostpath卷不会被删除。因此,从这个特点来看,hostpath卷并不算是严格意义上的临时卷。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: dp-cm
name: dp-cm
spec:
replicas: 1
selector:
matchLabels:
app: dp-cm
template:
metadata:
labels:
app: dp-cm
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx
volumeMounts:
- mountPath: /cache
name: cache-volume
- mountPath: /etc/timezone
name: time-zone
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx2
command: ['sleep','3600']
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
- name: time-zone
hostPath:
path: /etc/timezone # # 宿主机上目录位置
type: File # 此字段为可选
除了必需的 path 属性之外,
你可以选择性地为 hostPath 卷指定 type。
支持的 type 值如下:
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory 在给定路径上必须存在的目录。
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File 在给定路径上必须存在的文件。
Socket 在给定路径上必须存在的 UNIX 套接字。
CharDevice 在给定路径上必须存在的字符设备。
BlockDevice 在给定路径上必须存在的块设备。
验证:
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7b4555ddf9-z7wd6 -c nginx -- cat /etc/timezone
Asia/Shanghai
验证2:
如果这个pod挂了,跑到别的节点了 是否还能正常挂载呢?
# 假设pod目前再master03节点
1. 先创建一个其他节点没有的文件
[root@k8s-master01 pod]# cp /etc/timezone{,.bak}
[root@k8s-master01 pod]# vim /etc/timezone.bak
[root@k8s-master01 pod]# cat /etc/timezone.bak
Asia/Shanghai
Asia/Anhui
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx
volumeMounts:
- mountPath: /etc/timezone
name: time-zone
...
hostPath:
path: /etc/timezone.bak
type: FileOrCreate
# 现在pod在master03上
[root@k8s-master01 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dp-cm-7c99665f9-r8n8v 1/1 Running 0 33s 172.18.195.36 k8s-master03 <none> <none>
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7c99665f9-r8n8v -- cat /etc/timezone
Asia/Shanghai
Asia/Anhui
# 指定node 将pod创建到master01上,但是master01节点没有zonetime.bak这个文件
[root@k8s-master01 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dp-cm-ccbcfd49c-zvn8k 1/1 Running 0 7s 172.25.244.211 k8s-master01 <none> <none>
[root@k8s-master01 pod]# kubectl exec -it dp-cm-ccbcfd49c-zvn8k -- cat /etc/timezone
[root@k8s-master01 pod]#
# 查看容器内没有信息,这就是hostpath的弊端,如果pod被重建到其他节点,对应的宿主机映射路径 node上又不存在,那容器中就无数据
NFS
- 生产环境不推荐使用、nfs高可用没有保障
node01安装nfs
yum -y install nfs-utils
mkdir /data/nfs # 创建共享目录
[root@k8s-node01 nfs]# cat /etc/exports # 写入exports配置
/data/nfs 192.168.255.0/24(rw,sync,no_subtree_check,no_root_squash)
exportfs -r
systemctl restart nfs
# master01 节点操作
mount -t nfs 192.168.255.141:/data/nfs /mnt
cd /mnt
touch 123# 测试创建文件
# 其他节点安装nfs客户端
yum -y install nfs-utils
# 容器挂载nfs
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: dp-cm
name: dp-cm
spec:
replicas: 3
selector:
matchLabels:
app: dp-cm
template:
metadata:
labels:
app: dp-cm
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx
volumeMounts:
- mountPath: /opt
name: nfs-volume
nodeName: k8s-master01
volumes:
- name: nfs-volume
nfs:
server: 192.168.255.141
path: /data/nfs/
验证
# 可以看到使用nfs也可以实现数据共享、虽然容器都不再同一个节点
# 跨node实现数据共享,这是emptydir不具备的
[root@k8s-master01 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dp-cm-7689bc6dd7-964xb 1/1 Running 0 16s 172.18.195.38 k8s-master03 <none> <none>
dp-cm-7689bc6dd7-kqp77 1/1 Running 0 14s 172.25.244.215 k8s-master01 <none> <none>
dp-cm-7689bc6dd7-s6s5c 1/1 Running 0 11s 172.17.125.27 k8s-node01 <none> <none>
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-964xb -- ls /opt
123
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-kqp77 -- ls /opt
123
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-s6s5c -- ls /opt
123
生命周期验证
- 使用nfs挂载的卷,卷的生命周期不受容器所控制
#
[root@k8s-master01 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dp-cm-7689bc6dd7-964xb 1/1 Running 0 16s 172.18.195.38 k8s-master03 <none> <none>
dp-cm-7689bc6dd7-kqp77 1/1 Running 0 14s 172.25.244.215 k8s-master01 <none> <none>
dp-cm-7689bc6dd7-s6s5c 1/1 Running 0 11s 172.17.125.27 k8s-node01 <none> <none>
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-964xb -- ls /opt
123
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-kqp77 -- ls /opt
123
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-s6s5c -- ls /opt
123
# 删除重新创建
kubectl delete deploy/dp-cm
kubectl create -f dp-cm.yaml
# 其挂载卷的生命周期也是不随pod所控制
[root@k8s-master01 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dp-cm-7689bc6dd7-98fkg 1/1 Running 0 6m14s 172.25.244.216 k8s-master01 <none> <none>
dp-cm-7689bc6dd7-nh7nz 1/1 Running 0 6m14s 172.17.125.28 k8s-node01 <none> <none>
dp-cm-7689bc6dd7-qk6q4 1/1 Running 0 6m14s 172.18.195.39 k8s-master03 <none> <none>
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-98fkg -- cat /opt/123
456
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-nh7nz -- cat /opt/123
456
[root@k8s-master01 pod]# kubectl exec -it dp-cm-7689bc6dd7-qk6q4 -- cat /opt/123
456
持久化存储
PV/PVC
什么是pv和pvc?
PV(Persistent Volume)是持久化存储卷,是对底层的共享存储的一种抽象。它由kubernetes管理员进行创建和配置,与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。
PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC其实是用户向kubernetes系统发出的一种资源需求申请。
为什么要引入pv和pvc?
在Kubernetes中,存储系统有很多种,每种都有其特定的配置和操作方式。如果让每个用户都去直接操作底层存储,会大大增加用户的负担,并且容易造成错误。因此,Kubernetes引入了PV和PVC这两种资源对象,将底层的存储实现细节进行屏蔽,使得用户只需要关心存储需求即可。
引入PV和PVC是为了简化用户对Kubernetes存储资源的管理和使用,提高系统的可用性和可维护性
PV的回收策略
数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)
- Retained:保留,当删除pvc时,pv仍然存在,PV被视为已释放,管理员需要手动回收卷
- Recycled: 如果下层的卷插件支持,回收策略 Recycle 会在卷上执行一些基本的擦除 (rm -rf /thevolume/*)操作,之后允许该卷用于新的 PVC 申领,目前只有nfs和HostPath支持该策略。
- Delete: 如果Volume插件支持,删除pvc的同时也会删除pv,动态卷默认为delete,目前支持delete的插件有AWS、EBS、GCEPD、Azure Disk、Openstack Cinder等。
PV的访问策略
- ReadWriteOnce: 可以被单节点以读写模式挂载,缩写RWO
- ReadOnlyMant: 可以被多个节点以只读模式挂载,缩写ROX
- ReadWriteMany: 可以被多个节点以读写模式挂载,缩写RWX
PV配置例子-NFS/NAS
- 首先节点需要安装nfs,本案例是测试使用、生产环境别用nfs
- 具体nfs搭建可参考上方NFS的配置,这里不再演示
[root@k8s-master01 pod]# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
192.168.255.141:/data/nfs 17G 5.1G 12G 30% /mnt
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs # pv名称
spec:
capacity:
storage: 5Gi # 容量配置
volumeMode: Filesystem # 卷的模式、目前支持Filesystem文件系统和Block块,其中Block类型需要后端存储支持,默认为文件系统
accessModes:
- ReadWriteOnce # 访问模式 单用户读写
persistentVolumeReclaimPolicy: Recycle # 回收策略
storageClassName: nfs-slow # PV的类,名称任意
nfs:
path: /data/nfs # nfs上的共享目录
server: 192.168.255.141 # nfs的ip地址
[root@k8s-master01 pod]# kubectl create -f nfs-pv.yaml
persistentvolume/pv-nfs created
You have new mail in /var/spool/mail/root
[root@k8s-master01 pod]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available nfs-slow 4s
PV的状态
- Available:可用,没有被PVC绑定的空闲资源
- Bound:已绑定,已经被PVC绑定
- Released: 已释放、PVC被删除,但是资源还未被重新使用
- Failed: 失败,自动回收失败
PV配置例子-HostPath
- 就后端实际配置不一致 前面都是一样的
[root@k8s-master01 pod]# cat hostpath-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-hostpath
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: hostpath-slow
hostPath:
path: /data
创建NFS类型的PVC
- pvc要和pod在同一个命名空间
[root@k8s-master01 pod]# cat nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc # pvc的名称 等待pod 挂载时调用
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: nfs-slow # 这里类名要和刚才创建的pv类名一样
[root@k8s-master01 pod]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-hostpath 5Gi RWO Recycle Available hostpath-slow 8m57s
pv-nfs 5Gi RWO Recycle Bound default/nfs-pvc nfs-slow 18m
[root@k8s-master01 pod]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc Bound pv-nfs 5Gi RWO nfs-slow 12s
Pod引用PVC
[root@k8s-master01 pod]# cat dp-cm.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: dp-cm
name: dp-cm
spec:
replicas: 1
selector:
matchLabels:
app: dp-cm
template:
metadata:
labels:
app: dp-cm
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
name: nginx
volumeMounts:
- mountPath: /data # 挂载到容器的路径
name: nfs-volume # 引用的卷名称
volumes:
- name: nfs-volume # volume名称
persistentVolumeClaim:
claimName: nfs-pvc # 指定pvc的名称
# 容器内查看信息和nfs服务器上数据一致
[root@k8s-master01 pod]# kubectl exec -it dp-cm-6f86bf6959-fnqzf -- sh
/ # cat /data/pvc
pvcfiletest
更多推荐
所有评论(0)