如何让FileSystem类型持久卷数据随Pod迁移到新K8s节点
hostPath、local类型的PersistentVolume都属于节点级本地存储,数据直接落盘在Pod首次调度所在节点的本地磁盘路径上,本身不具备跨节点数据共享、同步能力。当Pod被调度到其他节点时,新节点只会读取自身本地对应路径下的文件,原节点上存储的历史数据不会自动同步过去,自然会启动全新的空实例,这是本地存储的固有特性,和访问模式、回收策略配置无关。
你后续测试的local类型PV没有解决问题是正常的:这类PV本质还是绑定节点本地磁盘,你配置的节点亲和性匹配所有worker节点,相当于Pod到任意节点都会挂载该节点自己的本地路径,和hostPath的行为完全一致,没有跨节点数据迁移能力。另外persistentVolumeReclaimPolicy: Retain参数仅控制PVC删除时PV和对应数据是否保留,和跨节点迁移逻辑没有任何关系。
方案1:替换为支持跨节点挂载的分布式网络存储(生产/长期使用推荐)
这是K8s持久化存储的标准使用方式,存储本身不绑定单节点,无论Pod调度到集群哪个节点,都能直接挂载同一个存储卷,读取全部历史数据,天然支持Pod跨节点漂移时数据不丢失。
- 可选存储类型:
- 块存储:Longhorn、OpenEBS、Ceph RBD、各类公有云提供的云硬盘(如AWS EBS、阿里云盘),完美兼容你当前使用的
ReadWriteOnce访问模式 - 文件存储:NFS、CephFS、GlusterFS
- 块存储:Longhorn、OpenEBS、Ceph RBD、各类公有云提供的云硬盘(如AWS EBS、阿里云盘),完美兼容你当前使用的
- 配置方式:部署对应存储的CSI插件后,不需要手动写死PV的本地路径,通过StorageClass动态创建PV即可,你现有的PVC定义、Deployment里的卷挂载逻辑完全不需要修改。
方案2:固定Pod调度节点(测试环境临时使用)
如果集群资源有限,不想部署额外存储组件,可以直接给Portainer Pod加节点选择器,强制其永远调度到存储了历史数据的节点上,从根源避免Pod漂移找不到数据的问题。
修改Deployment中spec.template.spec下的nodeSelector配置即可:
nodeSelector: kubernetes.io/hostname: <存储Portainer数据的原节点主机名>
该方案的缺陷是绑定的节点宕机时,Portainer将无法启动也无法访问历史数据,不适合生产环境使用。
方案3:节点间定期同步本地数据(极端临时场景过渡,不推荐)
可以通过DaemonSet或者定时脚本,在所有节点之间定期同步/opt/kubernetes/volumes/portainer路径下的数据,保证每个节点本地路径都存有最新的Portainer数据。
该方案同步存在延迟,节点数量多的时候维护成本极高,很容易出现数据覆盖、不一致、丢失的问题,禁止在生产环境使用。
内容的提问来源于stack exchange,提问作者Davis8988

