第五章:卷-将磁盘挂载到容器

本章内容包括:

  • 创建多容器pod
  • 创建一个可在容器间共享磁盘存储的卷
  • 在pod中使用git仓库
  • 将持久性存储挂载到pod
  • 使用预先配置的持久性存储
  • 动态调配持久存储

在前面说过,pod类似逻辑主机,在逻辑主机中运行的进程共享如CPU、RAM、网络接口等资源,但磁盘是不共享的,pod中的每个容器都有自己独立的文件系统,因为文件系统来自容器镜像。

每个容器都是通过在构建镜像时加入的详细配置文件来启动的。将次与pod中容器重新启动的现象结合起来,很容易就意识到新容器并不会识别前一个容器写入文件系统内的任何内容,即使新启动的容器运行在同一个pod中。

Kubernetes通过定义存储卷来满足想要在重启容器中继续使用存储数据的目录这种需求,它们不像pod这样的顶级资源,而是被定位为pod的一部分,并和pod共享相同的生命周期,这意味着在pod启动时创建卷,在删除pod时销毁卷。因此,在容器重新启动期间,卷的内容将保持不变,在重新启动容器之后,新容器可以识别前一个容器写入卷的所有文件。此外,卷还能被同一个pod中的多个容器共同使用。

1 介绍卷

Kubernetes的卷是pod的一个组成部分,因此卷在pod的规范中定义。它们不是独立的Kubernetes资源,也不能单独创建或删除。pod中所有容器都可以使用卷,但必须先将它挂载在每个需要访问它的容器中。在每个容器中都可以在文件系统的任意位置挂载卷。

1.1 使用卷

假设现在有三个容器的pod,一个容器运行了一个web服务,第二个容器运行了一个代理来创建 HTML文件,第三个容器处理web日志。因为容器之间的磁盘是不共享的,所以第一个容器读取不到第二个容器创建的HTML文件,第三个容器也处理不了第一个容器产生的web日志。

我们可以把两个卷挂载到三个容器中合适的位置,这样三个容器的文件共享,各自的功能也能顺序的发挥作用,由于这两个卷最初都是空的,所以可以使用一张叫emptyDIr的卷,Kubernetes还支持其他类型的卷,这些卷要么是从外部源初始化卷时填充的,要么是在卷内挂载现有目录。这个填充或装入卷的过程是在pod内的容器启动之前执行的。

1.2 卷的类型

当卷被绑定到pod的lifecycle中,只有在pod存在时才会存在,但取决于卷的类型,即使在pod和卷消失之后,卷的文件也能保持原样,并可以挂在到新的卷中。有多种卷类型可供选择。其中一些是通用的,而另一些则相对于当前常用的存储技术有较大差别。

  • emptyDir:用于存储临时数据的简单空目录
  • hostPath:用于将目录从工作节点的文件系统挂载到pod中
  • gitRepo:通过检测出Git仓库的内容来初始化的卷,已在1.11版本中被启用
  • nfs:挂载到pod中的NFS共享卷
  • gcePersistentDisk、awsElasticBlockStore、AzureDisk:用于挂载云服务商提供的特定存储类型
  • cinder、cephfs、iscsi、flocker、glusterfs、quobyte、rbd、flexVolume、vsphere-Volume、photonPersistenDisk、scaleIO:用于挂载其他类型的网络存储
  • config、secret、downwardAPI:用于将Kubernetes部分资源和集群信息公开给pod的特殊类型的卷
  • persistentVolumeClaim:一种使用预置或者动态配置的持久存储类型
    单个卷可以使用不用类型的卷,每个pod都可以装载或不装载卷。

2 通过卷在容器之间共享数据

2.1 emptyDir卷

最简单的卷类型是emptyDir卷,顾名思义,该卷从一个空目录开始,运行在pod内的应用程序可以写入它需要的任何文件。因为卷的生命周期与pod的生命周期相关联,所以当删除pod时,卷的内容就会丢失。

