为啥我的主机路径持久卷可以从所有 pod 访问?

Posted

技术标签:

【中文标题】为啥我的主机路径持久卷可以从所有 pod 访问?【英文标题】:Why is my Host Path Persistent Volume reachable from all pods?为什么我的主机路径持久卷可以从所有 pod 访问? 【发布时间】:2021-10-14 01:45:33 【问题描述】:

我对名为 PVPVC 的 Kubernetes 学习步骤非常坚持。 我在这里要做的是了解如何处理多个 pod 上的共享读写卷。 我在这里的理解是,除非配置了类似 NFS 的存储类,否则不能在 Pod 之间共享 PVC。 我仍然使用我的 hostPath 存储类,我尝试了以下方法(Docker Desktop3 节点 microK8s 集群):

    PVC 具有动态主机路径配置
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-desktop
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Mi
    在同一 PVC 上使用 3 个复制的 pod 进行部署。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox
spec:
  replicas: 3
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
        - name: busybox
          image: library/busybox:stable
          command: ["/bin/sh"]
          args:
            ["-c", 'while true; do echo "1: $(hostname)" >> /root/index.html; sleep 2; done;',]
          volumeMounts:
            - mountPath: /root
              name: vol-desktop
      volumes:
        - name: vol-desktop
          persistentVolumeClaim:
            claimName: pvc-desktop
    用于提供卷内容的 nginx 服务器
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:stable
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: vol-desktop
          ports:
            - containerPort: 80
      volumes:
        - name: vol-desktop
          persistentVolumeClaim:
            claimName: pvc-desktop

按照我对文档的理解,这是不可能的,但实际上一切都运行得非常顺利,我的 Nginx 服务器很好地显示了最新的index.html 文件。 它实际上适用于单节点集群和多节点集群。

我在这里没有得到什么?为什么这个东西有效? 每个 pod 安装在启动时都是自己的主机路径卷吗? hostPath 存储如何在多个节点之间工作?

编辑:对于多节点情况,已在每台机器的相同存储路径之间创建了一个网络文件夹,这就是所有内容都已成功复制的原因。我不明白在每个安装了PVC 的节点上创建了相同的主机路径。 对于有相同问题的任何人:安装此主机路径 PVC 的每个节点都将在 PV 路径上创建自己的文件夹。 因此,如果节点之间没有网络复制,只有同一节点的 pod 将共享同一文件夹。 这就是为什么不鼓励在多节点集群上使用它的原因,因为集群上 Pod 的位置不可预测。

谢谢!

【问题讨论】:

AFAIK,RWO 表示“来自单个节点的一个或多个 RW”而不是单个 pod。所以只要所有的 pod 都在同一个节点上,它们就可以访问数据 Documentation on access modes 好吧@P....,但经过进一步测试,此设置也适用于多节点集群。感谢您的帮助 在您的“多节点”集群中,您的 pod 位于何处?它们是安排在单节点还是多节点上。尝试kubectl get pod -owide 看看那里的节点。 对于测试,在 3 个节点上复制了 15 个 pod: - 节点 1:5 个 pod - 节点 2:5 个 pod - 节点 3:5 个 pod 【参考方案1】:

如何处理多个 pod 上的共享读写卷。

重新设计您的应用程序以避免它。安全地管理多个写入器往往很脆弱且难以实现;你依赖于你的应用程序正确地执行诸如文件锁定之类的事情,底层共享文件系统实现正确地处理事情,以及系统能够容忍任何可能发生的网络故障。

您给出的示例经常出现在 Docker Compose 设置中:有一个混合了后端代码和静态文件的应用程序,然后尝试通过卷在运行时发布静态文件到反向代理。相反,您可以构建一个在构建时复制静态文件的映像

FROM nginx
ARG app_version=latest
COPY --from=my/app:$app_version /app/static /usr/share/nginx/html

让您的 CI 系统构建它并在构建后端映像后立即推送它。生成的图像提供相应的静态文件,但不需要共享卷或卷内容的任何手动管理。

对于其他类型的内容,请考虑将数据存储在数据库中,或使用维护自己的后备存储并可以处理并发问题的对象存储服务。然后你的大部分 pod 可以完全是无状态的,你可以单独管理数据(甚至可能在 Kubernetes 之外)。

hostPath 存储如何在多个节点之间工作?

它没有。这是对 Kubernetes 的指令,在 Pod 恰好被调度到的任何节点上,将该主机目录挂载到容器中。没有任何目录内容的管理;如果两个 pod 被调度在同一个节点上,它们将共享目录,如果没有,它们不会;如果您的 pod 的 Deployment 已更新,并且该 pod 被删除并在其他地方重新创建,则它可能不是同一个节点并且可能没有相同的数据。

除了一些非常特殊的例外,您根本不应该使用hostPath 卷。例外情况是日志收集器作为 DaemonSet 运行,其中 每个 节点上只有一个 pod,并且您有兴趣获取每个节点上不同的主机目录内容。

在您的特定设置中,您很幸运地发现了数据生产者和消费者所在的位置,或者您的 MicroK8s 设置导致主机目录被共享。它通常不是可靠的存储。

【讨论】:

感谢您的详细回答和您的时间! 我认为这可以通过应用程序的架构真正帮助 Kubernetes 学习者。对于 MicroK8s,由于我对 hostPath 和一些服务器设置的误解,事情是否正常,我编辑了我的问题。 那么如何处理多pods文件夹共享呢?真实用例:我的 php 应用程序需要为多个副本共享会话文件夹。这不是我可以改变的,我需要处理它。文件夹共享是必然的吗? 听起来该设置无法在 Kubernetes 中有效地运行超过 1 个副本。 (在有容器之前,您如何将应用程序部署在多个节点上?)您可以将会话数据存储在数据库中,还是存储在会话 cookie 本身中(通常很小)? 有趣的问题!我的目标是滚动更新和高可用性,仅用于培训目的!不幸的是,该应用程序仅适用于会话文件,这是了解如何在 Kubernetes 中实现这一点的好方法。感谢@david-maze 的这个结论!

以上是关于为啥我的主机路径持久卷可以从所有 pod 访问?的主要内容,如果未能解决你的问题,请参考以下文章

10最为主流的三个存储卷 emptyDirhostPathnfs

mariadb 在具有主机路径卷的 Kubernetes pod 内崩溃

如何进入K8S中的一个节点

k8s基础学习-介绍持久卷和持久卷声明

Kubernetes进阶之hostpath及emptyDir数据卷

部署k8s集群存储-数据卷