K3s + Helm + CircleCI 实战:从 GitHub/GitLab 导入项目到 Docker Hub 多环境部署
K3s + Helm + CircleCI 实战:从 GitHub/GitLab 导入项目到 Docker Hub 多环境部署

适用场景:你已经有一台运行 K3s 的 ARM64 Linux 主机,希望把 GitHub 或 GitLab 项目导入 CircleCI,使用当前主机上的 CircleCI self-hosted runner 构建镜像,并通过 Helm 自动部署到 dev、main 或 master 环境。
本文基于实际项目:
zszweb/emailAccountsAdmin,同时保留原有 GitLab/zszDeploy 流程的可恢复能力。文中的密码、Token、kubeconfig 和私有仓库凭据均使用变量名或占位符,不包含真实值。
目录
- 一、最终架构
- 二、部署前提
- 1. 主机要求
- 2. 域名规划
- 三、初始化 K3s 主机
- 1. 设置主机名与内核参数
- 2. 安装 K3s
- 3. 安装 Helm
- 四、安装 Traefik、cert-manager 与 HTTPS 基础设施
- 1. 安装 cert-manager CRDs
- 2. 安装 cert-manager 控制器
- 3. 创建 ClusterIssuer
- 4. 创建 HTTPS 重定向 Middleware
- 5. HTTPS 生效检查
- 五、将 GitHub 或 GitLab 项目导入 CircleCI
- 1. GitHub 项目
- 2. GitLab 项目
- 3. 配置文件的职责边界
- 六、CircleCI Context 与变量
- 1. build Context
- 2. deploy Context
- 3. 密钥安全规则
- 七、self-hosted Container Runner
- 1. 检查 runner
- 2. ARM64 兼容
- 3. Kaniko 与 Docker daemon
- 八、CircleCI Pipeline 设计
- 1. 分支与动作
- 2. 镜像 tag 规则
- 3. validate 内容
- 九、项目 Helm Chart 结构
- 1. 动态 release 命名
- 2. 镜像拉取 Secret
- 3. 健康检查
- 十、暂停 GitLab/zszDeploy,切换到 CircleCI
- 1. 先确认 CircleCI 新流程
- 2. 禁用而不是删除 Webhook
- 3. 回滚旧流程
- 十一、首次上线与 release 改名迁移
- 1. 先部署新 release
- 2. 验证新资源
- 3. 再清理旧 release
- 4. 重复 Ingress 的风险
- 十二、常用运维检查
- 1. CircleCI 配置
- 2. Helm
- 3. Kubernetes
- 4. 域名与证书
- 十三、常见故障排查
- 1. CircleCI 找不到配置
- 2. Pipeline 只运行 validate,不构建镜像
- 3. Docker Hub 推送失败
- 4. Pod 为 ImagePullBackOff
- 5. Helm 报 ownership metadata 错误
- 6. Ingress 返回 502/503
- 7. cert-manager 不签发证书
- 十四、生产安全清单
- 十五、最终状态
一、最终架构
整个发布链路如下:
GitHub/GitLab Push ➔ CircleCI Pipeline ➔ self-hosted Container Runner ➔ Node.js 构建 ➔ Kaniko 构建并推送 Docker Hub ➔ Helm upgrade --install ➔ K3s Deployment/Service/Ingress ➔ Traefik + cert-manager 提供 HTTPS
本次项目的关键边界:
| 部分 | 当前方案 |
|---|---|
| Git 仓库 | GitLab:https://gitlab.com/zszweb/emailAccountsAdmin |
| CircleCI 项目 | emailAccountsAdmin |
| runner 主机 | us-arm-12g,当前 K3s 主机 |
| runner resource class | zszweb/k3s-ci |
| runner 架构 | ARM64 |
| 镜像仓库 | Docker Hub |
| 镜像地址 | docker.io/zszken/email-accounts-admin |
| Helm Chart | 仓库内 ./helm |
| dev 域名 | https://dev-email.zszweb.cn |
| production 域名 | https://email.zszweb.cn |
| 旧流程 | GitLab Push Webhook ➔ zszDeploy ➔ .zsz-ci.yml |
| 新流程 | CircleCI ➔ .circleci/config.yml |
二、部署前提
1. 主机要求
建议准备一台可以稳定访问公网的 Linux ARM64 主机,并满足:
- 已配置域名 DNS,域名指向主机公网 IP;
- 放行 TCP
80和443; - 具备 root 或 sudo 权限;
- 可以访问 GitHub、GitLab、CircleCI、Docker Hub、Let's Encrypt 和 npm registry;
- 主机时间同步正常;
- 不在仓库中保存 kubeconfig、Registry 密码或 CI Token。
2. 域名规划
本项目使用两个入口:
| 环境 | 域名 | 用途 |
|---|---|---|
| dev | dev-email.zszweb.cn | dev 分支自动部署 |
| production | email.zszweb.cn | main 或 master 分支发布 |
如果更换域名,需要同时修改 CircleCI 配置、Helm 参数、证书配置和 DNS。
三、初始化 K3s 主机
以下步骤整理自旧笔记:K3s + Helm + NPM 命令式部署文档。版本号建议在正式执行前再次确认;生产环境应固定经过验证的版本,避免直接使用未经测试的 latest。
1. 设置主机名与内核参数
hostnamectl set-hostname k3s-master
cat <<'EOF' >> /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.proxy_arp = 1
EOF
sysctl -p /etc/sysctl.conf
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.proxy_arp
如果 /etc/sysctl.conf 中已经存在这些参数,不要重复追加;应先确认最终值。
2. 安装 K3s
curl -sfL https://get.k3s.io | sh -s - \
--write-kubeconfig ~/.kube/config \
--write-kubeconfig-mode 600
验证服务、节点和 Pod:
systemctl status k3s --no-pager
kubectl get nodes -o wide
kubectl get pods -A
节点必须处于 Ready。如果 kubectl 无法连接,先检查 k3s 服务和 kubeconfig 路径。
3. 安装 Helm
ARM64 主机示例:
HELM_VERSION="v4.1.4"
wget "https://get.helm.sh/helm-${HELM_VERSION}-linux-arm64.tar.gz"
tar -zxvf "helm-${HELM_VERSION}-linux-arm64.tar.gz"
install -m 0755 linux-arm64/helm /usr/local/bin/helm
helm version
也可以使用系统包管理器或官方安装脚本,但生产环境建议固定版本并在升级前验证 Chart 渲染结果。
四、安装 Traefik、cert-manager 与 HTTPS 基础设施
K3s 默认提供 Traefik。项目的 Helm Ingress 使用:
ingressClassName: traefik;- cert-manager 的
ClusterIssuer; - HTTP 到 HTTPS 的 Traefik Middleware;
- Let's Encrypt HTTP-01 challenge。
1. 安装 cert-manager CRDs
CERT_MANAGER_VERSION="v1.20.2"
kubectl apply -f \
"https://github.com/cert-manager/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.crds.yaml"
kubectl get crds | grep cert-manager
2. 安装 cert-manager 控制器
只安装 CRDs 不够,还需要安装 cert-manager 控制器:
helm repo add jetstack https://charts.jetstack.io
helm repo update
kubectl create namespace cert-manager \
--dry-run=client -o yaml | kubectl apply -f -
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version "${CERT_MANAGER_VERSION}"
kubectl get pods -n cert-manager
正常情况下应看到 cert-manager、cert-manager-cainjector 和 cert-manager-webhook。
3. 创建 ClusterIssuer
创建 production-issuer.yaml:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ${LETSENCRYPT_EMAIL}
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
ingressClassName: traefik
Shell 环境变量不会被 Kubernetes YAML 自动替换。实际执行前可以用模板工具渲染,或把邮箱作为非敏感配置写入文件。不要把 DNS API Token 或其他私密凭据写进公开仓库。
kubectl apply -f production-issuer.yaml
kubectl get clusterissuer letsencrypt-prod
kubectl describe clusterissuer letsencrypt-prod
4. 创建 HTTPS 重定向 Middleware
创建 https-redirect.yaml:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-https
namespace: default
spec:
redirectScheme:
scheme: https
permanent: true
应用并检查:
kubectl apply -f https-redirect.yaml
kubectl get middleware -n default
kubectl describe middleware redirect-https -n default
5. HTTPS 生效检查
kubectl get ingress -A
kubectl get certificate,certificaterequest,order,challenge -A
curl -I http://dev-email.zszweb.cn
curl -kI https://dev-email.zszweb.cn
如果 HTTP-01 challenge 失败,优先检查 DNS、80 端口、Traefik Pod、IngressClass 和 cert-manager 日志。
五、将 GitHub 或 GitLab 项目导入 CircleCI
CircleCI 的项目导入方式取决于代码托管平台,但仓库中都应放置 .circleci/config.yml。
1. GitHub 项目
- 登录 CircleCI。
- 选择 GitHub 组织或个人账户。
- 授权 CircleCI GitHub App,或使用当前组织已有连接。
- 在 Projects 中找到目标仓库。
- 选择 Set Up Project。
- 确认配置文件路径为
.circleci/config.yml。 - 选择目标分支并运行第一次 Pipeline。
如果仓库没有配置文件,可以先提交最小配置;正式部署前应替换为项目真实的 build、push 和 deploy 流程。
2. GitLab 项目
本项目实际使用 GitLab.com:
https://gitlab.com/zszweb/emailAccountsAdmin
导入步骤:
- 在 CircleCI 中选择 GitLab.com 连接。
- 授权 CircleCI 访问目标 GitLab 组织或项目。
- 选择
zszweb/emailAccountsAdmin。 - 确认 CircleCI 读取仓库根目录的
.circleci/config.yml。 - 在 CircleCI 项目设置中确认 GitLab push 能触发 Pipeline。
- 先用功能分支验证
validate,再合并到dev。
CircleCI 通过 GitLab 集成读取代码,不需要把 GitLab 用户名、密码或个人 Token 写入 .circleci/config.yml。如果还要保留 GitLab Webhook 触发的旧系统,应单独管理 Webhook,不要把两套流程混在同一个脚本里。
3. 配置文件的职责边界
本项目同时存在两个文件:
| 文件 | 作用 | 当前处理 |
|---|---|---|
.circleci/config.yml | CircleCI 新流程 | 由 CircleCI 读取 |
.zsz-ci.yml | GitLab/zszDeploy 旧流程 | 保留,不删除、不修改 |
旧流程需要暂停时,只禁用 GitLab 中指向 zszDeploy 的 Push Webhook,不删除 .zsz-ci.yml,也不访问或处理 zszdeploy-server 仓库中的公开凭据和文件。
六、CircleCI Context 与变量
建议使用两个 Context(沿用现有 CI 兼容标识,暂不随仓库改名重命名):
emailaccoutsadmin-build:只绑定镜像构建任务;emailaccoutsadmin-deploy:只绑定 Kubernetes 部署任务。
1. build Context
DOCKERHUB_USERNAME
DOCKERHUB_TOKEN
VITE_INSFORGE_BASE_URL
VITE_INSFORGE_ANON_KEY
其中:
DOCKERHUB_USERNAME是 Docker Hub 用户名;DOCKERHUB_TOKEN是 Docker Hub Access Token,不建议使用账户密码;VITE_INSFORGE_*是前端构建时需要注入的公开运行配置,是否适合暴露给浏览器要遵循项目自身安全模型。
当前仓库配置中的非敏感默认值为:
REGISTRY=docker.io/zszken
REGISTRY_URL=docker.io
DEPOT_NAME_LOWER=email-accounts-admin
2. deploy Context
DOCKERHUB_USERNAME
DOCKERHUB_TOKEN
Kubernetes namespace 当前由配置固定为:
HELM_NAMESPACE=default
生产环境不需要把以下内容放入 Context:
KUBECONFIG_B64
HELM_OCI_USERNAME
HELM_OCI_PASSWORD
原因是:
- 当前 CircleCI runner 就在 K3s 主机内,部署任务使用任务 Pod 注入的 ServiceAccount Token 访问集群;
- 当前项目不发布 Helm Chart OCI,因此不需要 Helm OCI 凭据;
- 不把宿主机
/root/.kube/config复制到 CI,也不把完整 kubeconfig 编码成变量。
3. 密钥安全规则
- 不把真实 Token 写入 YAML、Markdown、Git commit、Issue 或 Pipeline 日志;
- 不在脚本中
echo密钥; - 不把 Docker config、kubeconfig 或 Secret YAML 上传为 artifact;
- 如果 Token 曾经粘贴到聊天、Issue 或日志,应立即轮换,并更新 CircleCI Context;
- Registry、Webhook 和 Git 仓库访问凭据均通过 CircleCI Environment Variables 或 Context 管理。
七、self-hosted Container Runner
本项目使用当前 K3s 主机上的 CircleCI Container Runner,而不是 CircleCI 托管的 machine executor。
1. 检查 runner
在 K3s 主机上:
kubectl get pods -A -o wide | grep -Ei 'circleci|runner'
当前 runner 使用的 resource class:
zszweb/k3s-ci
CircleCI job 中应配置:
docker:
- image: cimg/base:current
resource_class: zszweb/k3s-ci
2. ARM64 兼容
脚本根据 runner 架构下载对应的 kubectl:
case "$(uname -m)" in
x86_64) KUBECTL_ARCH=amd64 ;;
aarch64|arm64) KUBECTL_ARCH=arm64 ;;
*) echo "Unsupported runner architecture: $(uname -m)" >&2; exit 1 ;;
esac
Kaniko 构建阶段同样根据架构选择镜像和执行器。不要默认把 ARM64 runner 当作 amd64 主机使用。
3. Kaniko 与 Docker daemon
当前构建任务使用 privileged runner 容器中的 Kaniko:
- 不依赖 Docker daemon;
- 不使用
setup_remote_docker; - 在 Kaniko Docker config 中写入 Docker Hub auth;
- 使用
--destination推送最终镜像。
如果构建失败,优先检查 runner 是否允许 privileged、/kaniko 是否可执行、Kaniko context 是否包含 Dockerfile 和 nginx.conf,以及 Docker Hub auth 是否写入正确位置。
八、CircleCI Pipeline 设计
当前 .circleci/config.yml 的工作流为:
validate
│
└── build_and_push
├── dev ──> deploy_dev
└── main/master ──> deploy_production
1. 分支与动作
| 分支 | validate | 构建并推送 Docker 镜像 | Helm 部署 |
|---|---|---|---|
dev | 是 | 是 | email-accounts-admin-dev |
main | 是 | 是 | email-accounts-admin-main |
master | 是 | 是 | email-accounts-admin-master |
| 其他分支 | 是 | 否 | 否 |
2. 镜像 tag 规则
镜像 tag 为:
<小写分支名>-<Commit SHA 前 7 位>
例如:
docker.io/zszken/email-accounts-admin:dev-c9f1645
这种 tag 能同时表达发布分支和代码版本,便于回滚与排查。
3. validate 内容
本地可以先运行:
circleci config validate .circleci/config.yml
npm ci
npm run build
helm lint ./helm
helm template email-accounts-admin-dev ./helm \
--set DEPOT_NAME_LOWER=email-accounts-admin \
--set image.tag=dev-local \
--set url=dev-email.zszweb.cn
helm template email-accounts-admin-main ./helm \
--set DEPOT_NAME_LOWER=email-accounts-admin \
--set image.tag=main-local \
--set url=email.zszweb.cn
先通过渲染检查,再让 Pipeline 接触真实集群,可以减少 Helm YAML、域名和参数错误。
九、项目 Helm Chart 结构
本项目 Chart 位于:
helm/
├── Chart.yaml
├── values.yaml
└── templates/
├── _helpers.tpl
├── emailAccoutsAdmin-deploy.yaml(历史模板文件名,暂不改动)
├── emailAccoutsAdmin-ingress.yaml(历史模板文件名,暂不改动)
├── emailAccoutsAdmin-svc.yaml(历史模板文件名,暂不改动)
└── register.key.yaml
1. 动态 release 命名
资源名称由 .Release.Name 推导:
email-accounts-admin-dev-app
email-accounts-admin-main-app
email-accounts-admin-master-app
Deployment、Service、Ingress 同时带有:
app.kubernetes.io/instance: <Release.Name>
app.kubernetes.io/name: <Release.Name>-app
app.kubernetes.io/managed-by: Helm
这使 dev 与 main 能够在同一 namespace 并行运行。
2. 镜像拉取 Secret
CircleCI 部署前会幂等更新 Docker Hub pull secret:
kubectl -n "$HELM_NAMESPACE" create secret docker-registry \
dockerhubkey-email-accouts-admin \
--docker-server=https://index.docker.io/v1/ \
--docker-username="$DOCKERHUB_USERNAME" \
--docker-password="$DOCKERHUB_TOKEN" \
--dry-run=client -o yaml | kubectl apply -f -
Helm 使用已有 Secret:
--set imagePullSecret.existingName=dockerhubkey-email-accouts-admin
Chart 默认不会把镜像凭据写进仓库;imagePullSecret.create 只有在明确需要由 Chart 创建 Secret 时才启用。
3. 健康检查
Deployment 配置了 readiness probe 和 liveness probe。修改镜像或端口后,必须同时检查:
kubectl -n default rollout status deploy/email-accounts-admin-dev-app
kubectl -n default get pods -l app.kubernetes.io/instance=email-accounts-admin-dev
kubectl -n default get endpoints/email-accounts-admin-dev-app
十、暂停 GitLab/zszDeploy,切换到 CircleCI
这是一个可逆切换,不删除旧流程。
1. 先确认 CircleCI 新流程
建议按以下顺序:
- 提交
.circleci/config.yml到功能分支; - 确认
validate成功; - 合并到
dev; - 确认
build_and_push和deploy_dev成功; - 打开 dev 域名确认页面可访问;
- 再暂停 GitLab 中指向 zszDeploy 的 Push Webhook。
2. 禁用而不是删除 Webhook
打开:
https://gitlab.com/zszweb/emailAccountsAdmin/-/hooks
找到 URL 指向 zszDeploy 的 Webhook:
- 只编辑这一条 Webhook;
- 将其设置为 inactive/disabled;
- 不删除 Webhook;
- 不修改其他 Webhook;
- 刷新页面,确认它仍然存在但处于禁用状态。
这样可以保证将来需要恢复 zszDeploy 时,只需要重新启用原 Webhook。
3. 回滚旧流程
如果 CircleCI 出现持续失败:
- 暂停 CircleCI 的生产部署;
- 确认没有正在执行的生产 Pipeline;
- 在 GitLab Webhooks 页面重新启用 zszDeploy Webhook;
- 保持
.zsz-ci.yml不变; - 观察下一次 GitLab push 是否由旧流程接管。
不要为了回滚去删除 CircleCI 配置或清理 zszdeploy-server。
十一、首次上线与 release 改名迁移
如果旧集群已经存在:
emailaccountsadmin-dev
emailaccountsadmin-main
而新配置希望使用:
email-accounts-admin-dev
email-accounts-admin-main
email-accounts-admin-master
不要直接修改或删除旧 release。推荐执行“新建、验证、清理”的迁移顺序。
1. 先部署新 release
CircleCI 自动部署 dev 时使用:
helm upgrade --install email-accounts-admin-dev ./helm \
--namespace default \
--set DEPOT_NAME_LOWER=email-accounts-admin \
--set image.repository=docker.io/zszken \
--set imagePullSecret.existingName=dockerhubkey-email-accouts-admin \
--set image.tag=dev-<commit-sha> \
--set url=dev-email.zszweb.cn
2. 验证新资源
helm status email-accounts-admin-dev -n default
kubectl -n default rollout status deploy/email-accounts-admin-dev-app
kubectl -n default get deploy,svc,ingress,pods \
-l app.kubernetes.io/instance=email-accounts-admin-dev
curl -kfsS -o /dev/null -w '%{http_code}\n' \
https://dev-email.zszweb.cn/
3. 再清理旧 release
确认新 Pod、Service、Ingress 和域名都正常后,才执行:
helm uninstall emailaccountsadmin-dev -n default
生产 main 同理,但应先部署并验证 email-accounts-admin-main,再清理 emailaccountsadmin-main。
4. 重复 Ingress 的风险
旧、新 release 同时存在时,如果两者使用同一个 host,例如 email.zszweb.cn,Traefik 可能出现:
- 503 Service Unavailable;
- 502 Bad Gateway;
- 路由指向不确定;
- 新旧服务之间的证书或 Middleware 冲突。
因此“新 release 部署完成”不等于“迁移完成”。必须在短时间内完成验证和旧 release 清理,然后重新访问域名确认返回 200。
如果新 release 使用全新的 TLS Secret,证书签发可能需要等待;也可以在确认安全的前提下复用已有、未过期且域名匹配的 TLS Secret。
十二、常用运维检查
1. CircleCI 配置
circleci config validate .circleci/config.yml
2. Helm
helm list -A
helm status email-accounts-admin-dev -n default
helm get values email-accounts-admin-dev -n default -a
helm history email-accounts-admin-dev -n default
3. Kubernetes
kubectl get nodes -o wide
kubectl get pods -A
kubectl -n default get deploy,svc,ingress,pods -o wide
kubectl -n default describe pod <pod-name>
kubectl -n default logs deploy/email-accounts-admin-dev-app --tail=100
kubectl -n default get secret
4. 域名与证书
kubectl get certificate,certificaterequest,order,challenge -A
kubectl describe certificate -n default
kubectl -n kube-system logs -l app.kubernetes.io/name=traefik --since=10m
curl -I http://dev-email.zszweb.cn
curl -kI https://dev-email.zszweb.cn
十三、常见故障排查
1. CircleCI 找不到配置
确认:
- 文件路径是仓库根目录下的
.circleci/config.yml; - GitLab/GitHub 项目连接正确;
- CircleCI 使用的分支包含该文件;
- YAML 能通过
circleci config validate。
2. Pipeline 只运行 validate,不构建镜像
这是预期行为:当前配置只对 main、master、dev 执行 build_and_push。功能分支只做验证,合并到 dev 后才会构建和部署。
3. Docker Hub 推送失败
检查:
DOCKERHUB_USERNAME
DOCKERHUB_TOKEN
以及 Token 是否具备目标仓库的 push 权限。不要在日志中打印 Token。若 Token 已泄露,先在 Docker Hub 轮换,再更新 CircleCI Context。
4. Pod 为 ImagePullBackOff
kubectl -n default get secret dockerhubkey-email-accouts-admin
kubectl -n default describe pod <pod-name>
kubectl -n default get deploy/<release-name>-app \
-o jsonpath='{.spec.template.spec.imagePullSecrets}'
检查镜像地址、tag、Secret namespace 和 Docker Hub Token 权限是否一致。
5. Helm 报 ownership metadata 错误
典型原因是旧 release 与新 release 争用同名资源。处理顺序:
- 不要强行覆盖生产资源;
- 检查
helm list -A; - 使用
.Release.Name动态命名的 Chart; - 镜像 pull secret 优先使用已有 Secret;
- 确认新 release 后再清理旧 release。
6. Ingress 返回 502/503
按顺序检查:
kubectl -n default get ingress
kubectl -n default get svc,endpoints
kubectl -n default get pods -o wide
kubectl -n kube-system logs -l app.kubernetes.io/name=traefik --since=10m
如果旧、新 release 同时绑定同一域名,优先清理已经验证通过的旧 release。若 Service 没有 endpoint,则继续检查 Pod readiness、Service selector 和容器监听端口。
7. cert-manager 不签发证书
kubectl get clusterissuer letsencrypt-prod
kubectl get certificate,order,challenge -A
kubectl describe challenge -A
kubectl -n cert-manager logs deploy/cert-manager --tail=100
常见原因是 DNS 未生效、80 端口未放行、IngressClass 错误、HTTP 被其他代理拦截,或只安装了 CRDs 而没有安装 cert-manager 控制器。
十四、生产安全清单
发布前逐项确认:
- [ ] CircleCI 项目连接的是正确的 GitHub/GitLab 仓库;
- [ ]
.circleci/config.yml通过本地验证; - [ ]
npm run build成功; - [ ]
helm lint和helm template成功; - [ ] build/deploy Context 已创建且变量名正确;
- [ ] Token 没有出现在仓库和日志;
- [ ] self-hosted runner 为在线状态;
- [ ] runner 架构与镜像构建目标匹配;
- [ ]
circleci-deployer具备目标 namespace 的最小权限; - [ ] Docker Hub pull secret 位于目标 namespace;
- [ ] DNS、80/443 和 Traefik 正常;
- [ ] cert-manager ClusterIssuer 为 Ready;
- [ ] 旧 zszDeploy Webhook 已按计划禁用但没有删除;
- [ ] 已记录回滚步骤和旧 release 名称;
- [ ] 生产发布只从
main或master触发。
十五、最终状态
本次项目迁移后的状态为:
GitLab zszweb/emailAccountsAdmin
│
├── .zsz-ci.yml(保留,旧流程可恢复)
└── .circleci/config.yml
│
├── dev ➔ docker.io/zszken/email-accounts-admin:dev-<sha>
│ ➔ email-accounts-admin-dev
│ ➔ dev-email.zszweb.cn
│
└── main/master ➔ docker.io/zszken/email-accounts-admin:<branch>-<sha>
➔ email-accounts-admin-main/master
➔ email.zszweb.cn
核心原则只有三条:
- 代码仓库只保存流程,不保存凭据;
- 新 release 先验证,再删除旧 release;
- 旧 zszDeploy 只暂停,不删除,确保能够回滚。
当这三条边界保持清晰时,K3s、Helm、CircleCI 和 GitLab/GitHub 的职责就能相互解耦,后续新增项目也可以复用同一套部署模型。