Kubernetes (Containerd) 存储目录迁移指南

作者:Administrator 发布时间: 2025-11-29 阅读量:3 评论数:0

1. 背景与目标

  • 背景:Kubernetes 节点默认将容器镜像、容器读写层存储在 /var/lib/containerd(通常位于系统根分区 /)。随着业务运行,根分区容易被镜像和日志占满。

  • 目标:将 Containerd 的存储路径迁移到空间更大的数据盘(例如 /root/data/k8s/containerd),并在不丢失现有镜像的前提下恢复服务。

  • 环境:Kubernetes + Containerd (CRI)。

2. 风险提示

  • 业务中断:此操作需要停止 K8s 节点服务,业务会发生驱逐或中断,请在维护窗口进行。

  • 数据备份:虽然是无损迁移,但在执行 rm 操作前,请务必确认新目录数据已同步完成。


3. 操作步骤

第一步:彻底停止服务与清理进程

这是最关键的一步。简单的 systemctl stop 往往无法停止底层的 shim 进程,导致文件系统挂载点依然被占用,进而导致数据迁移不一致。

  1. 停止守护进程

    systemctl stop kubelet
    systemctl stop containerd
    

强制清理残留进程(重要): Containerd 的 shim 进程可能还在运行,必须将其杀掉以释放文件句柄。

# 杀掉所有容器垫片进程
killall containerd-shim-runc-v2 2>/dev/null
# 或者
pkill -f containerd-shim
  1. 验证挂载是否卸载: 执行 df -h,确保列表中不再包含 /run/containerd/io.containerd.../var/lib/kubelet/pods... 的挂载项。

    • 如果依然存在顽固挂载,建议直接重启服务器 (Reboot) 后再进行下一步,这是最安全的清理方式。

第二步:数据同步 (无损迁移)

将旧数据完整复制到新磁盘,保持权限和属性不变。

  1. 创建新目录

    mkdir -p /root/data/k8s/containerd
    
  2. 同步数据: 使用 rsync 进行增量同步。

    # 注意路径写法:源目录末尾带斜杠,表示同步目录下的内容
    rsync -avP /var/lib/containerd/ /root/data/k8s/containerd/
    

第三步:修改 Containerd 配置文件

  1. 备份配置文件

    cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
    
  2. 编辑配置

    vim /etc/containerd/config.toml
    

    修改 root 字段指向新路径。注意不要修改 state 字段

    # 修改 root 为新路径 (持久化数据)
    root = "/root/data/k8s/containerd"
    
    # 保持 state 不变 (内存运行状态)
    state = "/run/containerd"
    

第四步:清理旧状态并启动

为了防止 Containerd 读取旧的运行状态(Metadata)导致与新数据路径冲突,建议清理临时状态目录。

  1. 清理临时状态

    rm -rf /run/containerd/*
    
  2. 启动 Containerd

    Bash

    systemctl start containerd
    systemctl status containerd
    # 确保状态为 Active (running)
    
  3. 启动 Kubelet

    systemctl start kubelet
    

4. 验证与生效(关键)

验证节点状态

在主控节点执行:

kubectl get nodes
# 状态应恢复为 Ready

验证存储空间 (Pod 重建)

注意:这是最容易产生误解的地方。

  • 现象:服务重启后,进入旧的 Pod 执行 df -h,发现根目录大小依然是旧磁盘的大小(例如 116G)。

  • 原因:旧 Pod 使用的是迁移前创建的 OverlayFS 快照(Snapshot),它仍然绑定在旧的文件系统视图上。

  • 解决方案:必须删除并重建 Pod,让 Containerd 在新路径下为容器分配新的读写层。

操作演示

# 1. 此时进入旧 Pod 查看,空间未变
kubectl exec -it <pod-name> -- df -h  # 显示 116G

# 2. 删除 Pod (触发重建)
kubectl delete pod <pod-name>

# 3. 等待新 Pod 启动后再次查看
kubectl exec -it <new-pod-name> -- df -h # 显示 916G (成功)

5. 后续清理

在系统稳定运行 1-2 天,确认所有业务 Pod 重建后均无异常,且新目录下有数据写入,可以删除旧数据释放空间。

rm -rf /var/lib/containerd

6. 常见问题排查 (FAQ)

Q1: 为什么停止服务后 df -h 还能看到很多挂载点? A: 这是因为 containerd-shim 进程由 systemd 托管脱离了主进程。必须执行 killall containerd-shim-runc-v2 或重启服务器来释放挂载。切勿在挂载未清理时进行 rsync,会导致数据损坏。

Q2: 为什么我看容器里的 / 变大了,但某个目录还是旧磁盘大小? A: 检查该目录是否是 emptyDir 卷或 HostPath。Kubelet 管理的卷默认存储在 /var/lib/kubelet,本次迁移只迁移了 Containerd (镜像/容器层),未迁移 Kubelet 目录。通常这不影响使用,除非你的应用在临时卷里写海量数据。

Q3: 启动 containerd 失败,日志提示 "invalid argument" 或权限错误? A: 检查 /etc/containerd/config.toml 语法,特别是 root 路径是否正确。同时确保 /run/containerd 目录已被清空,防止旧状态干扰。

评论