将CPFS智算版从Hostpath挂载迁移至PVC挂载

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: CPFS智算版是阿里云推出的高性能存储系统,适用于AI场景。早期通过Hostpath挂载,现支持PVC/PV方式,提升应用鲁棒性和数据持久性。本文介绍迁移背景、方案及操作步骤,助您顺利升级存储使用方式。

早期的CPFS智算版文件系统是随着灵骏节点一起部署,以Hostpath的形式挂载使用的,目前ACK已支持通过PVC/PV的方式挂载使用CPFS智算版文件系统。如果您有以Hostpath方式使用的CPFS智算版文件系统,建议迁移为PVC/PV的使用方式。


背景信息

CPFS智算版

CPFS智算版是阿里云面向AI服务推出的全新升级存储系统。通过创新的分布式并行存储架构设计,自研的高性能RoCE RDMA网络协议和虚拟存储通道技术,以及多级缓存弹性客户端,实现高吞吐、低延迟、Serverless化的高性能存储能力。更多信息,请参见CPFS智算版简介

Hostpath

Hostpath是Kubernetes原生支持的一种存储形态, 它支持通过Hostpath的形式将宿主机上的目录挂载到容器里面。使用方式如下:

  volumeMounts:
  - name: pvc-cpfs
    mountPath: /data
volumes:
- name: pvc-cpfs
  hostPath:
    path: /cpfs01

由于早期的CPFS智算版文件系统是随着灵骏节点一起部署的,该Hostpath目录(/cpfs01)一般是宿主机默认挂载的目录。


迁移场景

早期的CPFS智算版文件系统是随着灵骏节点一起部署,以Hostpath的形式挂载使用的,目前ACK已支持通过PVC/PV的方式挂载使用CPFS智算版文件系统。如果您有以Hostpath方式使用的CPFS智算版文件系统,建议迁移为PVC/PV的使用方式。

以下是PVC/PV相较于Hostpath的优势:

  • PVC/PV是Kubernetes使用外部存储的标准接口。该机制通过实现计算与存储的分离,可以极大地提升应用的鲁棒性与数据持久性。
  • 使用Hostpath方式无法自动额外为已有节点添加新的CPFS智算版文件系统;使用PVC/PV方式可以动态给已有节点关联新的CPFS智算版文件系统。
  • CPFS智算版文件系统依赖EFC客户端访问。使用Hostpath方式时,EFC客户端默认部署在节点上,运维复杂;使用PVC/PV方式时,EFC客户端会部署在容器内,后续需要升级EFC版本时,只需升级EFC客户端组件即可,无需升级节点上的EFC版本。
  • PVC/PV可以在集群纬度自适应使用,引用PVC/PV的Pod被调度到ECS节点时,会使用VPC挂载方式,被调度到灵骏节点时,会使用VSC挂载方式,可以简化使用成本。

环境准备

  1. 确保集群满足版本要求。如需升级集群,请参见升级集群
  • ACK托管集群Pro版:1.26及以上
  • ACK灵骏集群:1.20及以上
  1. 确保集群中已安装以下存储组件,且版本满足要求。您可以在集群的组件管理页面,确认组件版本,以及安装和升级组件。
  • bmcpfs-csi-controller组件为挂载CPFS智算版的CSI控制面组件,托管在阿里云侧。
  • bmcpfs-csi-node组件为挂载CPFS智算版的CSI节点侧组件,以DaemonSet形式部署在集群中。


终态迁移方案

下文以StatefulSet为例,介绍如何将现有的Hostpath挂载的StatefulSet迁移为PVC挂载的StatefulSet。

假设现有的StatefulSet的YAML配置如下:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-app-statefulset
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app-statefulset
  template:
    metadata:
      labels:
        app: my-app-statefulset
    spec:
      tolerations:
        - effect: NoSchedule
          key: node-role.alibabacloud.com/lingjun
          operator: Exists
      containers:
        - name: my-app-container
          image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginx:latest
          volumeMounts:
            - name: my-data-volume
              mountPath: /data
      volumes:
        - name: my-data-volume
          hostPath:
            path: /cpfs01

