k8s使用volume将ConfigMap作为文件或目录直接挂载_Kubernetes in Action 06. 卷:将磁盘挂载到容器...

简介 P161

pod 中的每个容器都有自己独立的文件系统,因为文件系统来自容器镜像。 P161

Kubernetes 中的卷是 pod 的一部分,并和 pod 共享相同的生命周期。这意味着 pod 启动时创建卷,并在删除 pod 时销毁卷。 P162

介绍卷 P162

pod 中的所有容器都可以使用卷,但必须先将它挂载在每个需要访问它的容器中。在每个容器中,都可以在其文件系统的任意位置挂载卷。 P162

卷的应用示例 P162

一个有三个功能分明的容器而没有挂载卷的 pod 基本上什么也做不了,因为各自容器内的程序都读写的是容器自身的文件系统,没有共享任何内容。

d313e460dd838eb095bd8b2a4267b048.png

图 6.1 同一个 pod 的三个容器没有共享存储

如果将两个卷添加到 pod ,并在三个容器的适当路径上挂载它们,那么它们就可以对相同的文件进行操作,这样三个容器将可以一起工作,并发挥作用。

6b4a41086b09ee2cb830d580948e2adf.png

图 6.2 三个容器共享挂载在不同安装路径的两个卷上

介绍可用的卷类型 P164

卷被绑定到 pod 的生命周期中,只有在 pod 存在时才会存在,但取决于卷的类型,即使在 pod 和卷消失之后,卷的文件也可能保持原样,并可以挂载到新的卷中。 P164

以下是一些可用卷类型列表: P164

•emptyDir: 用于存储临时数据的简单空目录•hostPath: 用于将目录从工作节点的文件系统挂载到 pod 中•gitRepo: 通过检出 Git 仓库的内容来初始化的卷•nfs: 挂载到 pod 中到 NFS 共享卷•gcePersistentDisk(Google 高效能型存储磁盘卷), awsElasticBlockStore(AmazonWeb 服务弹性块存储卷) , azureDisk(Microsoft Azure 磁盘卷): 用于挂载云服务厂商提供到特定存储类型•cinder, cephfs, iscsi, flocker, glusterfs, quobyte, rbd, flexVolume, vsphere-Volume, photonPersistentDisk, scaleIO: 用于挂载其他类型的网络存储•configMap, secret, downwardAPI: 用于将 Kubernetes 部分资源和集群信息公开给 pod 的特殊类型的卷•persistentVolumeClaim: 一种使用预置或者动态配置的持久存储类型

单个容器可以同时使用不同类型的多个卷,每个容器都可以装载或不装载卷。 P165

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

使用 emptyDir 卷 P165

emptyDir 卷从一个空目录开始,运行在 pod 内的应用程序可以写入它需要的任何文件。它对于在同一个 pod 中运行的容器之间共享文件特别有用。容器的文件系统可能是不可写的,所以写到挂载的卷可能是唯一的选择。 P165

在 pod 中使用 emptyDir 卷 P166

我们将使用 Nginx 作为 Web 服务器并使用 fortune 命令来生成 HTML 内容, fortune 命令每次运行时都会输出一个随机名言,可以创建一个脚本每 10 秒调用一次执行,并将其输出存储在 index.html 中。 P166

我们可以使用如下 fortuneloop.sh 脚本和 Dockerfile 构建一个 fortune 容器镜像。 P166

#!/bin/bashtrap "exit" SIGINTmkdir /var/htdocswhile :do  echo $(date) Writing fortune to /var/htdocs/index.html  /usr/games/fortune > /var/htdocs/index.html  sleep 10done
FROM ubuntu:latest# 安装 fortuneRUN apt-get update && apt-get install -y fortune# 工作目录为 fortuneWORKDIR /fortune# 将 fortuneloop.sh 添加到工作目录下ADD fortuneloop.sh fortuneloop.sh# 运行该脚本ENTRYPOINT /fortune/fortuneloop.sh

创建 pod P167

使用如下 fortune-pod.yaml 描述文件创建一个包含两个共用同一个卷的容器的 pod 。 P167

