igozhang

——

    K8s YAML 文件导入导出规范及步骤

    适用版本:Kubernetes v1.24.6 / Sealos / Ubuntu 20.04.6
    编写日期:2026-07-04


    1. 文档范围

    本规范定义业务 YAML 的 导出 → 清洗 → 导入 流程,适用于 K8s v1.24.6 集群指定业务 namespace 的跨基地复刻。具体 namespace、Deployment 名称、域名映射由实施方按源/目标环境自行配置。


    2. ENV 环境要求

    2.1 操作系统

    项目 版本
    发行版 Ubuntu 20.04.6 LTS
    内核 5.4.0-216-generic

    2.2 容器与 K8s 运行时

    组件 版本
    Docker Engine 25.0.5
    kubelet v1.24.6
    kubectl v1.24.6
    Kustomize v4.5.4

    2.3 Kubernetes 平台组件

    组件 版本
    Kubernetes 1.24.6
    etcd 3.5.3-0
    CoreDNS 1.8.6
    metrics-server 0.6.4
    Calico 3.26.5
    ingress-nginx 1.8.1
    cert-manager 1.12.13
    Rancher 2.6.9
    Harbor 2.8.2
    NFS Subdir Provisioner 4.0.2
    lvscare (Sealos) 4.3.7

    2.4 中间件(业务依赖)

    组件 版本
    MySQL 8.4.5-debian-12-r0
    Nacos 2.2.1
    RocketMQ 4.9.4
    RocketMQ Dashboard 1.0.0

    2.5 工具

    工具 用途
    kubectl 导出、校验、导入
    python3 + PyYAML 解析/改写 YAML
    bash / grep / find 批量处理与校验

    3. 目录与命名规范

    3.1 工作目录

    /data/pkgs/yaml/
    ├── export/                 # 原始导出
    │   └── <deploy-name>/
    └── import/                 # 清洗后可 apply
        ├── _namespaces/
        └── <deploy-name>/
    

    执行前须 mkdir -p 确保目录存在。

    3.2 业务 Namespace 策略

    类型 导出条件 import 处理
    常规业务 ns spec.replicas > 0 保持不变或按映射表替换
    待废弃 ns spec.replicas > 0 合并至目标 ns(见 §5.2 F)

    不导出 spec.replicas == 0 的 Deployment。

    3.3 单 Deploy 子目录应含资源

    文件模式 资源
    deployment.yaml Deployment(必须)
    service-*.yaml Service
    ingress-*.yaml Ingress
    configmap-*.yaml ConfigMap
    secret-*.yaml Secret
    serviceaccount-*.yaml ServiceAccount
    hpa-*.yaml HPA
    poddisruptionbudget-*.yaml PDB

    4. 导出步骤

    4.1 前置检查

    在 Master 节点执行:

    mkdir -p /data/pkgs/yaml/export /data/pkgs/yaml/import
    kubectl cluster-info
    for namespace in ${NAMESPACE_LIST}; do
      kubectl get deployment -n "${namespace}" \
        -o custom-columns=NAME:.metadata.name,REPLICAS:.spec.replicas --no-headers
    done
    python3 -c "import yaml; print('OK')"
    

    ${NAMESPACE_LIST} 为待导出的业务 namespace 列表,由实施方定义。

    4.2 导出原则

    1. kubectl get,只读,不修改集群;
    2. 按 Deployment 名称分子目录,关联资源放入同一目录;
    3. 跳过 replicas=0 的 Deployment;
    4. 关联资源发现顺序:
      • Deployment label selector → Service、PDB;
      • Deployment volumes / env / envFrom → ConfigMap、Secret、ServiceAccount;
      • HPA scaleTargetRef.name → HPA;
      • Ingress backend.service.name → Ingress。

    4.3 执行导出

    对每个 replicas > 0 的 Deployment,写入 export/<deploy-name>/

    DEPLOY_NAME="<deploy-name>"
    NAMESPACE="<namespace>"
    OUT_DIR="/data/pkgs/yaml/export/${DEPLOY_NAME}"
    mkdir -p "${OUT_DIR}"
    
    kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" -o yaml \
      > "${OUT_DIR}/deployment.yaml"
    
    SELECTOR=$(kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" \
      -o jsonpath='{range $k,$v := .spec.selector.matchLabels}{printf "%s=%s," $k $v}{end}' \
      | sed 's/,$//')
    
    for kind in service poddisruptionbudget; do
      kubectl get "${kind}" -n "${NAMESPACE}" -l "${SELECTOR}" -o name 2>/dev/null \
        | while read -r obj; do
            k="${obj%%/*}"
            n="${obj#*/}"
            kubectl get "${k}" "${n}" -n "${NAMESPACE}" -o yaml \
              > "${OUT_DIR}/${k}-${n}.yaml"
          done
    done
    

    批量导出:对外层 ${NAMESPACE_LIST} 与 Deployment 列表做双重循环,原理同上。

    4.4 导出验收

    find /data/pkgs/yaml/export -mindepth 1 -maxdepth 1 -type d | wc -l
    find /data/pkgs/yaml/export -name 'deployment.yaml' | wc -l
    

    子目录数应等于 deployment.yaml 数量,且等于 replicas>0 的 Deployment 总数。


    5. 清洗规范

    5.1 清洗原理与过程

    从集群导出的 YAML 是某一集群某一时刻的快照,除业务声明(副本数、镜像 Tag、端口、资源配置)外,还混有 etcd 对象 ID、运行时 status、平台注入注解及源环境域名等不可移植信息。清洗即在本地将这些内容与目标环境配置分离:用 PyYAML 把每个文件解析为对象树,递归删除集群绑定字段与只读段,再按 namespace 映射表和域名替换表改写字符串,最后序列化写入 import/。全程不访问 API Server;kubectl apply 仅发生在导入阶段。建议先对样本文件做预览比对,确认 namespace、镜像仓库、Ingress 域名等关键字段无误后再批量写盘。

    5.2 需清洗字段及说明

    A. metadata 集群绑定字段(必须删除)

    字段 清洗动作 原因
    metadata.resourceVersion 删除 源集群 etcd 版本号;携带会导致 apply 冲突
    metadata.uid 删除 源集群唯一标识;新集群须分配新 UID
    metadata.creationTimestamp 删除 源集群创建时间;非声明式配置
    metadata.generation 删除 控制器世代计数;源集群状态,不可移植
    metadata.managedFields 删除 字段管理历史;与源集群绑定
    metadata.selfLink 删除 已废弃;含源 API 路径
    metadata.ownerReferences 删除 指向源集群父对象;新集群关系不同
    metadata.finalizers 删除 可能阻碍新集群创建或删除

    B. metadata 临时注解(必须删除)

    字段 清洗动作 原因
    metadata.annotations[kubectl.kubernetes.io/last-applied-configuration] 删除 上次 apply 快照;易引发三路合并冲突
    metadata.annotations[deployment.kubernetes.io/revision] 删除 Deployment 滚动 revision;新集群从 1 开始

    C. 平台运行时注解(必须删除)

    字段 清洗动作 原因
    metadata.annotations[field.cattle.io/publicEndpoints] 删除 Rancher 运行时 JSON,含源集群节点 IP;apply 后由平台重建

    D. 资源 status 段(必须删除)

    字段 清洗动作 原因
    顶层 status 删除 运行时状态;只读,apply 不接受客户端写入

    E. Service 集群分配字段(必须删除)

    字段 清洗动作 原因
    spec.clusterIP / spec.clusterIPs 删除 源集群 ClusterIP;新集群须重新分配
    spec.ipFamilies / spec.ipFamilyPolicy 删除 随 ClusterIP 一并重建
    status.loadBalancer.ingress 删除 已分配的外部地址;运行时状态

    F. Namespace 映射(按目标架构替换)

    范围 清洗动作 原因
    metadata.namespace 源 ns → 目标 ns 新集群 namespace 规划与源集群不同
    所有字符串值中的源 ns 名 同步替换 ConfigMap、平台注解 JSON 等仍引用旧 ns 名,不替换会导致配置与路由失效

    实施前须制定 namespace 映射表(含待废弃 ns 合并规则),对映射表中的源名做全文件、全字段替换。

    G. 域名与镜像仓库(按目标基地替换)

    范围 说明 原因
    镜像 image 字段 源 registry → 目标 registry 新基地镜像仓库地址不同
    Ingress spec.rules[].host 源域名 → 目标域名 入口 DNS 随基地变更
    Ingress spec.tls[].hosts 同步替换 须与 rules.host 一致
    环境变量 / ConfigMap 中的 URL 同步替换 应用内部地址依赖域名

    实施前须制定 域名 / registry 替换表

    H. 保留不清洗的字段

    字段 原因
    spec.replicas 业务副本配置
    镜像 Tag 版本标识,跨集群一致
    spec.selector / labels Service/PDB 关联所必需
    spec.containers 资源配置 业务运行参数
    Secret / ConfigMap 业务数据(除 ns、域名外) 业务配置

    5.3 清洗步骤

    EXPORT_DIR="/data/pkgs/yaml/export"
    IMPORT_DIR="/data/pkgs/yaml/import"
    mkdir -p "${IMPORT_DIR}"
    
    for deploy_dir in "${EXPORT_DIR}"/*/; do
      deploy_name=$(basename "${deploy_dir}")
      mkdir -p "${IMPORT_DIR}/${deploy_name}"
      for yaml_file in "${deploy_dir}"/*.yaml; do
        [ -f "${yaml_file}" ] || continue
        python3 - "${yaml_file}" "${IMPORT_DIR}/${deploy_name}/$(basename "${yaml_file}")" <<'PY'
    # load yaml → drop §5.2 A–E → replace ns/domain per mapping table → dump
    import sys, yaml
    src, dst = sys.argv[1], sys.argv[2]
    # ...
    PY
      done
    done
    
    mkdir -p "${IMPORT_DIR}/_namespaces"
    for ns in ${TARGET_NAMESPACE_LIST}; do
      printf 'apiVersion: v1\nkind: Namespace\nmetadata:\n  name: %s\n' "${ns}" \
        > "${IMPORT_DIR}/_namespaces/namespace-${ns}.yaml"
    done
    
    grep -r "${SOURCE_NS_PATTERN}"     "${IMPORT_DIR}" --include='*.yaml' | wc -l
    grep -r "${SOURCE_REGISTRY_PATTERN}" "${IMPORT_DIR}" --include='*.yaml' | wc -l
    

    预览:对单个文件执行相同逻辑,打印 namespaceimage、Ingress host 变更前后值,不写 import/

    5.4 清洗产出

    路径 说明
    import/_namespaces/namespace-<name>.yaml 目标集群需创建的 namespace
    import/<deploy-name>/*.yaml 清洗后的业务资源

    6. 导入步骤

    6.1 导入前检查

    • import 中源 namespace、源 registry/域名为 0 残留
    • 目标镜像仓库可拉取全部业务镜像
    • Namespace YAML 已生成

    6.2 执行导入

    在新集群 Master 节点:

    IMPORT_DIR="/data/pkgs/yaml/import"
    DEPLOY_NAME="<deploy-name>"
    NAMESPACE="<namespace>"
    
    kubectl apply --dry-run=client -f "${IMPORT_DIR}/_namespaces/"
    kubectl apply --dry-run=client -f "${IMPORT_DIR}/${DEPLOY_NAME}/"
    
    kubectl apply -f "${IMPORT_DIR}/_namespaces/"
    for deploy_dir in "${IMPORT_DIR}"/*/; do
      base=$(basename "${deploy_dir}")
      [ "${base}" = "_namespaces" ] && continue
      kubectl apply -f "${deploy_dir}"
    done
    
    kubectl get deployment,pods -n "${NAMESPACE}"
    

    6.3 推荐 apply 顺序

    1. Namespace
    2. ServiceAccount → Secret → ConfigMap
    3. Service
    4. Deployment
    5. Ingress → HPA → PDB

    单目录 apply 失败时,按上述顺序逐个资源 apply。

    MP3