第 34 篇 k8s之存储基础:emptyDir 与 hostPath

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。


在前面的文章中,我们用 Volume 为 Redis 持久化了数据,用 ConfigMap 和 Secret 注入了配置文件。你可能会觉得,K8s 的存储已经够用了。但如果我问你:Pod 里的多个容器如何共享临时文件?如何让容器访问宿主机上的特定目录或文件?

这两个场景,K8s 提供了两种最基础的存储卷类型来解决:emptyDirhostPath。它们是所有 K8s 存储中最简单的两种类型,也是理解更复杂的 PV/PVC(下一篇主题)的前置知识。

一、emptyDir:Pod 级别的临时存储

1.1 什么是 emptyDir?

emptyDir 是 Kubernetes 中最简单的卷类型。它的生命周期和 Pod 绑定------Pod 创建时自动创建一个空目录,Pod 删除时该目录连同里面所有数据被永久删除。

emptyDir 的核心用途是让同一个 Pod 内的多个容器共享文件。它的存储位置可以是节点的磁盘(默认),也可以配置为 tmpfs 存储在内存中以提高 IO 性能。

emptyDir 的三个关键特性:

  • Pod 级别生命周期:随 Pod 创建,随 Pod 删除。容器重启不影响 emptyDir 中的数据。

  • 同 Pod 内共享:Pod 内所有容器都可以读写该目录。

  • 节点本地存储:数据存储在 Pod 所在节点的磁盘上,不会跟随 Pod 迁移到其他节点。

在第 23 篇 Sidecar 模式实战中,我们其实已经用过 emptyDir------volumes: - name: shared-logs emptyDir: {} 让 Flask 主容器和日志采集 Sidecar 共享日志目录。当时我们只演示了用法,没有深挖它为什么是 emptyDir 而不是其他类型。

1.2 动手验证 emptyDir 的基本行为

下面的 YAML 定义一个 Pod,包含一个写入数据的容器和一个读取数据的容器:

bash 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: emptydir-demo
spec:
  containers:
  - name: writer
    image: alpine
    command: ["sh", "-c", "echo 'shared data' > /cache/demo.txt && sleep 3600"]
    volumeMounts:
    - name: shared-cache
      mountPath: /cache
  - name: reader
    image: alpine
    command: ["sh", "-c", "sleep 10 && cat /data/demo.txt && sleep 3600"]
    volumeMounts:
    - name: shared-cache
      mountPath: /data
  volumes:
  - name: shared-cache
    emptyDir: {}

这个 Pod 包含两个容器:writer 和 reader。它们通过 shared-cache 这个 emptyDir 卷共享文件。writer 写入 /cache/demo.txt,reader 从 /data/demo.txt 读取------两个容器内路径不同,但底层是同一个空目录。

部署并验证:

bash 复制代码
kubectl apply -f emptydir-demo.yaml
kubectl logs emptydir-demo -c reader
# shared data

reader 成功读到了 writer 写入的内容,这就是 emptyDir 实现的多容器文件共享。

1.3 emptyDir 的常见使用场景

场景一:Sidecar 模式中的文件交换

Flask 容器写日志到 /app/logs,Filebeat Sidecar 从 /var/log/flask 读取并转发。两个路径指向同一个 emptyDir 卷。

场景二:临时排序/计算空间

数据处理任务需要大量临时磁盘空间(如排序大文件),使用 emptyDir 作为临时工作目录。任务结束后 Pod 自动清理,不会留下垃圾文件。

场景三:共享缓存

一个容器下载数据,另一个容器处理数据。通过 emptyDir 共享,避免网络传输开销。

1.4 将 emptyDir 存储在内存中(tmpfs)

默认 emptyDir 使用节点磁盘。对于需要高 IO 性能且不介意丢失数据的场景,可以将其配置为内存存储:

bash 复制代码
volumes:
- name: fast-cache
  emptyDir:
    medium: Memory
    sizeLimit: 256Mi
  • medium: Memory:数据存储在 tmpfs(内存文件系统)中,读写速度远快于磁盘

  • sizeLimit: 256Mi:限制最大使用内存,防止某个 Pod 过度消耗节点内存

场景对比medium: Memory 适合需要高 IOPS 的临时计算(如机器学习训练中的中间特征存储),普通磁盘 emptyDir 适合日志、临时文件等 IO 要求不高的场景。内存 emptyDir 的数据在容器重启后仍然保留(因为 tmpfs 生命周期跟随 Pod),但 Pod 被删除或节点重启时数据会丢失。

二、hostPath:访问宿主机文件系统

2.1 什么是 hostPath?

hostPath 卷将宿主机(Node)文件系统上的一个特定目录或文件直接挂载到 Pod 中。与 emptyDir 不同,hostPath 的数据在 Pod 删除后依然保留在宿主机上,并且同一节点上的多个 Pod 可以挂载同一个宿主机路径来共享数据。

