0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Kubernetes存储体系解析 浅谈Volume概念的由来

454398 来源:云原生技术爱好者社区 作者:strict_nerd 2020-10-15 16:45 次阅读

Volume、PV、PVC、StorageClass由来

先思考一个问题,为什么会引入Volume这样一个概念?

答案很简单,为了实现数据持久化,数据的生命周期不随着容器的消亡而消亡。

”在没有介绍Kubernetes Volume之前,先来回顾下Docker Volume,Docker Volume常用使用方式有两种,

volumes通过这种方式, Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes目录中,由于在创建时没有创建指定数据卷, docker自身会创建默认数据卷;

bind mounts通过这种方式,可以把容器内文件挂载到宿主机任意目录。

既然有了Docker Volume,为啥Kubernetes又搞出了自己的Volume?谷歌的标新立异?

答案是否定的,Kubernetes Volume和Docker Volume概念相似,但是又有不同的地方,Kubernetes Volume与Pod的生命周期相同,但与容器的生命周期不相关。当容器终止或重启时,Volume中的数据也不会丢失。当Pod被删除时,Volume才会被清理。并且数据是否丢失取决于Volume的具体类型,比如emptyDir类型的Volume数据会丢失,而持久化类型的数据则不会丢失。另外Kubernetes提供了将近20种Volume类型。

”现在有了Kubernetes的Volume,我们就可以完全可以在Yaml编排文件中填写上Volume是字段,如下nfs所示:

。。..volumes: - name: static-nfs nfs: server: 12.18.17.240 path: /nfs/data/static

如果你使用ceph作为存储插件,你可以在编排文件中这样定义:

volumes: - name: ceph-vol cephfs: monitors: - 12.18.17.241:6789 - 12.18.17.242:6789 user: admin secretRef: name: ceph-secret readOnly: true

当然只要是Kubernetes已经实现的数据卷类型,你都可以按照如上方式进行直接在Yaml编排文件中定义使用。

看到这里其实已经完成了80%的工作,那么为什么还要设计多此一举的PV呢?这个问题先搁置下,后面会有说明。

在没有说明为什么要设计多此一举的PV PVC之前,先来看看什么是PV PVC?

PV是对持久化存储数据卷的一种描述。

”PV通常是由运维人员提前在集群里面创建等待使用的一种数据卷。如下所示:

apiVersion: v1kind: PersistentVolumemetadata: name: nfsspec: capacity: storage: 10Gi accessModes: - ReadWriteMany nfs: server: 10.244.1.4 path: “/nfs”

PVC描述的是持久化存储的属性,比如大小、读写权限等。

”PVC通常由开发人员创建,如下所示:

apiVersion: v1kind: PersistentVolumeClaimmetadata: name: nfsspec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi

而用户创建的PV PVC必须绑定完成之后才能被利用起来。而PV PVC绑定起来的前提是PV中spec中声明字段大小、权限等必须满足PVC的要求。

成功绑定之后,就可以在Pod Yaml编排文件中定义和使用。如下所示:

apiVersion: v1kind: Podmetadata: labels: role: webspec: containers: - name: web image: nginx ports: - name: web containerPort: 80 volumeMounts: - name: nfs mountPath: “/usr/share/nginx/html” volumes: - name: nfs persistentVolumeClaim: claimName: nfs

看到这里,我们还会认为仅仅是PV对Volume多了一层抽象,并不见得比直接在Yaml中声明Volume高明多少。仔细思考下,我们为什么能够直接在Yaml中直接定义Volume?因为Kubernetes已经帮助我们实现了这种Volume类型,如果我们有自己的存储类型,而Kubernetes中并没有实现,这种是没有办法直接在Yaml编排文件中直接定义Volume的。这个时候PV PVC面向对象的设计就体现出其价值了。这也是在软件开发领域经常碰到的问题,开源软件无法满足要求,但也没有提供出可扩展的接口,没办法,只能重新造轮子。

我们在开发过程中经常碰到这样一个问题,在Pod中声明一个PVC之后,发现Pod不能被调度成功,原因是因为PVC没有绑定到合适的PV,这个时候要求运维人员创建一个PV,紧接着Pod调度成功。刚才上在介绍PV PVC,它们的创建过程都是手动,如果集群中需要成千上万的PV,那么运维人员岂不累死?在实际操作中,这种方式根本行不通。所以Kubernetes给我们提供了一套自动创建PV的机制Dynamic Provisioning.在没有介绍这套自动创建机制之前,先看看Static Provisioning,什么是Static Provisioning?刚才人工创建PV PVC的方式就是Static Provisioning。你可以在PV PVC编排文件中声明StorageClass,如果没有声明,那么默认为“”。具体交互流程如下所示:

静态分配流程

首先由集群管理员事先去规划这个集群中的用户会怎样使用存储,它会先预分配一些存储,也就是预先创建一些 PV;然后用户在提交自己的存储需求(PVC)的时候,Kubernetes内部相关组件会帮助它把PVC PV 做绑定;最后pod使用存储的时候,就可以通过PVC找到相应的PV,它就可以使用了。不足之处也非常清楚,首先繁琐,然后运维人员无法预知开发人员的真实存储需求,比如运维人员创建了多个100Gi的PV存储,但是在实际开发过程中,开发人员只能使用10Gi,这就造成了资源的浪费。当然Kubernetes也为我们提供更好的使用方式,即Dynamic Provisioning它是什么呢?

Dynamic Provisioning包含了创建某种PV所需要的参数信息,类似于一个创建PV的模板。具体交互流程如下所示:

Kubernetes集群中的控制器,会结合PVC和StorageClass的信息动态生成用户所需要的PV,将PVC PV进行绑定后,pod就可以使用PV了。通过 StorageClass配置生成存储所需要的存储模板,再结合用户的需求动态创建PV对象,做到按需分配,在没有增加用户使用难度的同时也解放了集群管理员的运维工作。

动态PV使用Dynamic Provisioning上面提到过,运维人员不再预分配PV,而只是创建一个模板文件,这个模板文件正是StorageClass。下面以NFS为例进行说明,动态PV的整个使用过程。

安装NFS服务

#安装nfsyum -y install nfs-utils rpcbind#开机自启动systemctl enable rpcbind nfs-server#配置nfs 文件echo “/nfs/data *(rw,no_root_squash,sync)” 》/etc/exports

部署置备程序

apiVersion: v1

kind: ServiceAccount

metadata:

name: nfs-provisioner

---

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: nfs-provisioner-runner

rules:

- apiGroups: [“”]

resources: [“persistentvolumes”]

verbs: [“get”, “list”, “watch”, “create”, “delete”]

- apiGroups: [“”]

resources: [“persistentvolumeclaims”]

verbs: [“get”, “list”, “watch”, “update”]

- apiGroups: [“storage.k8s.io”]

resources: [“storageclasses”]

verbs: [“get”, “list”, “watch”]

- apiGroups: [“”]

resources: [“events”]

verbs: [“watch”, “create”, “update”, “patch”]

- apiGroups: [“”]

resources: [“services”, “endpoints”]

verbs: [“get”,“create”,“list”, “watch”,“update”]

- apiGroups: [“extensions”]

resources: [“podsecuritypolicies”]

resourceNames: [“nfs-provisioner”]

verbs: [“use”]

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: run-nfs-provisioner

subjects:

- kind: ServiceAccount

name: nfs-provisioner

namespace: logging

roleRef:

kind: ClusterRole

name: nfs-provisioner-runner

apiGroup: rbac.authorization.k8s.io

---

kind: Deployment

apiVersion: apps/v1

metadata:

name: nfs-client-provisioner

spec:

selector:

matchLabels:

app: nfs-client-provisioner

replicas: 1

strategy:

type: Recreate

template:

metadata:

labels:

app: nfs-client-provisioner

spec:

serviceAccount: nfs-provisioner

containers:

- name: nfs-client-provisioner

image: quay.io/external_storage/nfs-client-provisioner:latest

imagePullPolicy: IfNotPresent

volumeMounts:

- name: nfs-client

mountPath: /persistentvolumes

env:

- name: PROVISIONER_NAME

value: fuseim.pri/ifs

- name: NFS_SERVER

value: 12.18.7.20

- name: NFS_PATH

value: /nfs/data

volumes:

- name: nfs-client

nfs:

server: 12.18.7.20

path: /nfs/data

创建StorageClass模板

apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: nfs-storageprovisioner: fuseim.pri/ifsreclaimPolicy: Retain

这些参数是通过Kubernetes创建存储的时候,需要指定的一些细节参数。对于这些参数,用户是不需要关心的,像这里provisioner指的是使用nfs的置备程序。ReclaimPolicy就是说动态创建出来的PV,当使用方使用结束、Pod 及 PVC被删除后,这块PV应该怎么处理,我们这个地方写的是Retain,意思就是说当使用方pod PVC被删除之后,这个PV会保留。

提交完成模板文件之后,用户只需要在 Pod yaml文件定义 PVC,即可自动创建 PV和 PVC。