将Hostpath挂载迁移为PVC挂载的步骤如下:

  1. 基于已有的CPFS智算版文件系统,使用以下YAML创建对应的PV和PVC。
apiVersion: v1
kind: PersistentVolume
metadata:
  name: bmcpfs
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Ti
  claimRef:
    name: bmcpfs
    namespace: default
  csi:
    driver: bmcpfsplugin.csi.alibabacloud.com
    volumeAttributes:
      path: /
    volumeHandle: bmcpfs-xxxxx
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: bmcpfs
  namespace: default
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Ti
  volumeMode: Filesystem
  volumeName: bmcpfs

以下为核心参数。详细参数说明请参见使用CPFS智算版静态存储卷


参数

说明

csi.volumeAttributes.path

挂载目录。默认为/,表示挂载CPFS文件系统的根目录,支持设置为子目录,如/dir。如果子目录不存在,挂载时会自动创建。

csi.volumeHandle

CPFS智算版文件系统的ID。


  1. 修改StatefulSet的YAML,将Hostpath挂载改为PVC挂载,并将updateStrategy设为onDelete
apiVersion: v1
kind: PersistentVolume
metadata:
  name: bmcpfs
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Ti
  claimRef:
    name: bmcpfs
    namespace: default
  csi:
    driver: bmcpfsplugin.csi.alibabacloud.com
    volumeAttributes:
      path: /
    volumeHandle: bmcpfs-xxxxx
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: bmcpfs
  namespace: default
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Ti
  volumeMode: Filesystem
  volumeName: bmcpfs


  1. 保存应用修改后的YAML文件,并确认StatefulSet存量Pod无变化。
  2. 删除StatefulSet中的某一个Pod,观察新创建的Pod是否采用了新的PVC挂载方式,并确认Pod已经正常启动。
  3. 删除StatefulSet中的其他Pod,等待各个Pod重新启动,直至所有Pod都已转换挂载方式。
  4. 修改StatefulSet的YAML,将updateStrategy改为原有的策略。

过渡迁移方案

如果出于业务稳定性考虑,暂时不想将所有Pod迁移到PVC挂载的使用方式,可采用以下方式作为过渡,在不修改Hostpath使用方式的前提下,使用新的CPFS智算版存储卷。

操作步骤

  1. 基于已有的CPFS智算版文件系统,使用以下YAML创建对应的PV和PVC。

说明
如果有多个CPFS智算版文件系统,则需要创建多对PV和PVC。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: bmcpfs
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Ti
  claimRef:
    name: bmcpfs
    namespace: default
  csi:
    driver: bmcpfsplugin.csi.alibabacloud.com
    volumeAttributes:
      path: /
    volumeHandle: bmcpfs-xxxxx
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: bmcpfs
  namespace: default
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Ti
  volumeMode: Filesystem
  volumeName: bmcpfs
  1. 使用以下YAML创建一个DaemonSet,该DaemonSet需引用所有现有的PVC。
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: host-symlink-creator-daemonset
  namespace: default
  labels:
    app: host-symlink-creator
  # 保证Daemonset不被删除, 但是Pod仍有可能通过修改nodeAffinity触发删除
  finalizers:
  - finalizers.example.com/cleanup