# 遵循 v1 版本的 Kubernetes APIapiVersion: v1# 资源类型为 Podkind: Podmetadata:  # Pod 的名称  name: fortunespec:  # 该 pod 包含的容器列表  containers:    # 第一个容器由以下镜像创建    - image: idealism/fortune      # 容器名      name: html-generator      # 该容器挂载列表      volumeMounts:        # 将名为 html 的卷挂载到容器的 /var/htdocs        - name: html          mountPath: /var/htdocs    # 第二个容器由以下镜像创建    - image: nginx:alpine      # 容器名      name: web-server      # 该容器挂载列表      volumeMounts:        # 将名为 html 的卷挂载到容器的 /usr/share/nginx/html        - name: html          mountPath: /usr/share/nginx/html          # 该容器对该卷只读          readOnly: true      # 该容器开放的端口列表      ports:        # 容器端口为 80        - containerPort: 80          # 协议为 TCP          protocol: TCP  # 该 Pod 的卷列表  volumes:    # 有一个名为 html 的 emptyDir 卷    - name: html      emptyDir: {}

kubectl port-forward fortune 8080:80: 将 fortune 的 80 端口转发到本地 8080 端口,使得我们可以在本地浏览器中访问,可以发现每 10 秒中页面的内容换一次

指定用于 emptyDir 的介质 P168

emptyDir 的默认是在承载 pod 的工作节点的实际磁盘上创建的,但我们可以将 Pod.volumes.emptyDir.medium 设置为 Memory 使得文件存储在内存中。 P168

emptyDir 卷是最简单的卷类型,但是其他类型的卷都是在它的基础上构建的,在创建空目录后,它们会用数据填充它。 P168

使用 Git 仓库作为存储卷 P168

gitRepo 卷基本上也是一个 emptyDir 卷,它通过克隆 Git 仓库并在 pod 启动时(但在创建容器之前)检出特定版本来填充数据。 P168

13b3c247778b24f77397d4d370c472e7.png

图 6.3 gitRepo 卷是一个 emptyDir 卷,最初填充了 Git 仓库但内容

总结 P171

gitRepo 卷就像 emptyDir 卷一样,基本上是一个专用目录,专门用于包含卷的容器单独使用。当 pod 被删除时,卷及其内容被删除。 P171

访问工作节点文件系统上的文件 P171

大多数 pod 应该忽略它们的主机节点,因此他们不应该访问节点文件系统上的任何文件。但是某些系统级别的 pod (通常由 DaemonSet 管理)确实需要读取节点的文件或使用节点文件系统来访问节点设备。Kubernetes 通过 hostPath 卷实现了这一点。 P171

介绍 hostPath 卷 P171

hostPath 卷指向节点文件系统上的特定文件目录。在同一个节点上运行并在其 hostPath 卷中使用相同路径的 pod 可以看到相同的文件。hostPath 卷是一种持久性存储,数据会存储到节点对应的路径中。 P171

63c93e24345b117d246704bb64665956.png

图 6.4 hostPath 卷将工作节点上的文件或目录挂载到容器的文件系统中

hostPath 卷通常用于尝试单节点集群中单持久化存储。仅当需要在节点上读取或写入系统文件时才使用 hostPath ,切勿使用它们来持久化跨 pod 的数据。 P173

使用持久化存储 P173

为了使持久化的数据能够从任何集群节点访问,需要将其存储在某种类型的网络存储 (NAS) 中。 P173

通过底层持久化存储使用各种卷 P177

•gcePersistentDisk: 运行在 Google Kubernetes 引擎上的卷•awsElasticBlockStore: 运行在 Amazon 的 AWS EC2 上的卷•azureFIle/azureDisk: 运行在 Microsoft Azure 上的卷•nfs: 运行在自有的一组服务器上的卷•iscsi: 挂载 ISCSI 磁盘资源•glusterfs: 挂载 GlusterFS•rbd: 适用于 RADOS•...

不需要知道每种类型的卷的所有信息,如有需要可以使用 pod: 运行于 Kubernetes 中的容器 中介绍的 kubectl explain 查找对应的 API 信息。 P178

从底层存储技术解耦 pod P179

Kubernetes 的基本理念旨在向应用程序及开发人员隐藏真实的基础设施,使他们不必担心基础设施的具体状态,并使应用程序可在大量云服务商和数据企业之间进行功能迁移。 P179

介绍持久卷和持久卷声明 P179

Kubernetes 集群中为了使应用能够正常请求存储资源,同时避免处理基础设施细节,引入了两个新的资源,分别是 PersistentVolume (持久卷,简称 PV) 和 PersistentVolumeClaim (持久卷声明,简称 PVC) 。 P179

9d5feb038b3896a655c66b446001f4ac.png

