数据卷与持久数据卷
2401字约8分钟
2024-09-29
为什么需要存储卷
容器部署过程中一般有以下三种数据:
启动时需要的初始数据,例如配置文件
启动过程中产生的临时数据,该临时数据需要多个容器间共享
启动过程中产生的持久化数据,例如MySQL的data目录
数据卷概述
Kubernetes中的Volume提供了在容器中挂载外部存储的能力
Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume
数据卷类型大致分类:
本地(hostPath,emptyDir等)
网络(NFS,Ceph,GlusterFS等)
公有云(AWS EBS等)
K8S资源(configmap,secret等)
支持的数据劵类型:https://kubernetes.io/docs/concepts/storage/volumes/
数据卷:emptyDir
emptyDir卷:是一个临时存储卷,与Pod生命周期绑定一起,如果 Pod删除了卷也会被删除。
应用场景:Pod中容器之间数据共享
示例:Pod内容器之前共享数据
vim emptyDir.yaml
apiVersion: v1
kind: Pod
metadata:
name: emptydir-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: {}
验证查看
kubectl apply -f emptyDir.yaml
kubectl get pod
kubectl exec -it emptydir-pod -c write -- bash #写容器
# ls /data/
kubectl exec -it emptydir-pod -c read -- bash #读容器
# ls /data/
# tail -f /data/hello
#数据目录存放在本地的路径
kubectl get pod -o wide #查看该pod在哪个节点,对应节点查看数据卷目录
#data的存放目录路径
docker ps -l #查看最近创建的容器
/var/lib/kubelet/pods/53d07406-364b-4d85-90b9-e3a6dca15427/volumes/kubernetes.io~empty-dir/data
数据卷:hostPath
hostPath卷:挂载Node文件系统(Pod所在节点)上文件或者目 录到Pod中的容器。
应用场景:Pod中容器需要访问宿主机文件
示例:将宿主机/tmp目录挂载到容器/data目录
vim hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
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
验证查看
kubectl apply -f hostpath.yaml
kubectl get pod -o wide #查看该pod所在节点
kubectl exec -it hostpath-pod -- sh
# ls /data/
在pod所在节点的/tmp目录下创建文件,验证pod中/data目录下能否看见
touch /tmp/xiaozhe.txt
数据卷:NFS
NFS数据卷:提供对NFS挂载支持,可以自动将NFS共享 路径挂载到Pod中
NFS:是一个主流的文件共享服务器。
#安装nfs安装包(每个k8s节点都要安装)
yum install nfs-utils
#创建nfs共享目录
mkdir -p /nfs/kubernetes
#修改nfs配置文件
vim /etc/exports
/nfs/kubernetes *(rw,no_root_squash)
#启动nfs并加入开机自启
systemctl start nfs
systemctl enable nfs
#尝试在别的K8s节点挂载nfs共享目录
mount -t nfs 192.168.0.13:/nfs/kubernetes /mnt/
#在/mnt下新建文件,验证在nfs服务器共享目录下能否看到该文件
touch /mnt/index.html
ls /nfs/kubernetes/
示例:将网站程序通过NFS数据卷共享,让所有Pod使用
vim nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-deployment
spec:
selector:
matchLabels:
app: nfs-nginx
replicas: 3
template:
metadata:
labels:
app: nfs-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.13
path: /nfs/kubernetes
验证查看
kubectl apply -f nfs.yaml
kubectl get pod -o wide
#在nfs服务器上修改nfs的共享目录下index.html里面的内容
echo hello > index.html
curl 10.244.36.74 #访问nfs的任意pod的IP,验证数据是否共享
hello
持久卷概述
PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理 • PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节
PV与PVC使用流程
支持持久卷的存储插件:https://kubernetes.io/docs/concepts/storage/persistent-volumes/
vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
path: /nfs/kubernetes
server: 192.168.0.13
vim pvc-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pvc-deployment
spec:
selector:
matchLabels:
app: pvc-nginx
replicas: 3
template:
metadata:
labels:
app: pvc-nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: my-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
验证访问
kubectl apply -f pv.yaml
kubectl apply -f pvc-deployment.yaml
kubectl get pv,pvc
kubectl get pod -o wide
curl 10.244.169.139 #访问该pod对应的IP
hello
PV 生命周期
ACCESS MODES(访问模式):
AccessModes 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
ReadWriteMany(RWX):读写权限,可以被多个节点挂载
RECLAIM POLICY(回收策略):
目前 PV 支持的策略有三种:
Retain(保留): 保留数据,需要管理员手工清理数据
Recycle(回收):清除 PV 中的数据,效果相当于执行 rm -rf /ifs/kuberneres/*
Delete(删除):与 PV 相连的后端存储同时删除
STATUS(状态):
一个 PV 的生命周期中,可能会处于4中不同的阶段:
Available(可用):表示可用状态,还未被任何 PVC 绑定
Bound(已绑定):表示 PV 已经被 PVC 绑定
Released(已释放):PVC 被删除,但是资源还未被集群重新声明
Failed(失败): 表示该 PV 的自动回收失败
现在PV使用方式称为静态供给,需要K8s运维工程师提前创 建一堆PV,供开发者使用。
在nfs服务器共享目录下创建多个目录,供下面引用不同的pv匹配不同的pv目录
cd /nfs/kubernetes/
mkdir pv{2,3,4}
cd pv2/
echo 222 >index.html
cd ../pv4/
echo 444 >index.html
vim pv234.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv2
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
nfs:
path: /nfs/kubernetes/pv2
server: 192.168.0.13
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv3
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
nfs:
path: /nfs/kubernetes/pv3
server: 192.168.0.13
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv4
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
path: /nfs/kubernetes/pv4
server: 192.168.0.13
vim pvc234-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pvc234-deployment
spec:
selector:
matchLabels:
app: pvc234-nginx
replicas: 3
template:
metadata:
labels:
app: pvc234-nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: pv2
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv2
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 8Gi
验证查看
kubectl apply -f pv234.yaml
kubectl apply -f pvc234-deployment.yaml
kubectl get pv,pvc
从上面pvc234-deployment.yaml 文件配置可以看到,配置文件指定的pvc是pv2,使用最大容量是8Gi,但是pv2的容量可以看到是3Gi,并不满足你要使用的容量,但是为了尽可能的分配给你,所以它将pv4指定了给你使用,pv4的容量是10Gi。
访问
kubectl get pod -o wide #查看该pod对应的IP
curl 10.244.36.76 #可以看到结果是pv4目录下的内容
444
PV 动态供给(StorageClass)
PV静态供给明显的缺点是维护成本太高了!
因此,K8s开始支持PV动态供给,使用StorageClass对象实现。
支持动态供给的存储插件:https://kubernetes.io/docs/concepts/storage/storage-classes/
部署NFS实现自动创建PV插件:
git clone https://github.com/kubernetes-incubator/external-storage
cd nfs-client/deploy
kubectl apply -f rbac.yaml # 授权访问apiserver
kubectl apply -f deployment.yaml # 部署插件,需修改里面NFS服务器地址与共享目录
kubectl apply -f class.yaml # 创建存储类
kubectl get sc # 查看存储类
#修改deployment.yaml 修改里面NFS服务器地址与共享目录
vim sc-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sc-deployment
spec:
selector:
matchLabels:
app: sc-nginx
replicas: 3
template:
metadata:
labels:
app: sc-nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: nfs-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
storageClassName: "managed-nfs-storage" #在创建pvc时指定存储类名称
accessModes:
- ReadWriteMany
resources:
requests:
storage: 12Gi
kubectl apply -f sc-deployment.yaml
kubectl get pv,pvc
从上图可以看出当我们使用kubectl创建一个deployment时,它会请求managed-nfs-storage(nfs存储类),然后managed-nfs-storage调用nfs-client-provisioner插件(pod),帮我们自动创建pv。
访问
#在nfs服务器共享目录下新建文件
cd /nfs/kubernetes/default-nfs-pvc-pvc-2a62f7d8-b356-45d0-87cb-018c10447595
echo sc > index.html
kubectl get pod -o wide
curl 10.244.169.142 #验证数据是否是新建的内容
sc
删除deployment
kubectl delete -f sc-deployment.yaml
在nfs服务器上的共享目录查看
从上面可以看出,nfs的回收策略是deployment删除后端的存储也同时删除,但是当我们把deployment删除之后,数据共享目录还在,并没有删除,它只是帮我们把数据共享目录归档了,如果要删除需要修改class.yaml 配置文件中的archiveOnDelete为false,这时就会帮我们删除后端数据共享目录。
kubectl apply -f class.yaml #更新配置
kubectl delete -f sc-deployment.yaml
kubectl apply -f sc-deployment.yaml #删除再创建
#再次在nfs服务器共享目录下新建文件
cd /nfs/kubernetes/default-nfs-pvc-pvc-d5ca3b6e-7045-4868-8fdf-17063bc19e13
echo 123456 > index.html
kubectl get pod -o wide
curl 10.244.169.142 #验证数据是否是新建的内容
123456
#删除deployment后,验证在nfs服务器上查看是否删除了数据共享目录下的pv目录
kubectl delete -f sc-deployment.yaml
Q:PV与PVC什么关系?
A:一对一
Q:PVC与PV怎么匹配的?
A:访问模式和存储容量
Q:容量匹配策略
A:匹配就近的符合的容量(向上)
Q:存储容量是真的用于限制吗?
A:存储容量取决于后端存储,容量字段主要还是用于匹配
1、使用Ingress暴露应用对外访问
2、创建一个configmap,使用环境变量和数据卷方式引用
3、创建一个pv,再创建一个pod使用该pv
4、配置PV自动供给,再创建一个pod使用该pv
注:自由发挥,实现需求即可