转载自:https://mp.weixin.qq.com/s/Ywx3ju6FP0IShOgI757XYA

Volumes

默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问题,第一:当容器挂掉,K8S重启它时,文件将会丢失;第二:当Pod中同时运行多个容器,容器之间需要共享文件时。Kubernetes的Volume解决了这两个问题

背景

在Docker中也有一个Volume(卷)的概念,尽管它有点松散,管理也不太好。Docker的卷只是磁盘、其它容器中的一个目录,功能也比较有限。

Kubernetes支持多种类型的卷。pod可以同时使用任意数量、类型的卷。短暂卷(ephemeral volume)具有与pod相同的生命周期,但持久卷(persistent volume)生命周期存在于pod的生存期之外。当某个Pod不复存在时,K8S将销毁短暂卷,但不会销毁持久卷。对于给定pod中的任何类型的卷,都会在容器重启时保存数据

卷的核心是一个目录,其中可能包含一些数据,pod中的容器可以访问该目录。该目录的形成方式、支持它的介质以及它的内容由所使用的特定卷类型决定。

要使用卷,需要在.spec.volumes中指定要为pod提供的卷,并在.spec.containers[*].volumeMounts中声明加载这些卷到容器的位置。容器中的进程会看到一个文件系统视图,该视图由容器镜像的初始内容以及容器中装入的卷(如果已定义的话)组成。该进程会看到一个root文件系统,它最初与容器镜像的内容相匹配。如果允许,对该文件系统层次结构中的任何写入都会影响该进程在执行后续文件系统访问时查看的内容。在镜像中的指定路径上加载卷。对于pod中定义的每个容器,必须单独指定容器使用的每个卷的加载位置

卷无法在其他卷内装载,此外,卷不能包含指向其他卷中任何内容的硬链接。

Volume类型

K8S支持以下多种卷类型:

  • awsElasticBlockStore
  • azureDisk
  • azureFile
  • cephfs
  • cinder
  • configMap
  • downwardAPI
  • emptyDir
  • fc (fibre channel)
  • flocker (deprecated)
  • gcePersistentDisk
  • gitRepo (deprecated)
  • glusterfs
  • hostPath
  • iscsi
  • local
  • nfs
  • persistentVolumeClaim
  • portworxVolume
  • projected
  • quobyte (deprecated)
  • rbd
  • secret
  • storageOS (deprecated)
  • vsphereVolume

以下,仅针对其中部分类型做简单介绍

configMap

ConfigMap 提供了一种注入配置数据到Pod中的方法。存储在ConfigMap中的数据可以被configMap卷引用,然后由运行在pod中的容器化应用程序使用

引用ConfigMap时,需要在卷中提供ConfigMap的名称。你可以自定义用于ConfigMap中特定条目的路径。

配置示例1:将log-config ConfigMap 装载到名为 configmap-pod 的Pod上:

apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log/log_level.yaml

log-config ConfigMap 作为卷装载,存储在其log_level条目中的所有内容都挂载到Pod中的/etc/config/log/log_level.yaml路径。注意,该路径是从卷的mountPath和键值为log_level的path派生的

注意:

  • 使用之前,必须创建ConfigMap,configMap.items中的key必须是已创建的ConfigMap的key名称,必须是已存在的;path为相对路径,相对于volumeMounts[n].mountPath而言,也就是说,mountPath/path即为ConfigMap文件在Pod中的绝对路径;volumeMounts[n].name要和引用的卷的名称(volumes[n].name)保持一致
  • 将ConfigMap作为 subPath 卷使用的容器将不接收ConfigMap的更新。
  • 文本数据使用UTF-8字符编码作为文件公开。对于其他字符编码,请使用 binary

配置示例2:

apiVersion: v1
kind: Pod
metadata:
name: nginx-bypass
spec:
containers:
- name: nginx-bypass
image: 'registry.cn-shenzhen.aliyuncs.com/casstime/nginx-bypass:latest'
volumeMounts:
- name: nginx-bypass-configs-vol
mountPath: /usr/local/openresty/nginx/conf/config.yaml
subPath: config.yaml
volumes:
- name: nginx-bypass-configs-vol
configMap:
name: nginx-bypass-configs
defaultMode: 420

说明:

defaultMode: 420 为 ConfigMap 卷中的文件设置权限,这里配置为420,即文件所有者用户具有可读可写权限,同组用户具有只读权限,其它用户仅有只读权限。

问题:上述的defaultMode为啥为420呢?

答案:这是因为,Linux的权限掩码“644”是8进制数,而yaml中的数字为10进制数,420转换为8进制数,刚好为“644”。

emptyDir

当 Pod 被分配给节点时,首先创建 emptyDir 卷,并且只要该 Pod 在该节点上运行,该卷就会存在。正如卷的名字而言,该卷最初是空的。Pod 中的所有容器可以读取和写入 emptyDir 卷中的相同文件,尽管该卷可以挂载到每个容器中相同或不同的路径上。当出于任何原因从节点中删除 Pod 时,emptyDir 中的数据将被永久删除。

注意:容器崩溃不会从节点中移除 pod,因此 emptyDir 卷中的数据在容器崩溃时是安全的。

emptyDir 的一些用途有:

  • 暂存空间,例如用于基于磁盘的合并排序
  • 用作长时间计算崩溃恢复时的检查点
  • Web服务器容器提供数据时,保存内容管理器容器提取的文件

取决于你的环境, emptyDir卷存储在支持结点的任何介质上,如磁盘或者SSD或者网络存储。然而,如果设置emptyDir.medium字段为Memory,那么k8s将挂载一个tmpfs(RAM支持的文件系统)。虽然tmpfs速度很快,但是请注意,不像磁盘,节点重启时,tmpfs将被清空,并且写入的任何文件都会根据容器的内存限制计数

注意: 如果启用SizeMemoryBackedVolumes feature gate,则可以指定内存备份卷的大小。如果未指定大小,则内存备份卷的大小将调整为Linux主机内存的%50。

emptyDir配置示例:

apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}

hostPath

注意:HostPath卷存在许多安全风险,在可能的情况下避免使用HostPath是最佳做法。当必须使用HostPath卷时,应将其范围限定为所需的文件或目录,并以只读方式装入。如果通过许可策略限制Hostpath对特定目录的访问,则必须要求volumeMounts使用readOnly装载才能使策略生效

hostPath 卷将主机节点的文件系统中的文件或目录挂载到Pod中。该功能大多数 Pod 都用不到,但它为某些应用程序提供了一个强大的"escape hatch"。

例如,一些hostPath 的用途如下:

  • 运行需要访问 Docker 内部的容器;使用 hostPath:/var/lib/docker
  • 在容器中运行 cAdvisor;使用 hostPath:/sys
  • 允许 Pod 指定给定的 hostPath 是否应该在 pod 运行之前存在,是否应该创建,以及它应该以什么形式存在

除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type。

type 字段支持以下值:

使用这种卷类型时请注意,因为:

  • hostPath会公开特权系统凭据(如用于Kubelet的凭证)或特权API(如容器运行时socket),这些凭据可用于攻击集群的其他部分
  • 由于节点上的文件不同,具有相同配置(例如从pod模板中创建的)的pod在不同节点上的行为可能不同
  • 在底层主机上创建的文件或目录只能由 root 写入。需要在特权容器中以 root 身份运行进程,或修改主机上的文件权限以便写入 hostPath 卷
  • FileOrCreate 模式不会自动创建文件的父目录。如果待挂载文件的父目录不存在,pod将无法启动。

配置示例1

apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
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

配置示例2

apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /mydir/subdir/testdir
type: DirectoryOrCreate

说明:

1、Deployment发布之前,例中的路径/mydir/subdir/testdir 在节点机上本是不存在的,但是因为type 设置为DirectoryOrCreate,发布之后查看对应pod所在结点机,发现该路径对应的目录已被创建,即路径已存在,并且权限为rwxr-xr-x

2、实践发现,volumeMounts[n].mountPath 如果不存在,则会被自动创建。

配置示例3:挂载节点机/etc/localtime到pod,解决容器时区和节点机时区不一致,导致时差8小时问题。

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-bypass
namespace: nginx-bypass
spec:
containers:
- image: 'registry.cn-shenzhen.aliyuncs.com/casstime/nginx-bypass:latest'
imagePullPolicy: Always
name: nginx-bypass
volumeMounts:
- mountPath: /etc/localtime
name: localtime
readOnly: true
volumes:
- hostPath:
path: /etc/localtime
type: ''
name: localtime