spec:
  selector:
    matchLabels:
      app: host-symlink-creator
  template:
    metadata:
      labels:
        app: host-symlink-creator
    spec:
      containers:
        - name: symlink-manager
          image: busybox:1.35
          # 注入Pod的UID作为环境变量
          env:
            - name: POD_UID
              valueFrom:
                fieldRef:
                  fieldPath: metadata.uid
          # 核心逻辑:查找真实挂载点并创建软链接
          command: ["/bin/sh", "-c"]
          args:
            - |
              set -e
              echo "启动软链接创建脚本..."
              echo "当前 Pod UID: ${POD_UID}"

              # 定义Kubelet在容器内的挂载点
              KUBELET_PODS_DIR="/var/lib/kubelet/pods"
              HOST_MNT_DIR="/host-mnt"

              # 构造Pod在宿主机上的卷目录路径
              POD_VOLUMES_PATH="${KUBELET_PODS_DIR}/${POD_UID}/volumes/kubernetes.io~csi"

              echo "正在搜索挂载点于: ${POD_VOLUMES_PATH}"

              # 等待一小段时间,确保Kubelet已完成挂载
              sleep 5

              # 检查目录是否存在
              if [ ! -d "${POD_VOLUMES_PATH}" ]; then
                echo "错误: 找不到 Pod 卷目录 ${POD_VOLUMES_PATH}"
                exit 1
              fi
              
              # 查找真实的挂载点(通常名为 'mount' 的目录)
              # 对于只有一个CSI卷的Pod,这个find命令会返回唯一的结果
              SOURCE_HOST_PATH=$(find "${POD_VOLUMES_PATH}" -type d -name "mount" | head -n 1)

              if [ -z "${SOURCE_HOST_PATH}" ]; then
                  echo "错误: 在 ${POD_VOLUMES_PATH} 中未找到名为 'mount' 的挂载目录!"
                  exit 1
              fi
              
              echo "成功找到宿主机上的挂载点: ${SOURCE_HOST_PATH}"

              # 从路径中提取PV名称作为软链接的名称
              # 例如,从 /.../pvc-xxx-yyy/mount中提取pvc-xxx-yyy
              PV_NAME=$(basename $(dirname "${SOURCE_HOST_PATH}"))
              
              # 定义软链接在宿主机上的最终路径
              DEST_LINK_PATH="${HOST_MNT_DIR}/${PV_NAME}"

              echo "准备创建软链接: ${DEST_LINK_PATH} -> ${SOURCE_HOST_PATH}"

              # 检查并创建软链接(幂等性)
              if [ -L "${DEST_LINK_PATH}" ]; then
                  echo "软链接 ${DEST_LINK_PATH} 已存在。"
              elif [ -e "${DEST_LINK_PATH}" ]; then
                  echo "错误: ${DEST_LINK_PATH} 已存在但不是一个软链接!"
                  exit 1
              else
                  # 注意:我们创建的软链接,其源和目标都是相对于宿主机根目录的绝对路径
                  # 但我们是在容器内执行 ln 命令,所以路径需要是容器内的路径
                  ln -s "${SOURCE_HOST_PATH}" "${DEST_LINK_PATH}"
                  echo "软链接创建成功!"
              fi
              
              echo "初始化完成,容器进入休眠状态。"
              sleep infinity
          volumeMounts:
            # 将宿主机的/var/lib/kubelet挂载进来 (只读更安全)
            - name: host-kubelet-path
              mountPath: /var/lib/kubelet
              readOnly: true
            - name: pvc-for-trigger
              mountPath: /data
            # 将宿主机的/mnt挂载进来,用于创建软链接
            - name: host-mnt-storage
              mountPath: /host-mnt
      volumes:
        - name: pvc-for-trigger
          persistentVolumeClaim:
            claimName: bmcpfs
        # 定义宿主机Kubelet目录的挂载
        - name: host-kubelet-path
          hostPath:
            path: /var/lib/kubelet
            type: Directory
        # 定义宿主机mnt目录的挂载
        - name: host-mnt-storage
          hostPath:
            path: /mnt
            type: DirectoryOrCreate


重要

  • /mnt目录下(或其他自定义目录)里的软链接将在该Pod被删除之后失效,无法自动回收,您需要手动清理该目录下的软链接。
  • 由于该DamonSet将容器内部的挂载目录映射到了宿主机上,所以该DamonSet无法创建多个,您需要保证该DamonSet的存活。
  • 为了不影响现有服务,如果有序有新增的CPFS智算版文件系统对应的PVC/PV需要挂载,您需要创建新的DamonSet,而不是修改现有DamonSet。


  1. 使用以下YAML创建应用,并使用透出到节点的软链路径。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cpfs-test-hostpath
  labels:
    app: cpfs-test-hostpath
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cpfs-test
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: cpfs-test
    spec:
      tolerations:
        - effect: NoSchedule
          key: node-role.alibabacloud.com/lingjun
          operator: Exists
      containers:
      - name: nginx
        image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
          - name: pvc-cpfs
            mountPath: /data
      volumes:
        - name: pvc-cpfs
          hostPath:
            path: /mnt/${PV_NAME}