apiVersion: apps/v1kind: StatefulSetmetadata: name: esspec: 。。.。。.。。 template: metadata: labels: app: elasticsearch spec: 。。.。。.。。. initContainers: 。。.。。.。。 containers: - name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2 。。.。。.。 volumeClaimTemplates: - metadata: name: data labels: app: elasticsearch spec: accessModes: [ “ReadWriteOnce” ] storageClassName: nfs-storage resources: requests: storage: 50Gi`

Capacity:存储对象的大小;

AccessModes:也是用户需要关心的,就是说使用这个PV的方式。它有三种使用方式:ReadWriteOnce是单node读写访问;ReadOnlyMany是多个node只读访问,常见的一种数据共享方式;ReadWriteMany是多个node上读写访问;

StorageClassName:StorageClassName这个我们刚才说了,动态Provisioning时必须指定的一个字段,就是说我们要指定到底用哪一个模板文件来生成PV。

Kubernetes存储架构

存储架构图

PV Controller: 负责 PV PVC的绑定、生命周期管理,并根据需求进行数据卷的 Provision Delete操作

AD Controller:负责存储设备的 Attach Detach操作,将设备挂载到目标节点

Volume Manager:管理卷的 Mount Unmount操作、卷设备的格式化以及挂载到一些公用目录上的操作

Volume Plugins:它主要是对上面所有挂载功能的实现。 PV Controller、AD Controller、Volume Manager 主要是进行操作的调用,而具体操作则是由 Volume Plugins实现的。根据源码的位置可将 Volume Plugins分为 In-Tree和 Out-of-Tree两类: In-Tree表示源码是放在 Kubernetes内部的(常见的 NFS、cephfs等),和 Kubernetes一起发布、管理与迭代,缺点是迭代速度慢、灵活性差; Out-of-Tree的 Volume Plugins的代码独立于 Kubernetes,它是由存储 提供商实现的,目前主要有 Flexvolume CSI两种实现机制,可以根据存储类型实现不同的存储插件

Scheduler:实现对 Pod的调度能力,会根据一些存储相关的的定义去做存储相关的调度

动态PV交互流程

Kubernetes挂载Volume过程

用户创建一个包含 PVC的 Pod

PV Controller会观察 ApiServer,如果它发现一个 PVC已经创建完毕但仍然是未绑定的状态,它就会试图把一个 PV和 PVC绑定

Provision就是从远端上一个具体的存储介质创建一个 Volume,并且在集群中创建一个 PV对象,然后将此 PV和 PVC进行绑定

Scheduler进行多个维度考量完成后,把 Pod调度到一个合适的 Node

Kubelet不断 watch APIServer是否有 Pod要调度到当前所在节点

Pod调度到某个节点之后,它所定义的 PV还没有被挂载( Attach),此时 AD Controller就会调用 VolumePlugin,把远端的 Volume挂载到目标节点中的设备上( /dev/vdb);当 Volum Manager 发现一个 Pod调度到自己的节点上并且 Volume已经完成了挂载,它就会执行 mount操作,将本地设备(也就是刚才得到的 /dev/vdb)挂载到 Pod在节点上的一个子目录中

启动容器,并将已经挂载到本地的 Volume映射到容器中

总结本文主要扯了如下内容,首先介绍Kubernetes中Volume、PV、PVC、StorageClass由来,然后介绍了StorageClass使用,最后简单介绍了Kubernetes存储架构以及动态存储交互流程。
编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储技术
    +关注

    关注

    5

    文章

    731

    浏览量

    45778
  • 容器
    +关注

    关注

    0

    文章

    494

    浏览量

    22044
  • kubernetes
    +关注

    关注

    0

    文章

    223

    浏览量

    8695
收藏 人收藏

    评论

    相关推荐

    VLAN 概念解析及使用场景

    1. VLAN 概念解析 VLAN(Virtual Local Area Network,虚拟局域网)是一种在交换网络中划分不同广播域的技术。VLAN 的主要目的是将一个物理局域网划分成多个逻辑
    的头像 发表于 11-19 09:33 129次阅读

    TLV320ADC3101设置AGC后调整volume无效是怎么回事?

    各位大大:我tlv320adc3101芯片设置成功,pga和volume都能单独操作寄存器使经dac的音量增大或减小,就是本底噪音比较大,现设置agc,双声道设置一样
    发表于 10-25 08:24

    ZCAN PRO解析的DBC Singal 起始位与XNET解析的起始位不同;解析的信号不符合大端逻辑

    上图中的DBC文件使用记事本打开,Data_Field信号,起始位为23,长度为48,大端方式存储;(按照这个方式存储,明显已经溢出) 上图为该信号在ZCANPRO软件中打开,解析的起始位为23
    发表于 10-18 13:53

    tas5805m调整volume或EQ之后没有效果是什么原因?

    我使用tas5805m,目前有声音出来,但是调整volume或EQ之后没有效果。可能是什么原因?之前调整过BTL/PBTL是有效的。从寄存器看是0x66设为0x87了,但是设为0x86也是没有效果。就是无论我怎么改变volume的值都没有效果。
    发表于 10-15 07:44

    亮亮视野AR赋能标识解析体系,开启智能制造新篇章

    近日,亮亮视野承建的工业互联网标识解析二级节点AR应用继续深化,二期项目升级签约落地。AR(增强现实)技术与工业互联网标识解析体系的结合如同两把钥匙共同解锁了智能制造新世界的大门。
    的头像 发表于 09-13 11:47 482次阅读

    闪测仪的精度概念解析

    上期,小优博士讲述了和白光干涉仪相关的精度概念:上期回顾BREAKAWAY与白光干涉仪相关的精度概念都有哪些|科普篇优可测今天,小优博士为大家继续带来《和一键影像测量仪相关的精度概念》一、在单视野
    的头像 发表于 08-30 13:01 512次阅读
    闪测仪的精度<b class='flag-5'>概念</b><b class='flag-5'>解析</b>

    使用Velero备份Kubernetes集群

    Velero 是 heptio 团队(被 VMWare 收购)开源的 Kubernetes 集群备份、迁移工具。
    的头像 发表于 08-05 15:43 323次阅读
    使用Velero备份<b class='flag-5'>Kubernetes</b>集群

    如何使用Kubeadm命令在PetaExpress Ubuntu系统上安装Kubernetes集群

    Kubernetes,通常缩写为K8s,是一个开源的容器编排平台,旨在自动化容器化应用的部署、扩展和管理。有了Kubernetes,您可以轻松地部署、更新和扩展应用,而无需担心底层基础设施。
    的头像 发表于 07-15 13:31 820次阅读
    如何使用Kubeadm命令在PetaExpress Ubuntu系统上安装<b class='flag-5'>Kubernetes</b>集群

    虚拟存储器的概念和特征

    用户提供一个比物理贮存容量大得多、可寻址的“主存储器”,从而极大地提高了计算机系统的存储能力。本文将详细介绍虚拟存储器的概念、原理、特征及其在计算机系统中的应用。
    的头像 发表于 05-24 17:23 1514次阅读

    工业互联网标识解析体系&quot;贯通&quot;计划公布

    据了解,这份文件是首个关于工业互联网标识解析体系的明确指导方针。工业互联网作为第四次工业革命的支柱,也是连接数字经济与实体经济的桥梁,被视为新型工业化的重大基础设施。
    的头像 发表于 02-02 10:05 533次阅读

    Kubernetes Gateway API攻略教程

    Kubernetes Gateway API 刚刚 GA,旨在改进将集群服务暴露给外部的过程。这其中包括一套更标准、更强大的 API资源,用于管理已暴露的服务。在这篇文章中,我将介绍 Gateway
    的头像 发表于 01-12 11:32 850次阅读
    <b class='flag-5'>Kubernetes</b> Gateway API攻略教程

    使用Jenkins和单个模板部署多个Kubernetes组件

    在持续集成和部署中,我们通常需要部署多个实例或组件到Kubernetes集群中。通过Jenkins的管道脚本,我们可以自动化这个过程。在本文中,我将演示如何使用Jenkins Pipeline及单个
    的头像 发表于 01-02 11:40 702次阅读
    使用Jenkins和单个模板部署多个<b class='flag-5'>Kubernetes</b>组件

    Kubernetes RBAC:掌握权限管理的精髓

    Kubernetes RBAC(Role-Based Access Control)是 Kubernetes 中一项关键的安全功能,它通过细粒度的权限控制机制,确保集群资源仅被授权的用户或服务账号访问。
    的头像 发表于 12-25 09:43 449次阅读

    Kubernetes开发指南之深入理解CRD

    CRD本身是Kubernetes内置的资源类型,全称是CustomResourceDefinition,可以通过命令查看,kubectl get查看集群内定义的CRD资源。
    的头像 发表于 12-13 18:19 828次阅读
    <b class='flag-5'>Kubernetes</b>开发指南之深入理解CRD

    浅谈滤波器

    浅谈滤波器
    的头像 发表于 11-29 16:20 800次阅读
    <b class='flag-5'>浅谈</b>滤波器