当前位置: 首页 > news >正文

docker与k8s的容器数据卷

Docker容器数据卷

特性

  • docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
  • 如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。
  • 关闭并重启容器,其数据不受影响;但删除Docker容器,则其改变将会全部丢失。

存在的问题

  • 存在于联合文件系统(在docker中,只读层以及在顶层的读写层组合被称为联合文件系统)中,不易于宿主机的访问
  • 容器间数据共享不便
  • 删除容器其数据会丢失

解决方案:“卷”

  • “卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定”。
  • “卷”可以在运行容器时即完成创建与绑定操作。当然,前提需要拥有对应的申明。
  • “卷”的初衷就是数据持久化。

创建数据卷

C:\Users\dell>docker volume create -d local volume_demo
volume_demoC:\Users\dell>docker volume ls
DRIVER    VOLUME NAME
local     volume_demoC:\Users\dell>docker volume inspect volume_demo
[{"CreatedAt": "2025-07-27T10:54:30Z","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/volume_demo/_data",//数据卷的存储目录"Name": "volume_demo","Options": null,"Scope": "local"}
]

卷的分类

当在创建数据卷的时候,可以在创建容器时将主机本地的路径挂载到容器内作为数据卷。也可以在创建后挂载数据卷到容器使用,可以在运行容器时通过指定-v或–mount参数来使用该volume,并且可以依据数据卷类型不同挂载不同格式的数据卷。

  • Volume:普通数据卷,映射到特定位置(/var/lib/docker/volumes/)。
  • Bind:绑定数据卷,映射到主机的任意位置。
  • tmpfs:临时数据卷,只存在于内存中。

使用默认的Volume数据卷,运行一个Nginx容器,source指定数据卷,destination指定source映射在容器中的目录:

docker run -d \
--name=nginx_demo_docker \
--mount source=nginx_demo_volume,destination=/usr/share/nginx.html \
nginx:latest

可以通过使用-v来指定数据卷信息:

docker run -d \
--name=nginx_demo_docker \
-v nginx_demo_volume,/usr/share/nginx.html \
nginx:latest

使用bind指定Volume数据卷类型,运行一个nginx容器,source指定数据卷,destination指定source映射在容器的目录:

docker run -d \
--name=nginx_demo_docker \
--mount type=bind, source=/usr/local/nginx_demo_volume,destination=/usr/share/ \
nginx:latest

可以通过使用-v来指定数据卷信息:

docker run -d \
--name=nginx_demo_docker \
-v /usr/local/nginx_demo_volume:/usr/share/ \
nginx:latest

挂载成功后,容器从/usr/share/目录下读取或写入数据,实际上是从宿主机的/usr/local/nginx_demo_volume目录中读取或写入数据。
使用Bind mount挂载宿主机目录到一个容器中的非空目录,那么此容器的非空目录中的文件会被隐藏,容器访问这个目录时能够访问到的文件均来自宿主机目录。这也是Bind mount模式和Volume模式在行为上最大的不同。
Volume和Bind mount模式能够在宿主机和容器间共享文件,从而能够将数据持久化到宿主机上,以避免写入容器存储层带来的容器停止后数据丢失的问题。
如果使用Linux运行Docker,那么避免写入数据到容器存储层还有一个方案:tmpfs mount。tmpfs mounts,顾名思义,是一种非持久化的数据存储。它只是将数据保存在宿主机的内存中,一旦容器停止运行,tmpfs mount会被移除,从而造成数据丢失。可以在运行容器时通过指定–tmpfs参数或–mount参数来使用tmpfs mount:

docker run -d --tmpfs /mydata:size=100m --name mycontainer myimage

数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。
数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载。

  • 新建数据卷容器

    docker run -it -v /dbdata --name db_data ubuntu
    
  • 共享数据卷容器

       docker run -it --volumes-from db_data --name db_data_test ubuntu
    

注意:db_data这个数据卷容器不能随便关闭,如果关闭了,其他挂载了db_data里面数据卷的容器就会用不了。

数据迁移

  • 备份

    docker run --rm --volumes-from [数据卷容器id/name] -v [宿主机目录]:[容器目录] [镜像名称] [备份命令]# 创建备份的容器,并且挂载/backup,然后执行备份压缩至/data
    docker run --rm --volumes-from vol-test -v /backup:/backup nginx tar zcf /backup/data.tar.gz /data
    
  • 恢复

    docker run --rm -itd --volumes-from [数据要到恢复的容器] -v [宿主机备份目录]:[容器备份目录] [镜像名称] [解压命令]docker run --rm --volumes-from vol-test -v /backup:/backup nginx tar xf /backup/data.tar.gz -C /

k8s数据卷

  • 通过emptyDir共享数据
    EmptyDir是一个特殊的Volume类型,如果删除Pod,emptyDir卷中的数据也将被删除,所以一般emptyDir用于Pod中的不同Container共享数据,比如一个Pod存在两个容器A和B,容器A需要使用容器B产生的数据,此时可以采用emptyDir共享数据,类似的使用如Filebeat收集容器内程序产生的日志。
    在这里插入图片描述

  • 使用HostPath挂载宿主机文件
    HostPath卷可将节点上的文件或目录挂载到Pod上,用于实现Pod和宿主机之间的数据共享,常用的示例有挂载宿主机的时区至Pod,或者将Pod的日志文件挂载到宿主机等。
    以下为使用hostPath卷的示例,实现将主机的/etc/timezone文件挂载到Pod的/etc/timezone(挂载路径可以不一致):
    在这里插入图片描述
    在配置HostPath时,有一个type的参数,用于表达不同的挂载类型,HostPath卷常用的type(类型)如下:

    • type为空字符串:默认选项,意味着挂载hostPath卷之前不会执行任何检查。
    • DirectoryOrCreate:如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限。
    • Directory:目录必须存在于给定的路径下。
    • FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权。
    • File:文件,必须存在于给定路径中。
    • Socket:UNIX套接字,必须存在于给定路径中。
    • CharDevice:字符设备,必须存在于给定路径中。
    • BlockDevice:块设备,必须存在于给定路径中。
  • 挂载NFS至容器
    在生产环境中,考虑到数据的高可用性,仍然不建议使用NFS作为后端存储。因为NFS存在单点故障,很多企业并非对其实现高可用,并且NFS的性能存在很大的瓶颈。所以生产中,建议使用分布式存储,在公有云中建议使用公有云提供的NAS存储来替代NFS,并且NAS性能更好,可用性更高。NFS作为一个比较流行的远端存储工具,在非生产环境中是一个比较好用的选择,可以快速地搭建使用。接下来演示如何使用Volume挂载NFS为容器提供持久化存储。
    和 emptyDir 、 HostPath 的 配 置 方 法 类 似 , NFS 的 Volume 配 置 也 是 在Volumes字段中配置的,和emptyDir不同的是,NFS属于持久化存储的一种,在Pod删除或者重启后,数据依旧会存储在NFS节点上。配置NFS也相对简单。
    在这里插入图片描述

  • PersistentVolume
    虽然Volume已经可以接入大部分存储后端,但是实际使用时还有诸多问题,比如:

    • 当某个数据卷不再被挂载使用时,里面的数据如何处理?
    • 如果想要实现只读挂载如何处理?
    • 如果想要只能有一个Pod挂载如何处理?

    如上所述,对于很多复杂的需求Volume可能难以实现,并且无法对存储卷的生命周期进行管理。另一个很大的问题是,在企业内使用Kubernetes的不 仅 仅 是 Kubernetes 管 理 员 , 可 能 还 有 开 发 人 员 、 测 试 人 员 以 及 初 学Kubernetes的技术人员,对于Kubernetes的Volume或者相关存储平台的配置参数并不了解,所以无法自行完成存储的配置。

    为 此 , Kubernetes 引 入 了 两 个 新 的 API 资 源 : PersistentVolume 和PersistentVolumeClaim。PersistentVolume(简称PV)是由Kubernetes管理员设置的存储,PersistentVolumeClaim(简称PVC)是对PV的请求,表示需要什么类型的PV。它们同样是集群中的一类资源,但其生命周期比较独立,管理员可以单独对PV进行增删改查,不受Pod的影响,生命周期可能比挂载它
    的其他资源还要长。如果一个Kubernetes集群的使用者并非只有Kubernetes管理员,那么可以通过提前创建PV,用以解决对存储概念不是很了解的技术人员对存储的需求。和单独配置Volume类似,PV也可以使用NFS、GFS、CEPH等常用的存储后端,并且可以提供更加高级的配置,比如访问模式、空间大小以及回收策略等。目前PV的提供方式有两种:静态或动态。静态PV由管理员提前创建,动态PV无须提前创建。

    1. PV回收策略
      在这里插入图片描述

    2. PV访问策略
      在这里插入图片描述

    3. 基于·NFS的PV
      在这里插入图片描述

    4. 基于HostPath的PV
      注意:使用hostPath需要固定Pod所在的节点,防止Pod飘移造成数据丢失。在这里插入图片描述

    5. PV的状态
      在这里插入图片描述

    6. PersistentVolumeClaim
      PVC是其他技术人员在Kubernetes上对存储的申请,它可以标明一个程序需要用到什么样的后端存储、多大的空间以及以什么访问模式进行挂载。这一点和Pod的QoS配置类似,Pod消耗节点资源,PVC消耗PV资源,Pod可以请求特定级别的资源(CPU和内存),PVC可以请求特定的大小和访问模式的PV。例如申请一个大小为5Gi且只能被一个Pod只读访问的存储。
      在实际使用时,虽然用户通过PVC获取存储支持,但是用户可能需要具有不同性质的PV来解决不同的问题,比如使用SSD硬盘来提高性能。所以集群管理员需要根据不同的存储后端来提供各种PV,而不仅仅是大小和访问模式的区别,并且无须让用户了解这些卷的具体实现方式和存储类型,达到了存储的解藕,降低了存储使用的复杂度。

    7. 案例如下:

      apiVersion: v1  # API 版本
      kind: PersistentVolume  # 类型为持久卷
      metadata:name: jenkins-pv  # 持久卷的名称
      spec:capacity:storage: 2Gi  # 容量为2GBaccessModes:#- ReadWriteMany  # 访问模式为多路读写- ReadWriteOnce  # HostPath 通常只能支持单节点写入,因此使用 ReadWriteOnce  hostPath:path: /data/jenkins#nfs:#  server: 192.168.16.2  # NFS 服务器地址#  path: /data/jenkins  # 共享的路径---kind: PersistentVolumeClaim  # 类型为持久卷声明
      apiVersion: v1
      metadata:name: jenkins-pvc  # 持久卷声明的名称namespace: jenkins  # 使用的命名空间
      spec:resources:requests:storage: 2Gi  # 请求2GB的存储空间accessModes:- ReadWriteOnce  # 访问模式与上面保持一致---
      apiVersion: apps/v1                 # 使用的 Kubernetes API 版本
      kind: Deployment                    # 资源类型为 Deployment
      metadata:name: jenkins                     # Deployment 的名称为 jenkinsnamespace: jenkins            # 所属的命名空间为 jenkins
      spec:replicas: 1                       # 副本数为 1selector:matchLabels:app: jenkins                  # 选择器选择带有标签 app: jenkins 的 Podtemplate:metadata:labels:app: jenkins                # Pod 的标签为 app: jenkinsspec:serviceAccountName: jenkins-sa   # 使用的服务账户为 jenkins-sanodeName: node1dnsConfig: #需要添加域名解析,不然容器内部可能无法访问外网nameservers:- "8.8.8.8"  # Google 的公共 DNS- "8.8.4.4"  # Google 的公共 DNScontainers:- name: jenkins                       # 容器的名称为 jenkinsimage: jenkins/jenkins:2.479.1        # 使用的镜像为 jenkins/jenkins:latest,高版本的jenkins会有跨域问题ports:- containerPort: 8080               # 容器监听的端口为 8080name: web                         # 端口名称为 webprotocol: TCP                    # 使用的协议为 TCP- containerPort: 50000              # 容器监听的端口为 50000name: agent                       # 端口名称为 agentprotocol: TCP                    # 使用的协议为 TCPresources:limits:cpu: "1000m"                    # CPU 的资源限制为 1000m(相当于 1 核)memory: "1Gi"                   # 内存的资源限制为 1GiBrequests:cpu: "500m"                     # CPU 的资源请求为 500m(相当于 0.5 核)memory: "512Mi"                 # 内存的资源请求为 512MiBlivenessProbe:                      # 存活探针配置httpGet:path: /login                    # 使用 HTTP GET 请求路径 /loginport: 8080                      # 请求的端口为 8080initialDelaySeconds: 60           # 初始延迟时间为 60 秒timeoutSeconds: 5                 # 超时时间为 5 秒failureThreshold: 12              # 失败阈值为 12readinessProbe:                     # 就绪探针配置httpGet:path: /login                    # 使用 HTTP GET 请求路径 /loginport: 8080                      # 请求的端口为 8080initialDelaySeconds: 60           # 初始延迟时间为 60 秒timeoutSeconds: 5                 # 超时时间为 5 秒failureThreshold: 12              # 失败阈值为 12volumeMounts:                       # 挂载卷配置- name: jenkins-volume              # 卷的名称为 jenkins-volumesubPath: jenkins-home             # 在卷中的子路径为 jenkins-homemountPath: /var/jenkins_home      # 挂载到容器中的路径为 /var/jenkins_homevolumes:                              # 卷配置- name: jenkins-volume                # 卷的名称为 jenkins-volume#emptyDir: {}persistentVolumeClaim:              # 持久卷声明claimName: jenkins-pvc        # 使用的持久卷声明的名称为 jenkins-pvc
      
  • 动态存储StorageClass
    虽然使用PV和PVC能屏蔽一些存储使用上的细节,降低了存储使用的复杂度,但是也会有另一个问题无法解决。当公司Kubernetes集群很多,并且使用它们的技术人员过多时,对于PV的创建是一个很耗时、耗力的工作,并且达到一定规模后,过多的PV将难以维护。所以就需要某种机制用于自动管理PV的生命周期,比如创建、删除、自动扩容等,于是Kubernetes就设计了一个名为StorageClass(缩写为SC,没有命名空间隔离性)的东西,通过它可以动态管理集群中的PV,这样Kubernetes管理员就无须浪费大量的时间在PV的管理中。
    具体如何使用,各位读者就参考下文档,这里就不介绍了。

http://www.xdnf.cn/news/1195759.html

相关文章:

  • 自由学习记录(74)
  • 多租户Kubernetes集群架构设计实践——隔离、安全与弹性扩缩容
  • MYSQL--再谈间隙锁和临键锁
  • RabbitMq 常用命令和REST API
  • 商品中心—1.B端建品和C端缓存
  • Python-初学openCV——图像预处理(四)——滤波器
  • 命令行和neovim的git操作软件-lazygit
  • sealos 方式安装k8s5节点集群
  • 自动标注软件X-AnyLabeling的使用教程
  • 基于动态增强的 LLM 置信度方法研究
  • C语言中:形参与实参的那些事
  • [SAP ABAP] ALV报表练习4
  • Matlab自学笔记六十五:解方程的数值解法(代码速成)
  • 文件IO——bmp图像处理
  • 磁悬浮轴承转子不平衡质量控制策略设计:原理、分析与智能实现
  • 基于java的在线教育平台管理系统、在线学习系统的设计与实现
  • 零基础学习性能测试第三章:jmeter性能组件应用(事件,并发,定时器)
  • 哈尔滨←→南昌的铁路要道
  • AWD的攻击和防御手段
  • idea中无法删除模块,只能remove?
  • 2025年7月26日训练日志
  • 最优估计准则与方法(4)最小二乘估计(LS)_学习笔记
  • 幸福网咖订座点餐小程序的设计与实现
  • element-plus安装以及使用
  • 《基于雅可比矢量近似的EIT触觉传感灵敏度非均匀校正》论文解读
  • 微分方程入门之入门之入门,纯笔记
  • 实现网页访问/接口调用KernelMemory
  • S7-200 SMART 数字量 I/O 组态指南:从参数设置到实战案例
  • Ubuntu系统 系统盘和数据盘扩容具体操作
  • C++类和对象(三)