续步骤

后续当全部的CPFS智算版文件系统均已转为PVC挂载时,您需要清理过渡迁移方案创建的DamonSet(可能多个)。

  1. 确认节点上没有使用Hostpath挂载方式的Pod存活。
  2. 删除DamonSet。
  3. 在DamonSet对应的节点上,批量执行以下命令,以清理软链接。
find /mnt -xtype l -print -delete
  1. 迁移到终态迁移方案


目录
相关文章
|
1月前
|
传感器 数据采集 人工智能
衣服也能看病?智能织物正悄悄改变医疗的未来
衣服也能看病?智能织物正悄悄改变医疗的未来
67 0
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
ReasonRank:从关键词匹配到逻辑推理,排序准确性大幅超越传统方法
ReasonRank是一种创新段落重排系统,采用自动化数据合成与两阶段训练(监督微调+强化学习),在BRIGHT等测试中超越更大模型,显著提升信息检索中的推理能力。
113 0
ReasonRank:从关键词匹配到逻辑推理,排序准确性大幅超越传统方法
|
1月前
|
缓存 前端开发 Java
基于最新 Java 技术栈的在线任务管理系统开发实战详解
本项目基于最新Java技术栈开发在线任务管理系统,涵盖任务创建、分配、跟踪、统计等功能。采用Spring Boot 3.2.x、React 18、PostgreSQL 16等主流技术,详解项目架构设计、核心功能实现及部署流程,助力掌握现代Java全栈开发技能。
128 6
|
1月前
|
前端开发 Java API
2025 年 Java 全栈从环境搭建到项目上线实操全流程指南:Java 全栈最新实操指南(2025 版)
本指南涵盖2025年Java全栈开发核心技术,从JDK 21环境搭建、Spring Boot 3.3实战、React前端集成到Docker容器化部署,结合最新特性与实操流程,助力构建高效企业级应用。
437 1
|
存储 Kubernetes 数据可视化
|
1月前
|
人工智能 自然语言处理 Serverless
Vibecoding 新体验:实测 Qwen3 Coder 代码生成效果
Qwen3 Coder 是全球领先的开源编程大模型,具备强大的代码生成能力与1M超长上下文支持,适用于构建复杂应用。本文通过实际案例展示其在电商网站开发中的应用,并详解提示词设计、技术拆解与部署方案,探讨Agentic AI落地的挑战与经验。
902 13
|
5月前
|
人工智能 API
MCP协议的局限性
5年前,我把 AI 比喻为一种智能化的 API 网关,提出一种分治的思想,将一个大问题转换为若干可解的小问题,如今,这种思想正在 mcp 这种协议沿用。但目前来看,它的实现方式还是有点丑陋的,并且有一些问题。
|
6月前
|
存储 人工智能 缓存
DeepSeek 3FS解读与源码分析(1):高效训练之道
本文从设计文档和源码,深入对 3FS 在文件系统和 AI workload 方面做一系列的解读。如有错误欢迎指正。
|
11月前
|
缓存 Java 程序员
Java|SpringBoot 项目开发时,让 FreeMarker 文件编辑后自动更新
在开发过程中,FreeMarker 文件编辑后,每次都需要重启应用才能看到效果,效率非常低下。通过一些配置后,可以让它们免重启自动更新。
215 0
|
10月前
|
人工智能 自然语言处理 测试技术
利用Qwen-coder提升编程效率:代码生成、错误检测与重构建议
利用Qwen-coder提升编程效率:代码生成、错误检测与重构建议
735 2