1.为什么需要存储卷
容器部署过程中一般有以下三种数据:
- 启动时需要的初始数据,可以是配置文件
- 启动过程中产生的临时数据,该临时数据需要多个容器间共享
- 启动过程中产生的持久化数据
2.数据卷概述
- Kubernetes 中的 Volume 提供了在容器中
挂载外部存储的能力
- Pod 需要设置
卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)
两个信息后才可以使用相应的 Volume
官方给出了 k8s 支持的所有卷类型,点击查看:Volumes | Kubernetes
存储分为以下几类:
本地:hostPath,emptyDir
网络:nfs,cephfs,rbd,glusterfs
公有云:awsElasticBlockStore,azureDisk
k8s 本身存储:secret,configMap,downwardAPI
3.临时存储卷:emptyDir
创建一个空卷,挂载到 Pod 中的容器。Pod 删除该卷也会被删除。
应用场景:Pod 中容器之间数据共享
pod 实现:网络共享(infra container),存储共享(emptyDir)
示例程序 emptyDir.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: write
image: centos
command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"]
volumeMounts:
- name: data
mountPath: /data
- name: read
image: centos
command: ["bash","-c","tail -f /data/hello"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
卷挂载是针对容器的,故
volumeMounts
要与container
同级
yaml 应用完成后,k8s 会在宿主机创建一个空目录,路径在 /var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~empty-dir/data/
,所有的文件都会挂载在这个空目录中,下面介绍查找方法:
- 1.查看 pod 在哪个节点上
kubectl get pod -o wide
- 2.去 node1 执行:
docker ps | grep my-pod
-
3.找到 pod-id:
37a7c719-31b6-4a4f-bfa0
-
4.接着去目录下查看执行结果:
cd /var/lib/kubelet/pods/37a7c719-31b6-4a4f-bfa0-acacea1fac22/volumes/kubernetes.io~empty-dir/data
可以发现文件夹下产生了一个 hello 文件.文件内容可以直接 cat 查看或者通过 kubectl 查看:kubectl logs -f my-pod read
4.节点存储卷:hostPath
挂载 Node 文件系统上文件或者目录到 Pod 中的容器。
应用场景:Pod 中容器需要访问宿主机文件
示例:hostPath.yaml
将宿主机 /tmp
目录挂载到 pod 的 /data
目录中
apiVersion: v1
kind: Pod
metadata:
name: my-pod2
spec:
containers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- sleep 36000
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
hostPath:
path: /tmp
type: Directory
挂载的目录为当前节点宿主机目录,不是其他节点的也不是远程存储的目录
5. 网络存储卷:NFS
示例程序 nfs.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
nfs:
server: 192.168.0.6
path: /data/nfs
在 nfs 服务器上新建一个 index.html,内容为 123:
echo 123 > index.html
选择一个 pod,exec 进去看看:
以上说明,nfs 挂载没问题!其他两个 pod 中也会有同样的 index.html
访问 pod 的 ip:
6.持久卷
持久卷对上述配置磁盘(nfs)的角色进行划分,并且抽象出来两个资源:
-
PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理
1.静态
2.动态 -
PersistentVolumeClaim(PVC):让用户不需要关心具体的 Volume 实现细节
解决的痛点:专人做专事,运维只负责提供存储空间,用户不需要关心怎么实现,直接用配置好的存储即可。
pv 与 pvc 一一对应,用户申请一块容量,会匹配一个 pv,该 pv 会与这个 pvc 绑定
示例:
作为开发者,需要关注前两个 yaml,先写部署的镜像信息,再指定数据卷类型(pvc)(左图),然后再指定需要的容量和访问模式(中间图),它们通过 pvc 的名称关联;这两块一般写在同一个 yaml 中(左图和中图);右图一般是运维人员提前准备好的 pv,里面包含了卷的来源,访问模式和大小
6.1 PV 静态供给
原理图:
解释:中间部分为运维人员准备的一些存储池,存储池中有很多的 pv,当开发者在 k8s 中申请一块存储时,执行完 yaml 之后,pvc 会自动查找与其定义的访问模式或者容量相匹配的 pv 并与之绑定,只有绑定了 pv 成功申请了存储之后,pod 才会显示 running 状态,否则一直显示 pending 状态
注意 pv 与 pvc 一一对应并且绑定
总结:
PVC 与 PV:
- 一对一的关系
- PV 可以是多个后端存储
- PV 一般都是 k8s 运维创建(存储池)
示例
my-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: my-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
my-pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
path: /data/nfs
server: 192.168.0.6
效果
补充:
Kubernetes 支持持久卷的存储插件:
https://kubernetes.io/docs/concepts/storage/persistent-volumes/
PV 与 PVC 匹配:
1、访问模式(三种访问方式: ReadWriteOnce(RWO), ReadOnlyMany(ROX), ReadWriteMany(RWX))
2、存储容量(PVC 如果没有找到精确对应的 PV 时,会根据就近 PV 匹配)
6.2 PV 动态供给
当 pvc 去申请容量时,它会根据存储类自动创建 pv,pvc 申请多大空间,pv 就会创建多大空间
- Dynamic Provisioning 机制工作的核心在于 StorageClass 的 API 对象。
- StorageClass 声明存储插件,用于自动创建 PV。
Kubernetes 支持动态供给的存储插件:
https://kubernetes.io/docs/concepts/storage/storage-classes/
由此可见,k8s 并不支持 nfs 的 pv 动态供给,故需要安装插件让其支持,插件地址为:
https://github.com/kubernetes-incubator/external-storage
动态供给-NFS
下载安装存储插件:点击下载
注意:deployment.yml 中的 nfs 地址需要手动更改!!!路径不存在会自动创建。
cd nfs-client
kubectl apply -f .
示例
my-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: my-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
storageClassName: "managed-nfs-storage" # 指定存储类
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于