hostPath 的核心特性是绕过了容器的文件系统隔离,让 Pod 能够直接读写宿主机目录。这使得它能够用于运行需要访问宿主机资源的集群级组件,但也带来了更强的节点依赖性。

在第 27 篇部署 DaemonSet 时,我们演示过 hostPath------Node Exporter 通过 hostPath 挂载宿主机的 /proc/sys 来采集系统指标。那是 hostPath 最经典的用法。

2.2 hostPath 的类型

hostPath 通过 type 字段定义路径的存在性要求,这决定了 kubelet 在挂载前的检查行为:

2.3 hostPath 的三大典型场景

场景一:访问容器运行时数据

bash 复制代码
volumes:
- name: docker-sock
  hostPath:
    path: /var/run/docker.sock
    type: Socket

这是容器监控工具(如 cAdvisor、Prometheus)访问 Docker 运行时的常用配置。但这也存在严重的安全风险------容器获得了控制宿主机 Docker 引擎的能力。

场景二:节点级日志或配置文件访问

bash 复制代码
volumes:
- name: node-logs
  hostPath:
    path: /var/log
    type: Directory

Logging Agent 通过这种方式采集宿主机上所有容器的日志。

场景三:DaemonSet 部署的集群组件

Node Exporter 通过 hostPath 挂载 /proc/sys 采集系统指标;CNI 网络插件通过 hostPath 管理网络配置文件。

2.4 hostPath 的使用限制与安全风险

hostPath 在提供便利的同时,也带来了三个主要风险:

  1. 节点依赖性 :Pod 被调度到不同节点时,宿主机目录内容可能完全不同,导致 Pod 行为不可预测。hostPath 通常与 nodeSelectornodeName 配合使用,将 Pod 绑定到特定节点。

  2. 安全风险DirectoryOrCreate 如果创建的目录父目录属于 root,kubelet 会以 root 身份创建目录,可能导致权限问题。挂载敏感路径(如 /var/run/docker.sock)相当于赋予了容器控制宿主机的权限。

  3. 资源监控困难:hostPath 的磁盘使用量不会被 K8s 自动监控和限制,Pod 可能无意中填满节点磁盘。

最佳实践 :对于普通应用,优先使用 emptyDir(临时共享)或 PV/PVC(持久化)。hostPath 应限制在 DaemonSet 部署的集群组件,并且永远不要在 hostPath 中挂载 docker.sock 给不信任的容器。

三、emptyDir vs hostPath vs PV/PVC

在进入更复杂的存储体系之前,我们先建立这三个概念的清晰边界:

emptyDir 和 hostPath 都是节点级别的存储,Pod 一旦漂移到其他节点就无法访问原来的数据。对于数据库这类需要真正持久化的应用,必须使用 PV/PVC。这正是下一篇要解决的问题。

四、命令速查表

五、本篇总结

  • emptyDir 是 Pod 级的临时存储,适用于多容器间的文件共享和临时数据处理。分为磁盘型和内存型(tmpfs)。

  • hostPath 是节点级存储,将宿主机目录挂载到容器,适用于需要访问宿主机资源的集群组件。使用时需特别注意安全和节点依赖性。

  • 两者都不是持久化存储------Pod 删除或漂移到其他节点后,数据可能丢失。对于需要跨节点持久化的数据,必须使用 PV/PVC。

理解了 emptyDir 和 hostPath,你就掌握了 K8s 存储体系中"临时"和"节点绑定"这两类场景的工具。下一篇------第 35 篇:PVC 与 StorageClass:动态存储供应,我们将进入 K8s 存储体系的核心,学习如何用 PVC 和 StorageClass 为应用提供真正的持久化、跨节点的存储能力。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

相关推荐
取经蜗牛1 小时前
Docker 常用命令全面总结
运维·docker·容器
DO_Community2 小时前
AI推理成本砍半:DigitalOcean 批量推理服务正式上线
云原生·serverless·aigc·claude·deepseek
qq_382949222 小时前
推荐一门不错的微服务实战课:Spring Cloud Alibaba 从入门到落地
微服务·云原生·架构
IT策士2 小时前
第31篇 k8s之Ingress 进阶:TLS、重写与认证
云原生·容器·kubernetes
川石课堂软件测试2 小时前
作为一名测试工程师如何学习Kubernetes(k8s)技能
学习·测试工具·容器·职场和发展·kubernetes·测试用例·harmonyos
无聊的老谢3 小时前
DDD 驱动的电信网络优化微服务建模实战
微服务·云原生·架构
qq_452396233 小时前
第十一篇:《Docker Compose:多容器应用编排入门》
运维·docker·容器
Geoking.3 小时前
Docker安装Nacos指南
运维·docker·容器
日取其半万世不竭4 小时前
密码管理工具私有化部署,Vaultwarden 备份恢复怎么做?
数据库·docker·容器