一个emptyDir卷对于在同一个pod中运行的容器之间共享文件特别有用,但也可以被单个容器用于将数据临时写到磁盘,例如在大型数据集上执行排序操作时,没有那么多内存可供使用。数据也可以写入容器的文件系统本身,但容器的文件甚至可能是不可写的,所以写到挂载的卷是一个合适的选择。

apiVersion: v1
kind: Pod
metadata:name: fortune
spec:containers:- image: luksa/fortunename: html-generatorvolumeMounts:    # 名为html的卷挂载到容器/var/htdocs中- name: htmlmountPath: /var/htdocs- image: nginx:alpinename: web-servervolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlreadOnly: trueports:- containerPort: 80protocol: TCPvolumes:    # 定义一个叫html的emptyDir类型的卷- name: htmlemptyDir: {}

此manifest在一个pod中定义了两个容器,当这两个容器分别向/var/htdocs和/usr/share/nginx/html目录写文件时,都是写入卷中,而不是写入容器的顶层。

指定EmptyDir介质

作为卷来使用的emptyDir,是在承载pod工作节点的实际磁盘上创建的,因此其性能取决于节点的磁盘类型。我们可以通过设置参数来设置使用内容作为承载介质。

  volumes:   - name: htmlemptyDir: medium: Memory # 使用内存,不设置默认使用磁盘sizeLimit: "1Gi" # 限制大小,可以用Ei、Pi、Ti、Gi、Mi、Ki等单位

emptyDir卷是最简单的卷类型,但是其他类型的卷都是在它的基础上构建的,在创建空目录后,它们会用数据填充它。emptyDir 卷的数据在 Pod 存在期间是持久的,但当 Pod 被删除时,数据也会被删除。如果 Pod 在同一节点上重启,数据仍然存在;如果 Pod 被重新调度到其他节点,数据将丢失。

2.2 gitRepo卷

gitRepo卷本质上也是一个emptyDir卷,它通过克隆Git仓库并在pod启动时(在创建容器之前)检出特定版本来填充数据,如下图所示:
在这里插入图片描述

注意:在创建gitRepo之后,它并不能和对应的repo保持同步。当向git仓库推送新的提交时,卷中的文件不会被更新。但如果pod被删除后由控制器重新拉起来之后,卷中的数据将包含最新提交。

接下来我们创建一个gitRepo类型的卷并挂在到pod上

apiVersion: v1
kind: Pod
metadata:name: gitrepo-volume-pod
spec:containers:- image: nginx:alpinename: web-servervolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlreadOnly: trueports:- containerPort: 80protocol: TCPvolumes:- name: htmlgitRepo:repository: https://github.com/luksa/kubia-website-example.gitrevision: master  # 指出要克隆的Git 分支、标签或提交哈希,默认为masterdirectory: .  # 克隆的容器目录路径,默认为.

2.3 hostPath卷

大多数的pod都应该忽略它们的主机节点,因此它们不该访问节点文件系统上的任何文件。但是某些系统级别的pod(DaemonSet管理)需要读取节点的文件或使用节点文件系统来访问节点设备。

hostPath卷指向节点文件系统上的特定文件或目录。在同一个节点上运行并在其hostPath卷中使用相同路径的pod可以看到相同的文件。hostPath是一种持久性存储,因为前面介绍的emptyDir卷的内容都会在pod被删除时被删除。

如果考虑使用hostPath作为存储数据库数据的目录,请慎重考虑,因为hostPath卷存储的数据与节点高度绑定,这会使pod对预定规划的节点很敏感。

---
# 此清单将主机上的 /data/foo 挂载为 hostpath-example-linux Pod 中运行的单个容器内的 /foo
#
# 容器中的挂载是只读的
apiVersion: v1
kind: Pod
metadata:name: hostpath-example-linux
spec:os: { name: linux }nodeSelector:kubernetes.io/os: linuxcontainers:- name: example-containerimage: registry.k8s.io/test-webservervolumeMounts:- mountPath: /fooname: example-volumereadOnly: truevolumes:- name: example-volume# 挂载 /data/foo,但仅当该目录已经存在时hostPath:path: /data/foo # 主机上的目录位置type: Directory # 此字段可选

