容器云管平台存储架构设计

概述

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模式需要事先创建好PV,然后使用定义好的PVC进行一对一的Bond。但是如果PVC请求成千上万,那么就需要创建成千上万的PV,这样的话维护成本会很高。
因此,Kubernetes提供一种自动创建PV的机制,叫StorageClass,它的作用就是创建PV的模板:

  • 创建 StorageClass 需要定义 PV 的属性,比如存储类型、大小等;
  • 另外创建这种 PV 需要用到的存储插件,比如 Ceph 等。
    有了这两部分信息,Kubernetes 就能够根据用户提交的 PVC,找到对应的 StorageClass,然后 Kubernetes 就会调用 StorageClass 声明的存储插件,自动创建需要的 PV 并进行绑定。


    StorageClass

容器云存储实战

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就不需要了设置映射

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容