概述
k8s中每个容器都有独立的文件系统 ,容器磁盘上的文件的生命周期是短暂的(临时的)。 当容器重启或崩溃时,容器会被以“干净的”状态(镜像初始状态)重新创建,这意味着原有的数据会丢失,文件系统会恢复成镜像的初始状态。因此,为了应对上述这些问题,容器云管平台的存储需要通过pv和pvc来实现:
- PV 全称叫做 Persistent Volume,持久化存储卷:用来描述或者说用来定义一个存储卷的。
- PVC 的全称是 Persistent Volume Claim,是持久化存储的请求:用来描述希望使用什么样的或者说是满足什么条件的PV 存储。
架构实现原理
Kubernetes 中 PVC(Persistent Volume Claim) 和 PV(Persistent Volume) 的使用逻辑:
在 Pod 中定义一个存储卷(该存储卷类型为 PVC),定义的时候直接指定大小,PVC 必须与对应的 PV 建立关系,PVC 会根据配置的定义去 PV 申请,而 PV 是由存储空间创建出来的。PV 和 PVC 是 Kubernetes 抽象出来的一种存储资源。
PV和PVC模式需要事先创建好PV,然后使用定义好的PVC进行一对一的Bond。但是如果PVC请求成千上万,那么就需要创建成千上万的PV,这样的话维护成本会很高。
因此,Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板:
- 创建 StorageClass 需要定义 PV 的属性,比如存储类型、大小等;
-
另外创建这种 PV 需要用到的存储插件,比如 Ceph 等。
有了这两部分信息,Kubernetes 就能够根据用户提交的 PVC,找到对应的 StorageClass,然后 Kubernetes 就会调用 StorageClass 声明的存储插件,自动创建需要的 PV 并进行绑定。
容器云存储实战
emptydir
可以实现pod中的容器之间共享数据,且会随着pod生命周期结束而一起删除:pod-emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
#定义容器挂载内容
volumeMounts:
#使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
- name: html
#挂载至容器中哪个目录
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: html
#在容器内定义挂载存储名称和挂载路径
mountPath: /data/
command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
#定义存储卷
volumes:
#定义存储卷名称
- name: html
#定义存储卷类型
emptyDir: {}
定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。
使用curl命令:
kubectl apply -f pod-emptydir.yaml
kubectl get pods -o wide
curl 10.244.1.125
Fri Nov 29 08:41:27 UTC 2024
hostpath
可以实现持久化存储,使用node节点的目录或者文件挂载到容器,但是存储空间会受到节点单机限制,
node节点故障数据会丢失,pod跨node节点不能共享数据
mkdir -p /data/pod/volume1
echo 'node01.kgc.com' > /data/pod/volume1/index.html
创建 Pod 资源
vim pod-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-hostpath
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
#定义容器挂载内容
volumeMounts:
#使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
- name: html
#挂载至容器中哪个目录
mountPath: /usr/share/nginx/html
#读写挂载方式,默认为读写模式false
readOnly: false
#volumes字段定义了paues容器关联的宿主机或分布式文件系统存储卷
volumes:
#存储卷名称
- name: html
#路径,为宿主机存储路径
hostPath:
#在宿主机上目录的路径
path: /data/pod/volume1
#定义类型,这表示如果宿主机没有此目录则会自动创建
type: DirectoryOrCreate
kubectl apply -f pod-hostpath.yaml
kc get pod -o wide
curl 10.244.1.207
node01.kgc.com
nfs
在stor01节点上安装nfs,并配置nfs服务
mkdir /data/volumes -p
chmod 777 /data/volumes
vim /etc/exports
/data/volumes 192.168.10.0/24(rw,no_root_squash)
systemctl start rpcbind
systemctl start nfs
showmount -e
Export list for stor01:
/data/volumes 192.168.10.0/24
在master节点操作
kind: Pod
vim pod-nfs-vol.yaml
apiVersion: v1
metadata:
name: pod-vol-nfs
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
path: /data/volumes
server: stor01 #主机名或者ip
kubectl apply -f pod-nfs-vol.yaml
kubectl get pods -o wide
在nfs服务器上创建index.html
cd /data/volumes
vim index.html
<h1> nfs stor01</h1>
master节点操作
curl 10.244.2.38
<h1> nfs stor01</h1>
kubectl delete -f pod-nfs-vol.yaml #删除nfs相关pod,再重新创建,可以得到数据的持久化存储
kubectl apply -f pod-nfs-vol.yaml
可以实现持久化存储,使用nfs将存储设备空间挂载到容器,pod可以跨node节点共享数据
当nfs server设置域名时,需要做映射如果设置IP就不需要了设置映射