2.4 持久化存储

如果集群是运行在自有的一组服务器上,那么就有大量其他可移植的选项用于在卷内挂载外部存储。例如挂载一个NFS共享,只需指定NFS服务器和共享路径即可

apiVersion: v1
kind: Pod
metadata:name: mongodb-nfs
spec:volumes:- name: mongodb-datanfs:   # 指定服务器地址和共享路径server: 1.2.3.4path: /some/pathcontainers:- image: mongoname: mongodbvolumeMounts:- name: mongodb-datamountPath: /data/dbports:- containerPort: 27017protocol: TCP

在pod中通过卷来隐藏真实的底层基础设施,这正是Kubernetes存在的意义。但是将这种涉及基础设施类型的信息塞到一个pod设置中,意味着pod设置与特定的Kubernetes集群有很大的耦合度。这就不能在另一个pod中使用相同的配置了。所以使用这样的卷并不是在pod中附加持久化存储的最佳实践。

3 从底层存储技术解耦pod

到目前为止介绍的所有持久卷类型都要求pod的开发人员了解集群中可用的真实网络存储的基础结构。例如,要创建支持NFS协议的卷,开发人员必须知道NFS节点所在的实际服务器,这违背了Kubernetes的基本理念,这个理念指在向应用程序及其开发人员隐藏真实的基础设施,使他们不必担心基础设施的具体状态,并使应用程序可在大量云服务商和数据企业之间进行功能迁移。

当开发人员需要一定数量的持久化存储来进行应用时,可以向Kubernetes请求,就像在创建pod时可以请求CPU、内存和其他资源一样。系统管理员可以对集群进行配置让其可以为应用程序提供所需的服务。

3.1 持久卷和持久卷申领

Kubernetes集群中为了使应用能够正常请求存储资源,同时避免处理基础设施细节,引入了两个新的资源,分别是持久卷和持久卷申领。

在pod中使用PersistentVolume(持久卷,简称PV)要比使用常规的pod卷复杂一些。
在这里插入图片描述

研发人员无需向他们的pod中添加特定类型的卷,而是由集群管理员设置底层存储,然后通过Kubernetes API服务器创建持久卷并注册。在创建持久卷时,管理员可以指定其大小和所支持的访问模式。

当集群用户需要在其pod中使用持久化存储时,他们首先要创建持久卷申领(PersistentVolumeClaim,简称PVC)清单,指定所需要的最低容量要求和访问模式,然后用户将持久卷申领清单提交给Kubernetes API服务器,Kubernetes将找到可匹配的持久卷并将其绑定到持久卷申领。

持久卷申领可以当做pod中的一个卷来使用,其他用户不能使用相同的持久卷,除非先通过删除持久卷申领绑定来释放。

3.2 创建持久卷

apiVersion: v1
kind: PersistentVolume
metadata:name: mongodb-pv
spec:capacity:  # 定义PV的大小storage: 1GiaccessModes:   # 访问模式- ReadWriteOnce # 单个客户端挂载为读写模式- ReadOnlyMany  # 多个客户端挂载为只读模式persistentVolumeReclaimPolicy: Retain  # 当申领被释放后,PV将保留hostPath:       # PV使用的后端存储类型path: /tmp/mongodb  

在这里我们创建了一个1G大小后端使用hostPath类型的PV。在创建持久卷时,管理员需要告诉Kubernetes其对应的容量需求,以及它是否可以由单个节点或多个节点同时读取或写入,还需要告诉Kubernetes如何处理PV(当持久卷申领绑定被删除时)。最后还要指定持久卷实际使用的存储类型、位置和其他属性。

# 这里可以看到已经绑定好了default/mongodb-pvc,且状态已经是Bound
# 这里笔者是pv、pvc都创建好后查看的
[root@master ~]# kubectl get pv
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
mongodb-pv   1Gi        RWO,ROX        Retain           Bound    default/mongodb-pvc                           9s

注意:持久卷不属于任何命名空间,它跟节点一样时集群层面的资源。

