Kubernetes 存储概念之Volumes介绍
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为啥为644呢?
答案:这是因为,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 卷之前不会执行任何检查。 | 
DirectoryOrCreate | 
如果给定的path--要挂载的路径,在对应pod所在的K8S集群结点机上不存在,那么将根据该path在对应结点机上自动创建对应的目录,并且设置目录权限为 0755,与 Kubelet 具有相同的用户组和所有者权限 | 
Directory | 
给定的path必须为对应pod所在结点机上已存在目录路径 | 
FileOrCreate | 
如果给定的path在对应pod所在结点机上指向的文件不存在,那么会根据需要自动创建一个空文件,并设置文件权限为 0644,与 Kubelet 具有相同的用户组和所有者权限 | 
File | 
给定的path必须是对应pod所在结点机上指向已存在文件的文件路径 | 
Socket | 
给定的path必须指向已存在 UNIX socket | 
CharDevice | 
给定的path必须指向已存在的字符设备 | 
BlockDevice | 
给定的path必须指向已存在的块设备 | 
使用这种卷类型时请注意,因为:
- 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服务器运行并导出共享,然后才能使用它。
有关更多详细信息,请参阅有关NFS example的信息
persistentVolumeClaim
A persistentVolumeClaim 卷用于挂载 PersistentVolume 到Pod。PersistentVolumeClaims是用户在不了解特定云环境细节的情况下“声明”持久存储(如GCE PersistentDisk或iSCSI卷)的一种方式。
有关更多详细信息,请参阅有关PersistentVolumes的信息
secret
secret 卷用于传递敏感信息,比如密码,给pod。您可以将 secret 存储在Kubernetes API中,并将其作为文件装载,以供pods使用,而无需直接耦合到Kubernetes。 secret 卷由tmpfs(一个由RAM提供支持的文件系统)提供支持,因此它们永远不会写入非易失性存储。
注意: 必须先在Kubernetes API中创建一个secret,然后才能使用它
注意:使用secret作为subPath卷加载的容器将不会接收secret更新。
有关更多详细信息,请参阅有关 Configuring Secrets的信息
查看更多卷类型介绍:https://kubernetes.io/docs/concepts/storage/volumes/#volume-types
使用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 存储概念之Volumes介绍的更多相关文章
- Kubernetes存储之Persistent Volumes简介
		
简介 管理存储和管理计算有着明显的不同.PersistentVolume子系统给用户和管理员提供了一套API,从而抽象出存储是如何提供和消耗的细节.在这里,我们介绍两种新的API资源:Persiste ...
 - K8s - Kubernetes重要概念介绍(Cluster、Master、Node、Pod、Controller、Service、Namespace)
		
K8s - Kubernetes重要概念介绍(Cluster.Master.Node.Pod.Controller.Service.Namespace) Kubernetes 是目前发展最 ...
 - (九)Kubernetes 存储卷
		
Kubernetes存储卷概述 Pod本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,kubelet会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态:第二,当很多容器在同一 ...
 - 详解Kubernetes存储体系
		
Volume.PV.PVC.StorageClass由来 先思考一个问题,为什么会引入Volume这样一个概念? " 答案很简单,为了实现数据持久化,数据的生命周期不随着容器的消亡而消亡. ...
 - Kubernetes 基本概念和术语
		
Kubernetes 基本概念和术语 Kubernetes 中大部分概念如 Node.Pod.Replication Controller. Service 等都可以看做一种 "资源对象&q ...
 - Kubernetes基本概念和术语之《Pod》
		
Pod是Kubernetes的最重要也最基本的概念.我们看到每个Pod都有一个特殊的被称为“根容器”的Pause容器对应的镜像属于Kubernetes平台的一部分.除了Pause容器,每个Pod还包含 ...
 - 从零开始入门 K8s | Kubernetes 存储架构及插件使用
		
本文整理自<CNCF x Alibaba 云原生技术公开课>第 21 讲. 导读:容器存储是 Kubernetes 系统中提供数据持久化的基础组件,是实现有状态服务的重要保证.Kubern ...
 - 01 . 容器编排简介及Kubernetes核心概念
		
Kubernetes简介 Kubernetes是谷歌严格保密十几年的秘密武器-Borg的一个开源版本,是Docker分布式系统解决方案.2014年由Google公司启动. Kubernetes提供了面 ...
 - 第21 章 : Kubernetes 存储架构及插件使用
		
Kubernetes 存储架构及插件使用 本文将主要分享以下三方面的内容: Kubernetes 存储体系架构: Flexvolume 介绍及使用: CSI 介绍及使用. Kubernetes 存储体 ...
 - 第3 章 : Kubernetes 核心概念
		
Kubernetes 核心概念 本文整理自 CNCF 和阿里巴巴联合举办的云原生技术公开课的课时 3:Kubernetes 核心概念.本次课程中,阿里巴巴资深技术专家.CNCF 9个 TCO 之一 李 ...
 
随机推荐
- Android 13 - Media框架(20)- ACodec(二)
			
关注公众号免费阅读全文,进入音视频开发技术分享群! 这一节开始我们就来学习 ACodec 的实现 1.创建 ACodec ACodec 是在 MediaCodec 中创建的,这里先贴出创建部分的代码: ...
 - linux获取docker容器中的文件路径怎么表示
			
在Linux系统中,Docker容器中的文件路径与宿主机上的文件系统是隔离的,因此我们不能直接使用宿主机的文件系统路径来访问容器内的文件.但是,有几种方法可以让我们获取或操作Docker容器中的文件. ...
 - k8s——pod的资源配置文件详解(manifest)
			
pod的资源配置文件(manifest) 详细介绍pod的资源配置文件(mannifest)的各个字段的含义 元数据 字段 是否必须 类型 含义 由用户提供 备注 name 必须 str pod的名称 ...
 - 如何保留 Excel 表头和第一行数据并追加 CSV 数据
			
准备工作 在开始之前,确保你的 Python 环境中已经安装了 openpyxl 和 pandas 库.可以使用以下命令进行安装: pip install openpyxl pandas 第一步:编写 ...
 - idea 使用 mvn clean package 报错 Could not create local repository at
			
使用 mac 版本的 idea 打包使用打包命令 mvn clean package 总是报错: [ERROR] Could not create local repository at /Repos ...
 - 解决Python使用GPU
			
在Python中使用GPU进行计算通常涉及到一些特定的库,如NumPy.SciPy的GPU加速版本(如CuPy.PyCUDA等)或深度学习库(如TensorFlow.PyTorch等).这些库能够利用 ...
 - Linux Topicons Plus桌面工具安装
			
Topicons Plus是Linux系统GNOME桌面环境的工具,方便于在工具栏显示应用小图标. 1.进入GNOME商店搜搜下载TopIcons Plus工具.下载路径:https://extens ...
 - INFINI Gateway 如何防止大跨度查询
			
背景 业务每天生成一个日期后缀的索引,写入当日数据. 业务查询有时会查询好多天的数据,导致负载告警. 现在想对查询进行限制--只允许查询一天的数据(不限定是哪天),如果想查询多天的数据就走申请. 技术 ...
 - .net core .net5 asp.net core mvc 与quartz.net 3.3.3 新版本调用方式
			
参照了:https://www.cnblogs.com/LaoPaoEr/p/15129899.html 1.项目Nuget引用Quartz.AspNetCore和Quartz.Extensions. ...
 - mybatis中的useGeneratedKeys="true"
			
Springboot中 Mybatis 配置文件 Mapper参数useGeneratedKeys="true" keyProperty="id"useGene ...