You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多副本Kubernetes Pod中Multer上传文件无法跨Pod共享问题求助

Kubernetes多Pod共享上传文件失败问题排查与解决

问题描述

我有一个运行在Kubernetes集群上的NodeJS应用,配置了3个Pod副本。使用Multer将文件上传到指定目录/public/uploads(包含子目录,比如头像存到/public/uploads/profiles)。为了实现跨Pod文件共享,配置了PV和PVC并挂载到/public/uploads,但上传的文件仅在执行上传的Pod可见,其他Pod看不到。请问是配置错误还是需要额外设置?

提供的配置文件

Volumes部署文件

kind: PersistentVolume
apiVersion: v1
metadata:
  name: testapp-volume
  labels:
    type: local
spec:
  capacity:
    storage: 5Gi
  storageClassName: manual
  persistentVolumeReclaimPolicy: Delete
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/app-folder/uploads"

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: testapp-volumeclaim
  namespace: testapp-namespace
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual

Pods和Service部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: testapp-deployment
  namespace: testapp-namespace
  labels:
    app: testapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: testapp-deployment
  template:
    metadata:
      labels: 
        app: testapp-deployment
    spec:
      containers:
        - name: testapp-container
          image: /* Repository */
          ports:
            - containerPort: 2000
          imagePullPolicy: Always
          volumeMounts:
            - mountPath: /public/uploads
              name: testapp-volume
      imagePullSecrets:
        - name: testapp-secret
      volumes:
        - name: testapp-volume
          persistentVolumeClaim:
            claimName: testapp-volumeclaim

---

apiVersion: v1
kind: Service
metadata:
  name: testapp-deployment
  namespace: testapp-namespace
spec:
  type: ClusterIP
  selector:
    app: testapp-deployment
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 2000

Multer代码

var storage = multer.diskStorage({ //multers disk storage settings
    destination: function (req, file, cb) {
        cb(null, './public/uploads/' + req.body.folder)
    },
    filename: function (req, file, cb) {
        var datetimestamp = Date.now();
        var ext = path.extname(file.originalname);
        ext = ext.toLowerCase();
        console.log("FILE -> " + file.originalname + " ; RANDOM NUM -> " + generateRandomNumber(12) );
        cb(null, generateRandomNumber(14) + '_' + datetimestamp + '' + ext);
    }
});

var file_upload = multer({ 
    storage: storage,
    fileFilter: function (req, file, callback) {
        var ext = path.extname(file.originalname);
        ext = ext.toLowerCase();
        if(ext !== '.png' && ext !== '.jpg' && ext !== '.jpeg') {
            return callback(new Error('Only documents are allowed'));
        }
        callback(null, true)
    },
    limits:{
        fileSize: 1024 * 1024 * 100
    } 
});

问题根源

  1. ReadWriteOnce访问模式限制:当前PV和PVC的accessModes是ReadWriteOnce(RWO),该模式仅允许单个节点上的Pod挂载存储卷进行读写。如果3个Pod调度到不同节点,只有运行在PV所在节点的Pod能访问到实际的hostPath目录,其他节点的Pod挂载的是本地节点的/app-folder/uploads(空目录或独立目录),自然看不到上传的文件。
  2. hostPath存储不支持跨节点共享:hostPath是使用节点本地磁盘目录作为存储,每个节点的目录相互独立,本身就不适合多Pod跨节点共享文件的场景。
  3. Multer相对路径风险:Multer中使用的./public/uploads/是相对路径,可能指向容器内未挂载PV的目录(比如应用工作目录下的public/uploads),导致文件没有写入到共享PV中。

解决方案

1. 更换为支持跨节点共享的存储(推荐)

替换hostPath为支持多节点读写的存储方案,比如NFS、云厂商共享存储或分布式存储。以NFS为例,修改PV配置:

kind: PersistentVolume
apiVersion: v1
metadata:
  name: testapp-volume
  labels:
    type: nfs
spec:
  capacity:
    storage: 5Gi
  storageClassName: manual
  persistentVolumeReclaimPolicy: Retain
  accessModes:
    - ReadWriteMany  # 支持多节点同时读写
  nfs:
    server: <你的NFS服务器IP>
    path: "/nfs/testapp/uploads"  # NFS上预先创建的共享目录

同时修改PVC的accessModes为ReadWriteMany,确保与PV匹配:

spec:
  accessModes:
    - ReadWriteMany

2. 强制Pod调度到同一节点(临时测试方案)

如果暂时无法更换存储,可通过节点选择器让所有Pod运行在同一个节点,这样hostPath目录就能共享:
在Deployment的Pod模板中添加nodeSelector:

spec:
  template:
    spec:
      nodeSelector:
        kubernetes.io/hostname: <目标节点的名称>  # 替换为实际节点名

注意:该方案会失去Kubernetes的高可用性,节点故障会导致所有Pod下线,仅适合测试场景。

3. 修正Multer路径为绝对路径

将Multer中的相对路径改为绝对路径,确保文件写入到挂载的PV目录:

destination: function (req, file, cb) {
    // 使用绝对路径指向挂载的目录
    cb(null, '/public/uploads/' + req.body.folder)
}

内容的提问来源于stack exchange,提问作者user2572104

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:20:28