3.3 创建持久卷申领

假设现在需要部署一个需要持久化存储的pod,将要用到之前创建的持久卷,但是不能直接在pod中使用,需要创建一个持久卷申领。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mongodb-pvc # 绑定到pod时会使用
spec:resources:   requests:    # 申请1G的存储空间storage: 1GiaccessModes:- ReadWriteOnce  # 允许单个客户端读写storageClassName: "" 

当创建好申领后,Kubernetes就会找到适合的持久卷并将其绑定到申领,持久卷的容量必须足够大以满足申领的需求,并且卷的访问模式必须包含申领中指定的访问模式。

[root@master ~]# kubectl get pvc
NAME          STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mongodb-pvc   Bound    mongodb-pv   1Gi        RWO,ROX                       109s

RWO/ROX/RWX涉及可以同时使用卷的工作节点的数量而并非pod的数量。

3.4 使用持久卷申领

持久卷现在已经可以使用了,除非先释放掉卷,否则没有人可以申领相同的卷。要在pod中使用持久卷,需要在pod的卷中引用持久卷申领名称

apiVersion: v1
kind: Pod
metadata:name: mongodb 
spec:containers:- image: mongoname: mongodbvolumeMounts:- name: mongodb-datamountPath: /data/dbports:- containerPort: 27017protocol: TCPvolumes:- name: mongodb-datapersistentVolumeClaim:  claimName: mongodb-pvc   # 指定持久卷申领的名称

3.4 回收持久卷

当我们把pod和相关的PVC删除会怎么样呢?能重新创建PVC绑定到PV嘛?答案是不能。

[root@master ~]# kubectl get pv
NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                 STORAGECLASS   REASON   AGE
mongodb-pv   1Gi        RWO,ROX        Retain           Released   default/mongodb-pvc                           9m27s

可以看到此时PV的状态已经变成了Released,不能够被新的PVC绑定。这是因为我们之前创建PV时指定了persistentVolumeReclaimPolicy: Retain,这个参数设置为Retain,PV将在PVC删除之后不清除数据,但也变成不可绑定的状态,此状态被称为手动回收持久卷,因为只有手动删除PV之后才能重新绑定PVC。

也可以将PV这个参数设置为RecycleDelete。第一种删除卷的内容并使卷可用于再次申领,通过这种方式,PV可以被不同的持久卷申领和pod反复使用。Delet会删除底层存储。这两种被称为自动回收持久卷

注意:可以在现有的持久卷上修改回收策略。

3.6 持久卷的动态配置

使用持久卷和持久卷申领可以很轻松的获得持久化资源,无需研发人员处理下面实际使用的存储技术,但仍然需要一个集群管理员来支持实际的存储。幸运的是,Kubernetes还可以通过动态配置持久卷来自动执行任务。

集群管理员可以创建一个持久卷配置,并定义一个或多个StorageClass对象,从而让用户选择他们想要的持久卷类型而不仅仅只是创建持久卷。用户可以在其持久卷申领中引用StorageClass,而配置程序在配置持久存储时将采用这一点。

注意:与持久卷类似,StorageClass不是命名空间资源

与管理员预先提供一组持久卷不同的是,它们需要定义一个或多个StorageClass,并允许系统在每次通过持久卷申领请求时创建一个新的持久卷。

3.6.1 创建StorageClass

在用户创建持久卷申领之前,管理员需要创建一个或多个StorageClass资源,然后才能创建新的持久卷。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: fast
provisioner: k8s.io/minikube-hostpath # 用于配置持久卷的卷插件
parameters: # 传递参数type: pd-ssd 

StorageClass资源指定当持久卷申领请求此StorageClass时应使用哪个配置程序来提供持久卷。StorageClass定义中定义的参数传递给置备程序,并具体掉每个供应器插件。

3.6.2 持久卷申领使用StorageClass

创建StorageClass资源后,用户可以在其持久卷申领中按名称引用存储类。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mongodb-pvc 
spec:storageClassName: fast  # 请求自定义存储类resources:requests:storage: 100MiaccessModes:- ReadWriteOnce