注意:如果容器内运行的是Java程序,则需要挂载/etc/timezone到 pod,因为java获取时间是从/etc/timezone文件获取的,如果没有则手动创建该文件:echo "Asia/shanghai" > /etc/timezone,当然,也可以不挂载文件,通过修改jvm时区参数:-Duser.timezone=GMT+08

nfs

nfs卷允许将现有 NFS(网络文件系统)共享装载到pod中。与移除Pod时会擦除的emptyDir不同,nfs卷的内容会被保留,而卷只是卸载。这意味着NFS卷可以预先填充数据,并且数据可以在pod之间共享。NFS可以由多个写入程序同时加载。

注意:必须先让自己的NFS服务器运行并导出共享,然后才能使用它。

persistentVolumeClaim

A persistentVolumeClaim 卷用于挂载 PersistentVolume 到Pod。PersistentVolumeClaims是用户在不了解特定云环境细节的情况下“声明”持久存储(如GCE PersistentDisk或iSCSI卷)的一种方式。

secret

secret 卷用于传递敏感信息,比如密码,给pod。您可以将 secret 存储在Kubernetes API中,并将其作为文件装载,以供pods使用,而无需直接耦合到Kubernetes。secret 卷由tmpfs(一个由RAM提供支持的文件系统)提供支持,因此它们永远不会写入非易失性存储。

注意: 必须先在Kubernetes API中创建一个secret,然后才能使用它

注意:使用secret作为subPath卷加载的容器将不会接收secret更新。

使用subPath

有时,在单个pod中共享一个卷以供多种用途是很有用的。volumeMounts.subPath属性指定引用卷内的子路径,而不是其根路径,默认的,挂载卷到容器内指定路径,会导致挂载该路径所在根路径下所有文件都消失,即根路径下的内容会被被挂载卷的内容覆盖。

配置示例1:

以下示例配置,将PHP应用代码和assets( js、css、模板、图片、flash 等等资源文件)存储在html文件夹,MySQL数据库则存储在mysql文件夹。不建议在生产环境使用该示例的subPath配置。

apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpasswd"
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data

配置示例2:引用路径指向某个文件

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-bypass
namespace: nginx-bypass
spec:
containers:
- image: 'registry.cn-shenzhen.aliyuncs.com/cmall/nginx-bypass:latest'
imagePullPolicy: Always
name: nginx-bypass
volumeMounts:
- name: configs-volume
mountPath: /usr/local/openresty/nginx/conf/config.yaml
subPath: config.yaml
volumes:
- name: configs-volume
onfigMap:
name: nginx-bypass-configs
defaultMode: 420

使用具有扩展环境变量的subPath

FEATURE STATE: Kubernetes v1.17 [stable]

使用subPathExpr字段从 downwardAPI环境变量构造 subPath目录名。subPath和subPathExpr属性是互斥的。

下例中,使用 Pod使用subPathExpr在hostPath 卷 /var/log/pods中创建pod1 目录。hostPath 卷从downwardAPI获取 Pod名称。宿主目录 /var/log/pods/pod1 挂载到容器的/logs目录

apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: container1
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: busybox
command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
volumeMounts:
- name: workdir1
mountPath: /logs
subPathExpr: $(POD_NAME)
restartPolicy: Never
volumes:
- name: workdir1
hostPath:
path: /var/log/pods

资源

emptyDir 卷的存储介质(磁盘、SSD 等)由保存在 kubelet 根目录(通常是 /var/lib/kubelet)的文件系统的介质决定。emptyDir 或 hostPath 卷可占用多少空间并没有限制,容器之间或 Pod 之间也没有隔离。

