适用版本: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 导出原则
- 仅
kubectl get,只读,不修改集群;
- 按 Deployment 名称分子目录,关联资源放入同一目录;
- 跳过
replicas=0 的 Deployment;
- 关联资源发现顺序:
- 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 需清洗字段及说明
| 字段 |
清洗动作 |
原因 |
metadata.resourceVersion |
删除 |
源集群 etcd 版本号;携带会导致 apply 冲突 |
metadata.uid |
删除 |
源集群唯一标识;新集群须分配新 UID |
metadata.creationTimestamp |
删除 |
源集群创建时间;非声明式配置 |
metadata.generation |
删除 |
控制器世代计数;源集群状态,不可移植 |
metadata.managedFields |
删除 |
字段管理历史;与源集群绑定 |
metadata.selfLink |
删除 |
已废弃;含源 API 路径 |
metadata.ownerReferences |
删除 |
指向源集群父对象;新集群关系不同 |
metadata.finalizers |
删除 |
可能阻碍新集群创建或删除 |
| 字段 |
清洗动作 |
原因 |
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
预览:对单个文件执行相同逻辑,打印 namespace、image、Ingress host 变更前后值,不写 import/。
5.4 清洗产出
| 路径 |
说明 |
import/_namespaces/namespace-<name>.yaml |
目标集群需创建的 namespace |
import/<deploy-name>/*.yaml |
清洗后的业务资源 |
6. 导入步骤
6.1 导入前检查
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 顺序
- Namespace
- ServiceAccount → Secret → ConfigMap
- Service
- Deployment
- Ingress → HPA → PDB
单目录 apply 失败时,按上述顺序逐个资源 apply。