全国 【切换城市】欢迎您来到装修百科!
关注我们
我要装修

动手动脑学Kubernetes系列教程之Volume介绍(kubernetes volume详解)

发布:2024-09-12 浏览:20

核心提示:在之前的文章中, 介绍了搭建好的#minikube#环境,如果你现在还没有一个可用的minikube环境, 那么可以去该篇文章中直接下载;在之前的文章中, 先后介绍了如何从源代码开始构建一个Node.js应用和Spring Boot 应用, 并且部署到Kubernetes 中(这个Kubernetes 环境主要是之前建好的#minikube#) , 现在我们开始进一步深入的学习Kubernetes, 用一个个可以实际运行的例子的形式, 深入理解#Kubernetes#的概念以及原理.在#动手动脑学Kube

在之前的文章中, 介绍了搭建好的#minikube#环境,如果你现在还没有一个可用的minikube环境, 那么可以去该篇文章中直接下载;在之前的文章中, 先后介绍了如何从源代码开始构建一个Node.js应用和Spring Boot 应用, 并且部署到Kubernetes 中(这个Kubernetes 环境主要是之前建好的#minikube#) , 现在我们开始进一步深入的学习Kubernetes, 用一个个可以实际运行的例子的形式, 深入理解#Kubernetes#的概念以及原理.在#动手动脑学Kubernetes#系列教程中, 我们展示了Kubernetes的基本用法在第一篇里, 学习了Pod的基本知识;在第二篇里, 学习了标签(Label)的语法, 使用Label来选择和过滤Kubernetes 资源;在第三篇里, 介绍了Deployment的使用, 介绍了Deployment与Replica Set、Pod的关系, 并展示了如何进行应用的版本回滚;在第四篇里, 介绍了Service的使用,使用Replication Controller创建Pod, 并创建Service, 展示了从Service 调用应用的方法; 随后又展示了扩展 Pod的数量为2, 比较了Service和之前的不同, 基本展示了Cluster IP 类型的Service的基本用法.在第五篇里, 介绍了Namespace的使用, 除了创建,列出系统的Namespace之外, 还说明Namespace 如何对资源进行隔离, 建立Development, Staging, Production等环境的方法.在第六篇里, 介绍了Service Discovery的使用, 讲解了如何检查Kube-dns, 如何检查和使用Service的FQDN等知识, 对Kubernetes的DNS 系统有整体的理解.在第七篇里, 介绍了Port Forwards, 端口转发的用法, 在本地程序开发的时候, 使用端口转发可以简化本地测试的工作, 同时介绍了其他几种本地端口转发的用法.在第八篇里, 介绍了Probe, 也就是探针的用法, 也就是用来做Health Check, 并介绍了存活探针和就绪探针的基本使用方法, 并在最后介绍了Pod中的三种探针的定义, 以及使用场景.在第九篇里, 介绍了环境变量的用法, 使用环境变量可以把Pod 定义的信息传递给运行其中的镜像.在这一篇里, 我们将学习Volume, 卷的基本知识, 继续愉快的学习吧!Volume, 卷, 在Kubernetes中, 本质上就是是一个在Pod中运行的, 而且是所有容器都可访问的目录结构。
与容器本地文件系统相反,Volume中的数据在容器重新启动后会被继续保留。
根据支撑卷内容的介质的不同,卷的类型分为很多种:本地节点类型,例如emptyDir或hostPath文件共享类型,例如nfs云提供商特定的类型,例如awsElasticBlockStore,azureDisk或gcePersistentDisk分布式文件系统类型,例如glusterfs或cephfs特殊类型,例如secret,gitRepo卷的一种特殊类型是PersistentVolume,我们将在其他地方介绍。
从镜像开始首先, 我们从创建一个Pod 开始.Github地址: https://raw.githubusercontent.com/hintcnuie/kbe/main/specs/volumes/pod.yaml文件内容:apiVersion: v1kind: Podmetadata: name: sharevolspec: containers: - name: c1 image: centos:7 command: - "bin/bash" - "-c" - "sleep 10000" volumeMounts: - name: xchange mountPath: "/tmp/xchange" - name: c2 image: centos:7 command: - "bin/bash" - "-c" - "sleep 10000" volumeMounts: - name: xchange mountPath: "/tmp/data" volumes: - name: xchange emptyDir: {}可以看到, 这个Pod 的定义和以往不同, 这里面多了一个Volume部分, 而volume则是定义了一个名字和类型(emptyDir),先来创建一下:$ kubectl apply -f https://raw.githubusercontent.com/hintcnuie/kbe/main/specs/volumes/pod.yamlpod/sharevol created来查看一下这个Pod的详细情况:$ kubectl describe pod sharevolName:         sharevolNamespace:    defaultPriority:     0Node:         localhost.localdomain/10.0.2.15Start Time:   Mon, 15 Mar 2021 03:23:08 +0000Labels:       <none>Annotations:  <none>Status:       RunningIP:           172.17.0.5IPs:  IP:  172.17.0.5Containers:  c1:    Container ID:  docker://9cda5ee9e62a719d6fe4382ed64a75a02d63f9bd862ac2a98e3c9fd0d56aca5d    Image:         centos:7    Image ID:      docker-pullable://centos@sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e    Port:          <none>    Host Port:     <none>    Command:      bin/bash      -c      sleep 10000    State:          Running      Started:      Mon, 15 Mar 2021 03:23:09 +0000    Ready:          True    Restart Count:  0    Environment:    <none>    Mounts:      /tmp/xchange from xchange (rw)      /var/run/secrets/kubernetes.io/serviceaccount from default-token-q77th (ro)  c2:    Container ID:  docker://b360fc0f0351da009e57d019163bdbe49bde5e5fdc33dbe78290c0a168b0147c    Image:         centos:7    Image ID:      docker-pullable://centos@sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e    Port:          <none>    Host Port:     <none>    Command:      bin/bash      -c      sleep 10000    State:          Running      Started:      Mon, 15 Mar 2021 03:23:09 +0000    Ready:          True    Restart Count:  0    Environment:    <none>    Mounts:      /tmp/data from xchange (rw)      /var/run/secrets/kubernetes.io/serviceaccount from default-token-q77th (ro)Conditions:  Type              Status  Initialized       True   Ready             True   ContainersReady   True   PodScheduled      True Volumes:  xchange:    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)    Medium:         SizeLimit:  <unset>  default-token-q77th:    Type:        Secret (a volume populated by a Secret)    SecretName:  default-token-q77th    Optional:    falseQoS Class:       BestEffortNode-Selectors:  <none>Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300sEvents:  Type    Reason     Age   From               Message  ----    ------     ----  ----               -------  Normal  Scheduled  15s   default-scheduler  Successfully assigned default/sharevol to localhost.localdomain  Normal  Pulled     14s   kubelet            Container image "centos:7" already present on machine  Normal  Created    14s   kubelet            Created container c1  Normal  Started    14s   kubelet            Started container c1  Normal  Pulled     14s   kubelet            Container image "centos:7" already present on machine  Normal  Created    14s   kubelet            Created container c2  Normal  Started    14s   kubelet            Started container c2可以看到这个Pod 创建了两个容器, 同时还有一个名为xchange的Volume, 可以看出, EmptyDir这种类型的卷, 就是一个伴随着Pod 生命周期的一个临时目录.Volumes:  xchange:    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)    Medium:         SizeLimit:  <unset>  default-token-q77th:    Type:        Secret (a volume populated by a Secret)    SecretName:  default-token-q77th    Optional:    false让我们进入Pod的c1 容器, 看看这个卷长得什么样子,顺便增加点数据:$ kubectl exec -it sharevol -c c1 -- bash然后执行: [root@sharevol /]# mount | grep xchange/dev/mapper/vg01-lv_root on /tmp/xchange type ext4 (rw,relatime,data=ordered)从上面可以看到, 卷已经挂载到/tmp/xchange目录下 因此在/tmp/xchange目录下新建了一个data 文件试试: [root@sharevol /]# echo 'some data' > /tmp/xchange/data[root@sharevol /]# cat /tmp/xchange/datasome data[root@sharevol /]# exitexit下面我们来进入容器c2, 看看c2 里面能不能读到这个卷下面新添加的文件:$ kubectl exec -it sharevol -c c2 -- bash[root@sharevol /]# mount | grep xchange[root@sharevol /]# mount | grep /tmp/data/dev/mapper/vg01-lv_root on /tmp/data type ext4 (rw,relatime,data=ordered)[root@sharevol /]# cat /tmp/data/datasome data注意, 我们在Pod 文件里面看到, c2的卷的定义其实和c1不太一样, c2是挂载在/tmp/data目录下, 而c1是挂载在/tmp.xchange目录下: volumeMounts: - name: xchange mountPath: "/tmp/data"所以在c2 容器里面,查看数据的时候, 需要访问/tmp/data/data文件, 而且我们也能看到/tmp/data/data文件的内容:[root@sharevol /]# cat /tmp/data/datasome data需要注意的是,在每个容器中,您需要确定将卷安装在何处,而对于emptyDir,目前无法指定资源消耗限制。
ok, 操作的部分就到这里吧, 下面我们来看看关于卷的理论知识.Volume的产生容器中的文件在磁盘上是临时存放的,对于容器中运行的一些特殊程序, 这会带来了一些。
首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建。
其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。
Kubernetes 抽象出 Volume 对象来解决这两个问题。
Docker 也有 Volume 的概念,但对它只有少量且松散的管理。
在 Docker 中,Volume 是磁盘上或者另外一个容器内的一个目录。
直到最近,Docker 才支持对基于本地磁盘的 Volume 的生存期进行管理。
虽然 Docker 现在也能提供 Volume 驱动程序,但是目前功能还非常有限(例如,截至 Docker 1.7,每个容器只允许有一个 Volume 驱动程序,并且无法将参数传递给卷)。
另一方面,Kubernetes 卷具有明确的生命周期——与包裹它的 Pod 相同。
因此,卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留。
当然,当一个 Pod 不再存在时,卷也将不再存在。
也许更重要的是,Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。
卷的核心是包含一些数据的目录,Pod 中的容器可以访问该目录。
特定的卷类型可以决定这个目录如何形成的,并能决定它支持何种介质,以及目录中存放什么内容。
使用卷时, Pod 声明中需要提供卷的类型 (.spec.volumes 字段)和卷挂载的位置 (.spec.containers.volumeMounts 字段).容器中的进程能看到由它们的 Docker 镜像和卷组成的文件系统视图。
Docker 镜像 位于文件系统层次结构的根部,并且任何 Volume 都挂载在镜像内的指定路径上。
卷不能挂载到其他卷,也不能与其他卷有硬链接。
Pod 中的每个容器必须独立地指定每个卷的挂载位置。
卷的类型上面讲过, 卷有下面几个类型:本地节点类型,例如emptyDir或hostPath文件共享类型,例如nfs云提供商特定的类型,例如awsElasticBlockStore,azureDisk或gcePersistentDisk分布式文件系统类型,例如glusterfs或cephfs特殊类型,例如secret,gitRepo下面是更详细的列表:Kubernetes 支持下列类型的卷:awsElasticBlockStoreazureDiskazureFilecephfscinderconfigMapcsidownward APIemptyDirfc (fibre channel)flexVolumeflockergcePersistentDiskgitRepo (deprecated)glusterfshostPathiscsilocalnfspersistentVolumeClaimprojectedportworxVolumequobyterbdscaleIOsecretstorageosvsphereVolume我们欢迎大家贡献其他的卷类型支持。
来仔细看看emptyDir的定义.emptyDir介绍当 Pod 指定到某个节点上时,首先创建的是一个 emptyDir 卷,并且只要 Pod 在该节点上运行,卷就一直存在。
就像它的名称表示的那样,卷最初是空的。
尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir 卷中相同的文件。
当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会永久删除。
注意:容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃时 emptyDir 卷中的数据是安全的。
emptyDir 的一些用途:缓存空间,例如基于磁盘的归并排序。
为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
默认情况下, emptyDir 卷存储在支持该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储,这取决于使用的环境。
例如,可以将 emptyDir.medium 字段设置为 "Memory",以告诉 Kubernetes 安装 tmpfs(基于 RAM 的文件系统)。
虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。
tmpfs 在节点重启时会被清除,并且您所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
卷gitRepo ----已经已被弃用警告:gitRepo 卷类型已经被废弃。
如果需要在容器中提供 git 仓库,请将一个 EmptyDir 卷挂载到 InitContainer 中,使用 git 命令完成仓库的克隆操作,然后将 EmptyDir 卷挂载到 Pod 的容器中。
gitRepo 卷是一个卷插件的例子。
该卷类型挂载了一个空目录,并将一个 Git 代码仓库克隆到这个目录中供您使用。
将来,这种卷可能被移动到一个更加解耦的模型中,而不是针对每个应用案例扩展 Kubernetes API。
下面给出一个 gitRepo 卷的示例:apiVersion: v1kind: Podmetadata: name: serverspec: containers: - image: nginx name: nginx volumeMounts: - mountPath: /mypath name: git-volume volumes: - name: git-volume gitRepo: repository: "git@somewhere:me/my-git-repository.git" revision: "22f1d8406d464b0c0874075539c1f2e96c253775"卷hostPath 介绍卷hostPath 能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。
虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
例如,hostPath 的一些用法有:运行一个需要访问 Docker 引擎内部机制的容器;请使用 hostPath 挂载 /var/lib/docker 路径。
在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys。
允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。
除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type。
支持的 type 值如下:取值行为空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 Kubelet 相同的组和所有权。
Directory在给定路径上必须存在的目录。
FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。
File在给定路径上必须存在的文件。
Socket在给定路径上必须存在的 UNIX 套接字。
CharDevice在给定路径上必须存在的字符设备。
BlockDevice在给定路径上必须存在的块设备。
当使用这种类型的卷时要小心,因为:具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由 hostPath 使用的资源。
基础主机上创建的文件或目录只能由 root 用户写入。
您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。
Pod 示例apiVersion: v1kind: Podmetadata: name: test-pdspec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /test-pd name: test-volume volumes: - name: test-volume hostPath: # directory location on host path: /data # this field is optional type: Directory警告:应当注意,FileOrCreate 类型不会负责创建文件的父目录。
如果挂载挂载文件的父目录不存在,pod 启动会失败。
为了确保这种 type 能够工作,可以尝试把文件和它对应的目录分开挂载,如下所示:FileOrCreate pod 示例apiVersion: v1kind: Podmetadata: name: test-webserverspec: containers: - name: test-webserver image: k8s.gcr.io/test-webserver:latest volumeMounts: - mountPath: /var/local/aaa name: mydir - mountPath: /var/local/aaa/1.txt name: myfile volumes: - name: mydir hostPath: # 确保文件所在目录成功创建。
path: /var/local/aaa type: DirectoryOrCreate - name: myfile hostPath: path: /var/local/aaa/1.txt type: FileOrCreate卷local介绍local 卷指的是所挂载的某个本地存储设备,例如磁盘、分区或者目录。
local 卷只能用作静态创建的持久卷。
尚不支持动态配置。
相比 hostPath 卷,local 卷可以以持久和可移植的方式使用,而无需手动将 Pod 调度到节点,因为系统通过查看 PersistentVolume 所属节点的亲和性配置,就能了解卷的节点约束。
然而,local 卷仍然取决于底层节点的可用性,并不是适合所有应用程序。
如果节点变得不健康,那么local 卷也将变得不可访问,并且使用它的 Pod 将不能运行。
使用 local 卷的应用程序必须能够容忍这种可用性的降低,以及因底层磁盘的耐用性特征而带来的潜在的数据丢失风险。
下面是一个使用 local 卷和 nodeAffinity 的持久卷示例:apiVersion: v1kind: PersistentVolumemetadata: name: example-pvspec: capacity: storage: 100Gi # volumeMode field requires BlockVolume Alpha feature gate to be enabled. volumeMode: Filesystem accessModes: - ReadWriteonce persistentVolumeReclaimPolicy: Delete storageClassName: local-storage local: path: /mnt/disks/ssd1 nodeAffinity: required: nodeSelectorTerms: - matchexpressions: - key: kubernetes.io/hostname operator: In values: - example-node使用 local 卷时,需要使用 PersistentVolume 对象的 nodeAffinity 字段。
它使 Kubernetes 调度器能够将使用 local 卷的 Pod 正确地调度到合适的节点。
现在,可以将 PersistentVolume 对象的 volumeMode 字段设置为 “Block”(而不是默认值 “Filesystem”),以将 local 卷作为原始块设备暴露出来。
volumeMode 字段需要启用 Alpha 功能 BlockVolume。
当使用 local 卷时,建议创建一个 StorageClass,将 volumeBindingMode 设置为 WaitForFirstConsumer。
请参考 示例。
延迟卷绑定操作可以确保 Kubernetes 在为 PersistentVolumeClaim 作出绑定决策时,会评估 Pod 可能具有的其他节点约束,例如:如节点资源需求、节点选择器、Pod 亲和性和 Pod 反亲和性。
您可以在 Kubernetes 之外单独运行静态驱动以改进对 local 卷的生命周期管理。
请注意,此驱动不支持动态配置。
有关如何运行外部 local 卷驱动的示例,请参考 local 卷驱动用户指南。
总结本篇介绍了卷的概念, 并举例说明emptyDir卷的使用方法, 在理论部分, 又介绍了卷的使用背景, 以及hostpath 和local 卷的基本概念. Kubernetes 中的卷, 概念上跟Docker 的卷差不多, 但是支持的类型更多, 在实际使用中需要结合实际情况灵活运用.学无止境

  • 收藏

分享给我的朋友们:

上一篇:微软计算器傻傻分不清“音量”和“体积”(微软计算器怎么用) 下一篇:天燃气热水器选购注意什么 天燃气热水器的禁忌是什么

一键免费领取报价清单 专享六大服务礼包

装修全程保障

免费户型设计+免费装修报价

已有312290人领取

关键字: 装修百科 装修咨询 装修预算表

发布招标得免费设计

申请装修立省30%

更多装修专区

点击排行