Kubernetes 存储卷详解的更多相关文章

  1. kubernetes系列10—存储卷详解

    本文收录在容器技术学习系列文章总目录 1.认识存储卷 1.1 背景 默认情况下容器中的磁盘文件是非持久化的,容器中的磁盘的生命周期是短暂的,这就带来了一系列的问题:第一,当一个容器损坏之后,kubel ...

  2. Docker系列05—Docker 存储卷详解

    本文收录在容器技术学习系列文章总目录 1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加面成,启动容器时,docker会加载只读镜像层并在镜 ...

  3. Kubernetes K8S之存储ConfigMap详解

    K8S之存储ConfigMap概述与说明,并详解常用ConfigMap示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS ...

  4. Kubernetes K8S之存储Volume详解

    K8S之存储Volume概述与说明,并详解常用Volume示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2C ...

  5. Kubernetes Pod 驱逐详解

    原文链接:Kubernetes Pod 驱逐详解 在 Kubernetes 中,Pod 使用的资源最重要的是 CPU.内存和磁盘 IO,这些资源可以被分为可压缩资源(CPU)和不可压缩资源(内存,磁盘 ...

  6. kubernetes 存储卷

    kubernetes 存储卷    数据卷用于实现容器持久化数据,Kubernetes对于数据卷重新定义,提供了丰富强大的功能.在Kubernetes系统中,当Pod重建的时候,数据卷会丢失,Kube ...

  7. MySQL数据库的各种存储引擎详解

    原文来自:MySQL数据库的各种存储引擎详解   MySQL有多种存储引擎,每种存储引擎有各自的优缺点,大家可以择优选择使用: MyISAM.InnoDB.MERGE.MEMORY(HEAP).BDB ...

  8. Web存储使用详解(本地存储、会话存储)

    Web存储使用详解(本地存储.会话存储)1,Web存储介绍HTML5的Web存储功能是让网页在用户计算机上保存一些信息.Web存储又分为两种:(1)本地存储,对应 localStorage 对象.用于 ...

  9. (九)Kubernetes 存储卷

    Kubernetes存储卷概述 Pod本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,kubelet会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态:第二,当很多容器在同一 ...

随机推荐

  1. scrapy框架入门

    scrapy迄今为止依然是世界上最好用,最稳定的爬虫框架,相比于其他直接由函数定义的程序, scrapy使用了面向对象并对网页请求的过程分成了很多个模块和阶段,实现跨模块和包的使用,大大提升了代码的稳 ...

  2. 基于Python+Sqlite3实现最简单的CRUD

    一.基本描述 使用Python,熟悉sqlite3的基本操作(查插删改),以及基本数据类型.事务(ACID).     准备工作:在sqlite3的官网上下载预编译的sqlite文件(windows) ...

  3. 面试官:你确定 Redis 是单线程的进程吗?

    作者:小林coding 计算机八股文网站:https://xiaolincoding.com 大家好,我是小林. 这次主要分享 Redis 线程模型篇的面试题. Redis 是单线程吗? Redis ...

  4. PostgreSQL下的SQL Shell(psql)工具

    首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485130&idx=1 ...

  5. 论文解读(MaskGAE)《MaskGAE: Masked Graph Modeling Meets Graph Autoencoders》

    论文信息 论文标题:MaskGAE: Masked Graph Modeling Meets Graph Autoencoders论文作者:Jintang Li, Ruofan Wu, Wangbin ...

  6. PHP操作路由器

    用PHP操作路由器 我们经常会碰到需要自动换IP的需求,比方模拟点击投票,数据采集被封IP,Alexa作弊等等,也就是需要经常换IP的,我们都可以通过PHP控制路由器来换IP,这样就不需要用按键精灵搞 ...

  7. 万答17,AWS RDS怎么搭建本地同步库

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 背景说明 AWS RDS 权限受限,使用 mysqldump 的时候无法添加 - ...

  8. Java学习--流程控制

    Java学习 流程控制 用户交互Scanner Scanner对象 Java通过Scanner类获取用户的输入 基本语法: Scanner scanner = new Scanner(System.i ...

  9. 树莓派4B无屏幕连接Wi-Fi/启用ssh/创建用户

    前边总得说点什么 最近每次在Win10上写代码需要启动Redis,残血Redis For Windows有卡死系统的bug.由于主机内存不大够用(已经扩到顶了),开虚拟机运行Redis更别提了..想起 ...

  10. java学习第一天.day05

    jvm的内存 栈:类方法使用后自动销毁,销毁的好处是释放内存 java方法执行时,在栈区执行 堆: 线程共享的一块内存区域      所有的对象实例以及 数组 都要在堆上分配      每次使用new ...