图 6.6 持久卷由集群管理员提供,并被 pod 通过持久卷声明来消费

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

创建持久卷 P180

我们可以使用如下描述文件 mongodb-pv-hostpath.yaml 创建一个持久卷。 P181

# 遵循 v1 版本的 Kubernetes APIapiVersion: v1# 资源类型为 PersistentVolumekind: PersistentVolumemetadata:  # PV 的名称  name: mongodb-pvspec:  # 该 PV 的大小为 1GB  capacity:    storage: 1Gi  # 访问模式列表  accessModes:    # 可以被单个客户端挂载为读写模式    - ReadWriteOnce    # 可以被多个客户端挂载为只读模式    - ReadOnlyMany  # 当声明被释放后, PV 将被保留(不清理和删除)  persistentVolumeReclaimPolicy: Retain  # minikube 下指定节点上的路径为一个 hostPath 卷  hostPath:    path: /tmp/mongodb

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

e391616b31836436ec84e2088adc18af.png

图 6.7 和集群节点一样,持久卷不属于任何命名空间,区别于 Pod 和 PVC

通过创建持久卷声明来获取持久卷 P182

我们可以使用如下描述文件 mongodb-pvc.yaml 创建一个持久卷声明。 P182

# 遵循 v1 版本的 Kubernetes APIapiVersion: v1# 资源类型为 PersistentVolumeClaimkind: PersistentVolumeClaimmetadata:  # PVC 的名称  name: mongodb-pvcspec:  # 资源列表  resources:    # 申请列表    requests:      # 申请 1GB 的空间      storage: 1Gi  # 访问模式列表  accessModes:    # 允许单个客户端挂载为读写模式    - ReadWriteOnce  # 将在本文最后关于动态配置的部分中介绍  storageClassName: ""

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

访问模式简写: P183

•RWO: ReadWriteOnce —— 仅允许单个节点挂载读写•ROX: ReadOnlyMany —— 允许多个节点挂载只读•RWX: ReadWriteMany —— 允许多个节点挂载读写

注意:ROW, ROX, RWX 涉及可以同时使用卷的工作节点数量而并非 pod 的数量。 P183

持久卷是集群范围的,因此不能在特定的命名空间中创建;持久卷声明只能在特定的命名空间创建,所以持久卷和持久卷声明只能被同一命名空间内的 pod 创建使用。 P183

在 pod 中使用持久卷声明 P184

我们可以使用如下描述文件 mongodb-pod-pvc.yaml 创建一个引用持久卷声明的 pod 。 P184

# 遵循 v1 版本的 Kubernetes APIapiVersion: v1# 资源类型为 Podkind: Podmetadata:  # Pod 的名称  name: mongodbspec:  # 该 pod 包含的容器列表  containers:    # 第一个容器由以下镜像创建    - image: mongo      # 容器名      name: mongodb      # 该容器挂载列表      volumeMounts:        # 将名为 mongodb-data 的卷挂载到容器的 /data/db        - name: mongodb-data          mountPath: /data/db      ports:        # 容器端口为 27017        - containerPort: 27017          # 协议为 TCP          protocol: TCP  # 该 Pod 的卷列表  volumes:    # 有一个名为 mongodb-data 的持久卷声明    - name: mongodb-data      persistentVolumeClaim:        # 该持久卷声明的名称为 mongodb-pvc        claimName: mongodb-pvc

了解使用持久卷和持久卷声明的好处 P185

862b70a124a52b9935beccb8beebab85.png

图 6.8 直接使用或通过 PVC 和 PV 使用 GCE 持久磁盘

间接从基础设施获取存储对应用程序开发人员来说更加简单,不必关心底层实际使用的存储技术。 P185

可以在不同的 Kubernetes 集群上使用相同的 pod 和持久卷声明,因为它们不涉及任何特定依赖与基础设施的内容。 P185

回收持久卷 P186

先通过 kubectl delete pod mongodb 和 kubectl delete pvc mongodb-pvc 删除 pod 和持久卷声明。然后运行 kubectl get pv ,可以发现 mongodb-pv 的 STATUS 列为 Released ,并非最开始的 Available 。这表明这个卷已经使用过,所以可能包含前一个声明者的数据,如果集群管理员还没来得及清理,那么不应该将这个卷绑定到全新的声明中。 P186

手动回收持久卷 P186

