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

如何确保共享同一PVC的两个Kubernetes工作负载始终同节点部署?

问题描述

我有如下PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: managed-premium-delete
  resources:
    requests:
      storage: 50Gi

该PVC被两个工作负载使用:

StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:  
  name: foo
  labels:
    component: foo
spec:
  template:   
    spec:   
      containers:
      - image: foo:1.0.0
        name: foo
        volumeMounts:
        - mountPath: /a/specific/path
          name: shared
          readOnly: true
      volumes:
      - name: shared
        persistentVolumeClaim:
          claimName: my-pvc

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:       
  name: bar
spec:
  replicas: 1
  template:            
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                component: foo
            topologyKey: kubernetes.io/hostname
      containers:
      - image: bar:1.0.0
        name: bar
        volumeMounts:
        - mountPath: /a/specific/path
          name: shared
          readOnly: true
      volumes:
      - name: shared
        persistentVolumeClaim:
          claimName: my-pvc

当前存在以下问题:

  • 若Pod A与Pod B不在同一节点,其中一个Pod将无法挂载卷;
  • 若两者互设Pod亲和性,重启时会因循环依赖导致kubelet无法调度;
  • 若指定节点亲和性,集群缩容导致节点退役时会出现什么问题?

请问如何确保foo和bar这两个工作负载始终在同一节点启动,以满足共享PVC的需求?


解决方案

1. 单向亲和性+StatefulSet单实例约束

利用ReadWriteOnce PVC绑定节点的特性,让Deployment仅亲和StatefulSet的Pod,同时给StatefulSet设置单实例约束,避免多实例调度冲突,且不要给StatefulSet设置反向亲和性,彻底规避循环依赖:

修改后的StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:  
  name: foo
  labels:
    component: foo
spec:
  replicas: 1 # 固定单实例,防止多节点绑定PVC
  selector:
    matchLabels:
      component: foo
  template:   
    spec:   
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                component: foo
            topologyKey: kubernetes.io/hostname
      containers:
      - image: foo:1.0.0
        name: foo
        volumeMounts:
        - mountPath: /a/specific/path
          name: shared
          readOnly: true
      volumes:
      - name: shared
        persistentVolumeClaim:
          claimName: my-pvc

保留原Deployment配置

原Deployment的单向亲和性已经正确:仅让bar的Pod跟随foo的Pod调度。重启时foo会优先完成PVC挂载并绑定节点,之后bar自动调度到同一节点,不会出现循环依赖。


2. 指定节点亲和性的节点退役问题及应对

如果直接给两个工作负载指定节点亲和性,当该节点被缩容退役时:

  • PVC绑定的PV会随节点下线,两个Pod都无法重新调度(ReadWriteOnce PV无法跨节点挂载);
  • 若没有提前迁移,会导致服务中断。

应对方案:

  • 配置PodDisruptionBudget(PDB),限制节点驱逐时的Pod不可用数量:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: foo-pdb
spec:
  minAvailable: 1
  selector:
    matchLabels:
      component: foo
  • 手动迁移流程:先删除foo的Pod,让StatefulSet在新节点重建并重新绑定PVC(需存储类支持动态PV重建或手动调整PV绑定),之后bar的Pod会自动调度到新节点;
  • 长期优化:改用支持ReadWriteMany的存储类(如NFS、Azure Files),解除PVC的单节点绑定限制。

3. 终极方案:Sidecar模式合并工作负载

如果foo和bar的生命周期、资源需求兼容,可将它们打包为同一个Pod的两个容器,共享卷挂载,天然保证同节点调度,彻底消除亲和性依赖问题:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-bar
spec:
  replicas: 1
  template:
    spec:
      containers:
      - image: foo:1.0.0
        name: foo
        volumeMounts:
        - mountPath: /a/specific/path
          name: shared
          readOnly: true
      - image: bar:1.0.0
        name: bar
        volumeMounts:
        - mountPath: /a/specific/path
          name: shared
          readOnly: true
      volumes:
      - name: shared
        persistentVolumeClaim:
          claimName: my-pvc

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:04:58