除了指定大小和访问模式,持久卷申领现在还会指定要使用的存储类别。在创建申领时,持久卷由fast StorageClass资源中引用的provisioner创建。

StorageClass的好处在于,申领时通过名称引用它们的。因此,只要StorageClass名称相同,PVC定义便可跨不同集群移植。如果想将PVC绑定到手动创建的PV中,请把PVC中的storageClass: ""设置为空字符。

有的卷插件会在集群中创建一个默认的StorageClass,可以在pvc的申领中不指定明确的StorageClass的来使用。也可以手动指定集群中默认的StorageClass。

kubectl patch storageclass <storage-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3246730.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

一分钟了解什么是1U,2U服务器?

一、什么是1U&#xff0c;2U服务器&#xff1f; 什么是1U服务器呢&#xff1f;所谓的1U服务器就是一种高可用高密度的低成本服务器平台&#xff0c;U是服务器机箱的高度 1U等于4.45厘米 &#xff0c;那3U就是3x4.5CM了。 u(unit的缩略语)是一种表示组合式机架外部尺寸的单位&a…

【时时三省】tessy 集成测试:小白入门指导手册

目录 1,创建集成测试模块且分析源文件 2,设置测试环境 3,TIE界面设置相关函数 4,SCE界面增加用例 5,编辑数据 6,用例所对应的测试函数序列 7,添加 work task 函数 8,为测试场景添加函数 9,为函数赋值 10,编辑时间序列的数值 11,执行用例 12,其他注意事项…

【论文阅读】(StemGNN)多元时间序列预测的谱时间图神经网络

&#xff08;StemGNN&#xff09;Spectral Temporal Graph Neural Network for Multivariate Time-series Forecasting 引用&#xff1a; Cao D , Wang Y , Duan J ,et al.Spectral Temporal Graph Neural Network for Multivariate Time-series Forecasting[J]. 2021.DOI:10.…

DockerHub无法拉取镜像怎么办

快速构建企业级AIGC项目 LangChat是Java生态下企业级AIGC项目解决方案&#xff0c;在RBAC权限体系的基础上&#xff0c;集成AIGC大模型功能&#xff0c;帮助企业快速定制知识库、企业机器人。 网站文档&#xff1a;Index – LangChat 后台地址&#xff1a;LangChain Chat 前台…

【深度学习入门篇 ⑧】关于卷积神经网络

【&#x1f34a;易编橙&#xff1a;一个帮助编程小伙伴少走弯路的终身成长社群&#x1f34a;】 大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; ) &#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…

昇思25天学习打卡营第13天|CycleGAN 图像风格迁移互换全流程解析

目录 数据集下载和加载 可视化 构建生成器 构建判别器 优化器和损失函数 前向计算 计算梯度和反向传播 模型训练 模型推理 数据集下载和加载 使用 download 接口下载数据集&#xff0c;并将下载后的数据集自动解压到当前目录下。数据下载之前需要使用 pip install dow…

el-table表格操作列错行处理

解决方法&#xff1a; <style>::v-deep .el-table th.el-table__cell > .cell {white-space: nowrap !important;} </style>

Template execution failed: ReferenceError: name is not defined

问题 我们使用了html-webpack-plugin&#xff08;webpack&#xff09;进行编译html&#xff0c;导致的错误。 排查结果 连接地址 html-webpack-plugin版本低(2.30.1)&#xff0c;html模板里面不能有符号&#xff0c;注释都不行 // var reg new RegExp((^|&)${name}([^&…

测试——基础篇

内容纲要: 软件测试的生命周期 如何描述一个bug 如何定义bug的级别 bug的生命周期 如何开始第一次测试 测试的执行和bug管理 产生争执怎么办 1. 软件测试的生命周期 需求分析→测试计划→ 测试设计、测试开发→ 测试执行→ 测试评估 需求分析:需求是否正确,是否可行测试计划:…

Qt基础 | Qt全局定义 | qglobal头文件中的数据类型、函数、宏定义