我们目前持久卷的回收策略 (persistentVolumeReclaimPolicy) 为 Retain ,所以需要手动回收持久卷。手动回收需要先删除持久卷,然后在重新创建持久卷资源。我们可以决定如何处理底层存储中的文件:删除或保留复用。 P186

自动回收持久卷 P186

存在两种其他的回收策略: P186

•Recycle: 删除卷的内容并使卷可用于再次声明,通过这种方式,持久卷可以被不同的持久卷声明和 pod 反复使用•Delete: 删除底层存储

7cc4cdd68e5ee88df330e8de33575957.png

图 6.9 持久卷和持久卷声明的生命周期

持久卷的动态卷配置 P187

Kubernetes 可以通过使用 StorageClass 对象动态配置持久卷来自动执行创建持久卷的任务。 P187

注意:与持久卷类似, StorageClass 资源也是集群范围的。 P187

通过 StorageClass 资源定义可用存储类型 P188

我们可以使用如下描述文件 storageclass-fast-hostpath.yaml 创建一个 StorageClass 资源。 P188

# 遵循 storage.k8s.io/v1 版本的 Kubernetes APIapiVersion: storage.k8s.io/v1# 资源类型为 StorageClasskind: StorageClassmetadata:  # StorageClass 的名称  name: fast# 用于配置持久卷的插件provisioner: k8s.io/minikube-hostpath# 传递给插件的参数parameters:  # 持久卷的类型是 pd-ssd  type: pd-ssd

StorageClass 资源指定当持久卷声明请求其时应使用哪个置备程序来提供持久卷。 StorageClass 定义中定义当参数将传递给置备程序,并具体到每个供应器插件。 P188

请求持久卷声明中的存储类 P188

创建一个请求特定存储类的 PVC 定义 P188

我们可以使用如下描述文件 mongodb-pvc-dp.yaml 创建使用存储类的 PVC 。 P188

# 遵循 v1 版本的 Kubernetes APIapiVersion: v1# 资源类型为 PersistentVolumeClaimkind: PersistentVolumeClaimmetadata:  # PVC 的名称  name: mongodb-pvcspec:  # 资源列表  resources:    # 申请列表    requests:      # 申请 100MB 的空间      storage: 100Mi  # 访问模式列表  accessModes:    # 允许单个客户端挂载为读写模式    - ReadWriteOnce  # 使用的 StorageClass 资源的名称为 fast  storageClassName: fast

在创建持久卷声明时,持久卷由 fast StorageClass 资源中引用的 provisioner 创建。即使现有手动设置的持久卷与持久卷声明匹配,也会使用 provisioner 创建一个新的持久卷。 P189

kubectl get pv: 可以发现自动创建了一个新的持久卷。它的回收策略是 Delete ,这意味着当 PVC 被删除时,持久卷也将被删除。 P189

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGEpvc-2a2c7edd-80f3-4bec-9155-ca89380d6c87   100Mi      RWO            Delete           Bound    default/mongodb-pvc   fast                    3m14s

StorageClass 的好处:声明是通过名称引用它们的。因此只要 StorageClass 名称相同,那么 PVC 定义便可跨不同集群移植。 P190

不指定存储类的动态配置 P190

如果持久卷声明没有明确指出要使用哪个存储类(没有指定该字段的值),则默认存储类会用于动态提供持久卷的内容。 P191

我们可以使用如下描述文件 mongodb-pvc-dp-nostorageclass.yaml 创建使用默认存储类的 PVC 。 P191

# 遵循 v1 版本的 Kubernetes APIapiVersion: v1# 资源类型为 PersistentVolumeClaimkind: PersistentVolumeClaimmetadata:  # PVC 的名称  name: mongodb-pvc-nostorageclassspec:  # 资源列表  resources:    # 申请列表    requests:      # 申请 100MB 的空间      storage: 100Mi  # 访问模式列表  accessModes:    # 允许单个客户端挂载为读写模式    - ReadWriteOnce  # storageClassName 字段未配置

如果指定 storageClassName 为空字符串 ("") ,那么就和上面 mongodb-pvc.yaml 一样,用于强制将持久卷声明绑定到预配置的其中一个持久卷。 P192

9053929f838b37e140a8f5d8e3a1addb.png

图 6.10 持久卷动态配置

将持久化存储附加到一个容器的最佳方式是仅创建 PVC (如果需要,可以使用明确指定的 storageClassName) 和容器(其通过名称引用 PVC),其他所有内容都由动态持久卷置备程序处理。 P192

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值