6.7. 端到端交付实战:从提交到生产
前面每个章节各讲一个零件:CI、镜像、GitOps、Rollouts、SLO、回滚。这一章把它们装成一条完整的 Golden Path:一次 commit 如何经过构建、扫描、签名、GitOps 同步、金丝雀发布和 SLO 验证,最后安全地进入生产。
- 层级:
L4 · 实战
- 难度:
进阶
- 预计:
90 分钟
- 前置:
CI/CD、Helm/Kustomize、Argo CD、Prometheus
6.7.1. 目标链路
图:应用仓库负责「制品」,GitOps 仓库负责「期望状态」,Argo CD 负责「收敛」,Rollouts 负责「放量」。
6.7.2. 0. 实验环境
kind create cluster --name golden-path
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install kps prometheus-community/kube-prometheus-stack -n monitoring --create-namespace
需要 kubectl、helm、argocd、kubectl argo rollouts 插件。实验集群至少 4C/8G;没有 LoadBalancer 时用 port-forward 访问 Argo CD 和 Grafana。
6.7.3. 1. 应用仓库:构建一次
应用仓库包含代码、Dockerfile、测试和 CI。关键约束:
镜像 tag 使用 commit SHA,禁止
latest。CI 产出 digest、SBOM、漏洞报告、签名。
生产部署只引用 digest。
name: release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Build and push
run: |
IMAGE=ghcr.io/example/demoapp:${{ github.sha }}
docker build -t "$IMAGE" .
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
docker push "$IMAGE"
docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE" > digest.txt
- name: Scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/example/demoapp:${{ github.sha }}
exit-code: "1"
severity: CRITICAL,HIGH
真实流水线还应加入测试、SBOM、Cosign 签名和 GitOps 仓库更新。具体写法见 CI/CD 流水线 与 供应链安全。
6.7.4. 2. GitOps 仓库:只存期望状态
GitOps 仓库按环境分层:
apps/demoapp/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
└── overlays/
├── dev/kustomization.yaml
└── prod/kustomization.yaml
CI 最后一步用 yq 把 prod overlay 的 image 改成新 digest,然后提交:
yq -i '.images[0].newName = "ghcr.io/example/demoapp" | .images[0].digest = strenv(DIGEST)' \
apps/demoapp/overlays/prod/kustomization.yaml
git commit -am "release demoapp ${GITHUB_SHA}"
git push
不要让 CI 直接 kubectl apply 生产;CI 只改 Git,集群由 Argo CD 收敛。
6.7.5. 3. Argo CD:同步与漂移
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demoapp-prod
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/gitops-demo.git
targetRevision: main
path: apps/demoapp/overlays/prod
destination:
server: https://kubernetes.default.svc
namespace: demo
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
验收:Git 改副本数 → Argo CD 自动同步;手工改副本数 → selfHeal 纠正;删除 Git 中的资源 → prune 清理。
6.7.6. 4. 金丝雀:用指标决定放量
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: demoapp
spec:
replicas: 10
selector:
matchLabels:
app: demoapp
template:
metadata:
labels:
app: demoapp
spec:
containers:
- name: demoapp
image: ghcr.io/example/demoapp@sha256:<digest>
ports:
- containerPort: 80
strategy:
canary:
analysis:
templates:
- templateName: success-rate
steps:
- setWeight: 10
- pause: {duration: 2m}
- setWeight: 50
- pause: {duration: 2m}
- setWeight: 100
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
metrics:
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.99
failureLimit: 1
provider:
prometheus:
address: http://kps-kube-prometheus-stack-prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{job="demoapp",code!~"5.."}[2m]))
/
sum(rate(http_requests_total{job="demoapp"}[2m]))
kubectl argo rollouts get rollout demoapp --watch
kubectl argo rollouts set image demoapp demoapp=ghcr.io/example/demoapp@sha256:<new-digest>
kubectl argo rollouts promote demoapp
kubectl argo rollouts abort demoapp
分析失败会自动 abort;没有指标分析的 canary 只是慢速全量发布。
6.7.7. 5. SLO 与回滚
给服务定义 SLO,例如「30 天成功率 ≥ 99.9%」。错误预算消耗过快时:
暂停自动发布(GitOps 仍可同步,但 Rollout 不 promote)。
回滚到上一个已知良好的 digest。
检查数据库迁移是否兼容;应用回滚不等于数据回滚。
记录事件时间线与改进项。
kubectl argo rollouts undo demoapp
kubectl get rollout demoapp -o jsonpath='{.status.currentPodHash}'
回滚后观察 30 分钟错误率、P95 延迟与饱和度,再决定是否重新发布。
6.7.8. 6. 复盘与 DORA
一次完整演练后记录:
部署频率:本周发布次数。
变更前置时间:commit 到生产的时间。
变更失败率:回滚/事故比例。
恢复时间:从告警到恢复的时长。
复盘至少写清:触发原因、检测方式、止血动作、根因、改进项与负责人。流程见 SRE 与事件响应。
6.7.9. 验证清单
每个 commit 产出唯一 digest,生产只引用 digest。
镜像经过测试、扫描、签名,SBOM 已归档。
CI 只更新 GitOps 仓库,不直接 apply 生产。
Argo CD 能自动同步、纠正漂移、prune 资源。
Rollout 按 10% → 50% → 100% 放量,分析失败自动 abort。
回滚到旧 digest 后服务恢复,数据库兼容。
SLO/错误预算与发布门禁关联。
复盘有改进项与截止时间。
6.7.10. 排错表
现象 |
原因 |
处理 |
|---|---|---|
CI 推送成功但 Argo 不同步 |
GitOps 仓库未更新/digest 错 |
检查 commit 与 overlay |
Argo |
手工改动/CRD 未安装 |
开 selfHeal,调整 sync-wave |
Rollout 卡在 pause |
无 promote/分析失败 |
|
分析查询无数据 |
ServiceMonitor/标签不对 |
查 Prometheus targets 与 job 标签 |
回滚后仍报错 |
数据库 schema 不兼容 |
用 expand/contract,先兼容再回滚 |
发布后延迟升高 |
资源不足/连接池 |
看指标,调 resources/HPA |
6.7.11. 进阶挑战
把 GitHub Actions 换成 GitLab CI 或 Tekton,保持同样的 digest 流程。
用 Flagger 替代 Argo Rollouts,比较两者的分析模型。
给 Rollout 加 feature flag,按租户灰度。
把 SLO 告警接到 Slack,并演练一次 error budget 冻结发布。
6.7.12. 小结
端到端交付的核心是「制品不可变、状态在 Git、放量看指标、回滚有路径」。
CI 只负责构建与验证,GitOps 负责收敛,Rollouts 负责流量,SRE 负责风险。
任何一段没有可观测指标,发布就会退回人工判断。
先用一条 Golden Path 跑通,再谈平台化与多团队自助。