文章目录 一、数据类型定义二、函数三、宏定义 QtGlobal头文件包含了 Qt 类库的一些全局定义 &#xff0c;包括基本数据类型、函数和宏&#xff0c;一般的Qt类的头文件都会包含该文件。 详细内容可参考&#xff1a;https://doc.qt.io/qt-5/qtglobal.html 一、数据类型定义 为了…

《Python机器学习项目实战》书籍介绍

文章目录 书籍介绍主要内容书籍目录 书籍介绍 《Python机器学习项目实战》带领大家在构建实际项目的过程中&#xff0c;掌握关键的机器学习概念&#xff01;使用机器学习&#xff0c;我们可完成客户行为分析、价格趋势预测、风险评估等任务。要想掌握机器学习&#xff0c;需要…

2024年大数据高频面试题(中篇)

文章目录 Kafka为什么要用消息队列为什么选择了kafkakafka的组件与作用(架构)kafka为什么要分区Kafka生产者分区策略kafka的数据可靠性怎么保证ack应答机制(可问:造成数据重复和丢失的相关问题)副本数据同步策略ISRkafka的副本机制kafka的消费分区分配策略Range分区分配策略…

网络准入控制设备是什么?有哪些?网络准入设备臻品优选

小李&#xff1a;“小张&#xff0c;最近公司网络频繁遭遇外部攻击&#xff0c;我们得加强一下网络安全了。” 小张&#xff1a;“是啊&#xff0c;我听说实施网络准入控制是个不错的选择。但具体什么是网络准入控制设备&#xff1f;我们有哪些选择呢&#xff1f;” 小李微笑…

数据结构历年考研真题对应知识点(哈夫曼树和哈夫曼编码)

目录 5.5.1哈夫曼树和哈夫曼编码 1.哈夫曼树的定义 2.哈夫曼树的构造 【分析哈夫曼树的路径上权值序列的合法性&#xff08;2010&#xff09;】 【哈夫曼树的性质&#xff08;2010、2019&#xff09;】 3.哈夫曼编码 【根据哈夫曼编码对编码序列进行译码&#xff08;201…

乘积量化pq:将高维向量压缩 97%

向量相似性搜索在处理大规模数据集时&#xff0c;往往面临着内存消耗的挑战。例如&#xff0c;即使是一个包含100万个密集向量的小数据集&#xff0c;其索引也可能需要数GB的内存。随着数据集规模的增长&#xff0c;尤其是高维数据&#xff0c;内存使用量会迅速增加&#xff0c…

达梦 ./disql SYSDBA/SYSDBA报错[-70028]:创建SOCKET连接失败. 解决方法

原因 达梦命令./disql SYSDBA/SYSDBA默认访问端口5236&#xff0c;如果初始化实例的时候修改了端口&#xff0c;需要指定端口访问 解决 ./disql SYSDBA/SYSDBA192.168.10.123:5237

数据结构(5.2_1)——二叉树的基本定义和术语

二叉树的基本概念 二叉树是n(n>0)个结点的有限集合: 或者为空二叉树&#xff0c;即n0&#xff1b;或者由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一颗二叉树。 特点:每个结点至多只有两颗字数&#xff1b;左子树不能颠倒(二叉树…

09 深度推荐模型演化中的“平衡与不平衡“规律

你好&#xff0c;我是大壮。08 讲我们介绍了深度推荐算法中的范式方法&#xff0c;并简单讲解了组合范式推荐方法&#xff0c;其中还提到了多层感知器&#xff08;MLP&#xff09;。因此&#xff0c;这一讲我们就以 MLP 组件为基础&#xff0c;讲解深度学习范式的其他组合推荐方…

pico+unity3d手部动画

在 Unity 开发中&#xff0c;输入系统的选择和运用对于实现丰富的交互体验至关重要。本文将深入探讨 Unity 中的 Input System 和 XR Input Subsystem 这两种不同的输入系统&#xff0c;并详细介绍它们在控制手部动画方面的应用。 一、Input System 和 XR Input Subsystem 的区…