如何在GitLab流水线中配置按需Kubernetes部署用于CD人工验收?
你的思路完全可行,绝非理想化!这是预发布验收的标准实践
你的想法其实是CI/CD流程里预发布环境动态部署+人工审批的典型场景,很多团队都在实际落地,完全不是空想。我来给你拆解具体的实现路径和注意事项:
核心逻辑梳理
咱们的目标是:
- 每个GitLab流水线触发时,自动创建一个独立的临时K8s部署(带唯一访问域名)
- 暂停流水线,等待人工验收(验收人员通过专属URI访问应用)
- 验收通过/不通过后,自动销毁这个临时部署;或者超时自动清理,避免资源浪费
具体落地步骤
1. GitLab CI 流水线阶段配置
首先把流水线拆分成几个关键阶段,下面是简化版的配置示例:
stages: - build - deploy-preview - manual-approval - destroy-preview - deploy-production # 构建镜像(你已有成熟流程,这里略过细节) build-job: stage: build script: - docker build -t my-app:${CI_PIPELINE_ID} . - docker push my-registry/my-app:${CI_PIPELINE_ID} # 部署临时预览环境 deploy-preview: stage: deploy-preview image: bitnami/kubectl:latest script: # 创建专属Namespace(资源隔离更彻底,可选) - kubectl create namespace preview-${CI_PIPELINE_ID} || true # 部署应用:用CI_PIPELINE_ID做唯一标识,确保每个流水线资源独立 - kubectl -n preview-${CI_PIPELINE_ID} apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: my-app-preview spec: replicas: 1 selector: matchLabels: app: my-app-preview template: metadata: labels: app: my-app-preview spec: containers: - name: my-app image: my-registry/my-app:${CI_PIPELINE_ID} ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-app-preview-svc spec: selector: app: my-app-preview ports: - port: 80 targetPort: 80 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-app-preview-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: pipeline-${CI_PIPELINE_ID}.git.mydomain.com http: paths: - path: / pathType: Prefix backend: service: name: my-app-preview-svc port: number: 80 EOF # 绑定GitLab环境,方便后续管理和查看 environment: name: preview/${CI_PIPELINE_ID} url: https://pipeline-${CI_PIPELINE_ID}.git.mydomain.com on_stop: destroy-preview # 人工验收环节:必须手动触发才能继续流程 manual-approval: stage: manual-approval script: - echo "请访问 ${CI_ENVIRONMENT_URL} 进行验收,完成后点击继续/拒绝" when: manual allow_failure: false # 设置为false时,必须验收通过才能进入后续生产部署阶段 # 销毁临时预览环境(自动触发:验收通过后,或环境超时) destroy-preview: stage: destroy-preview image: bitnami/kubectl:latest script: - kubectl delete namespace preview-${CI_PIPELINE_ID} || true environment: name: preview/${CI_PIPELINE_ID} action: stop when: manual # 也可设为always,不管验收结果都销毁;或用GitLab环境过期自动触发
2. 实现“仅访问时启动”的资源优化
如果想让临时部署平时休眠(副本数为0),有访问请求时再自动启动,可以用KEDA(Kubernetes Event-driven Autoscaling):
- 给Deployment配置最小副本数为0,最大为1
- 用KEDA的HTTP触发器(基于Ingress请求数),有请求时自动扩容到1个副本
- 空闲一段时间后自动缩容回0,彻底节省集群资源
3. 集群选择:同一集群VS不同集群
- 同一集群:更推荐,操作简单,资源利用率高。用Namespace隔离每个预览环境,销毁时直接删除Namespace即可,干净利落。
- 不同集群:适合隔离性要求极高的场景(比如测试环境和生产集群完全物理隔离),但需要额外配置跨集群的Kubectl权限,运维成本更高。
4. 关键前置准备
- 泛域名解析:把
*.git.mydomain.com解析到K8s Ingress Controller的公网IP,确保每个流水线的专属域名能正常访问。 - GitLab Runner权限:确保Runner所在的ServiceAccount拥有K8s的Namespace创建/删除、Deployment/Ingress管理权限。
- 环境过期配置:在GitLab项目的「Settings > CI/CD > Environments」里设置预览环境的过期时间(比如7天),即使忘记手动销毁,GitLab也会自动清理资源。
类似实践参考
很多大厂和开源项目都在用这种模式:
- GitLab官方的Review Apps功能就是这个思路的官方实现(你可以直接用官方功能,减少自定义配置)
- 比如GitLab自身的产品迭代,每个Merge Request都会生成临时预览环境,供产品/测试验收
内容的提问来源于stack exchange,提问作者Jan Richter
相关产品推荐
相关产品推荐

