GitOps 实践:ArgoCD 持续交付 > 从"手工 kubectl apply"到"Git 驱动、自动同步、可回滚"的部署体系
写在前面
你可能还在用 Jenkins/GitLab CI 构建镜像,然后一个 kubectl apply -f deployment.yaml 推到集群。这叫 CI 驱动部署------流水线"推"着集群走。问题很明显:谁改了集群配置没人知道,回滚靠人脑记 Git commit,多环境手动操作出错率高。GitOps 是另一条路:集群的状态永远由 Git 仓库定义,ArgoCD 自动拉取并同步。你改 Git,ArgoCD 改集群;集群有人偷偷 kubectl edit,ArgoCD 会自动拉回来(自愈)。这篇文章从 GitOps 四原则出发,带你落地 ArgoCD 多环境管理、渐进式交付(Argo Rollouts)、通知和 SSO,让部署从"手工活"变成"Git 驱动的自动化闭环"。
核心问题
部署怎么从"手工 kubectl"进化到"Git 驱动、自动同步、可回滚"的持续交付体系?
一、原理剖析
1.1 GitOps 四原则
GitOps 不是"把 kubectl 命令写进 CI pipeline"那么简单,它有四个核心原则,缺一个就不完整:
┌──────────────────────────────────────────────────────────────┐
│ GitOps 四原则 │
├──────────────────┬───────────────────────────────────────────┤
│ 1. 声明式 │ 集群期望状态用声明式描述(YAML/Helm/Kust) │
│ │ 不写脚本,不写 kubectl 命令 │
├──────────────────┼───────────────────────────────────────────┤
│ 2. 版本化 │ 所有声明存入 Git,每次变更都是一个 commit │
│ │ 回滚 = git revert,审计 = git log │
├──────────────────┼───────────────────────────────────────────┤
│ 3. 自动拉取 │ 自动化系统(ArgoCD)持续拉取 Git, │
│ │ 发现差异后自动同步到集群 │
├──────────────────┼───────────────────────────────────────────┤
│ 4. 自愈 │ 集群被手动修改后,ArgoCD 检测到 │
│ │ OutOfSync 状态,自动拉回 Git 定义的状态 │
└──────────────────┴───────────────────────────────────────────┘
对比传统 CI Push 模型:
传统 CI Push:
Git → CI Pipeline → 构建镜像 → kubectl apply → 集群
问题: 集群状态 ≠ Git 状态;没有自愈;回滚靠人
GitOps Pull:
Git → ArgoCD 拉取 → 对比集群状态 → 自动/手动同步 → 集群
优势: 集群状态 = Git 状态;自愈;回滚 = git revert
1.2 ArgoCD 架构
┌─────────────────────┐
│ Git Repositories │
│ (Helm/Kust/YAML) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Repo Server │
│ (拉取Git+渲染模板) │
└──────────┬──────────┘
│ 渲染后的目标清单
┌──────────▼──────────┐
│ Application Ctrl │◄── UI/API/CLI
│ (对比目标vs实际状态) │
│ OutOfSync → Sync │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Kubernetes Cluster │
│ (实际运行状态) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Notification Ctrl │
│ (Sync结果/健康变化 │
│ → Slack/Email/Webhook) │
└─────────────────────┘
核心组件:
- Application Controller: 核心,持续对比 Git 目标状态与集群实际状态,发现差异触发 Sync
- Repo Server: 从 Git 仓库拉取配置,渲染 Helm/Kustomize,输出最终 YAML 清单
- API Server / UI: 用户交互入口,查看状态、手动同步、管理 Application
- Notification Controller: 监听 Application 状态变化,发送通知(Slack/Email/Webhook)
关键概念:
- Application: ArgoCD 的核心资源,定义"一个 Git 仓库的某个路径 → 同步到集群的某个 namespace"
- Source: Git 仓库地址+路径+分支+revision,可指定 Helm values 覆盖
- Project: 资源隔离边界,控制哪些 namespace/cluster/仓库可以被使用
- Sync Policy :
auto(自动同步) /manual(手动审批) /auto+prune(自动同步+自动删除不在 Git 里的资源)
1.3 多环境管理:App of Apps 与 ApplicationSet
当你的环境从 1 个变成 5 个(dev/staging/prod + 2 个区域),每个环境都要定义 Application,手动管理太痛了。
App of Apps 模式:
Git: argocd-apps/
├── apps/
│ ├── dev.yaml # dev 環境的 Application 列表
│ ├── staging.yaml # staging 環境
│ └── prod.yaml # prod 環境
│ └── root.yaml # "App of Apps"------引用上面三个
root.yaml:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
source:
repoURL: https://git.internal/argocd-apps
path: apps
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
ApplicationSet 模式(推荐):
ApplicationSet 用模板+生成器批量创建 Application,比 App of Apps 更灵活:
ApplicationSet 工作原理:
Generator(生成目标列表) + Template(Application模板) = 多个 Application
┌─────────────┐ ┌──────────────┐
│ Generator │ ───► │ Template │ ───► 生成 N 个 Application
│ (集群列表/ │ │ (Application │
│ Git目录/ │ │ 定义模板) │
│ 環境列表) │ └──────────────┘
└─────────────┘
1.4 Argo Rollouts:渐进式交付
ArgoCD 负责同步,Argo Rollouts 负责"怎么安全地推进新版本"。Rollouts 是 Deployment 的替代品,支持金丝雀/蓝绿/渐进式发布+自动化分析。
Argo Rollouts 金丝雀流程:
Stable (v1) ──► Canary (v2, 10%流量)
│
├─ AnalysisTemplate: 检查错误率/延迟
│ ├─ Pass → 增加到 30% 流量
│ ├─ Fail → 自动回滚到 v1
│ └─ Continue → 等待下一步
│
├─ 30% → Analysis again → Pass
│
├─ 60% → Analysis again → Pass
│
└─ 100% → Promote, v2 成为 Stable
关键组件:
- Rollout: 替代 Deployment 的 CRD,定义发布策略
- AnalysisTemplate: 定义指标检查条件(Prometheus/Web/Job)
- AnalysisRun: 一次实际的分析执行
- Experiment: 可在金丝雀期间运行并行实验
二、实战操作
2.1 ArgoCD 安装
bash
# 安装 ArgoCD(K8s 1.30 兼容版本 v2.12)
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.12.0/stable/install.yaml
# 获取初始 admin 密码
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# 安装 argocd CLI
curl -sLO https://github.com/argoproj/argo-cd/releases/download/v2.12.0/argocd-linux-amd64
chmod +x argocd-linux-amd64
mv argocd-linux-amd64 /usr/local/bin/argocd
# 访问 UI(端口转发)
kubectl port-forward svc/argocd-server -n argocd 8080:443 &
# 浏览器访问 https://localhost:8080
# 登录
argocd login localhost:8080 --username admin --password <上面获取的密码>
2.2 ApplicationSet 多环境方案
cluster-appset.yaml --- 按集群生成 Application:
yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-clusters
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: dev-cluster
url: https://dev.k8s.internal
env: dev
values:
replicaCount: 1
imageTag: latest
- cluster: staging-cluster
url: https://staging.k8s.internal
env: staging
values:
replicaCount: 2
imageTag: v2.4.1-rc1
- cluster: prod-cluster
url: https://prod.k8s.internal
env: prod
values:
replicaCount: 3
imageTag: v2.4.1
template:
metadata:
name: "myapp-{{env}}"
labels:
env: "{{env}}"
spec:
project: default
source:
repoURL: https://git.internal/platform/myapp-deploy
targetRevision: main
path: helm/myapp
helm:
valueFiles:
- values.yaml
- "values-{{env}}.yaml"
parameters:
- name: replicaCount
value: "{{values.replicaCount}}"
- name: image.tag
value: "{{values.imageTag}}"
destination:
server: "{{url}}"
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
Git 目录模式生成器 --- 每个环境一个目录:
yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-git-dir
namespace: argocd
spec:
generators:
- git:
repoURL: https://git.internal/platform/myapp-deploy
revision: main
directories:
- path: envs/* # 匹配 envs/dev、envs/staging、envs/prod
template:
metadata:
name: "myapp-{{path.basename}}"
spec:
project: default
source:
repoURL: https://git.internal/platform/myapp-deploy
targetRevision: main
path: "{{path}}"
destination:
server: https://kubernetes.default.svc
namespace: "myapp-{{path.basename}}"
syncPolicy:
automated:
prune: true
selfHeal: true
Git 仓库结构:
myapp-deploy/
├── envs/
│ ├── dev/
│ │ └── kustomization.yaml
│ │ └── patch-replicas.yaml # replicas: 1
│ ├── staging/
│ │ └── kustomization.yaml
│ │ └── patch-replicas.yaml # replicas: 2
│ └── prod/
│ │ └── kustomization.yaml
│ │ └── patch-replicas.yaml # replicas: 3
│ │ └── patch-resources.yaml # 更大的资源限制
2.3 Argo Rollouts 金丝雀发布
先安装 Argo Rollouts:
bash
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/v2.37.0/stable/install.yaml
# 安装 kubectl argo-rollouts 插件
curl -sLO https://github.com/argoproj/argo-rollouts/releases/download/v2.37.0/kubectl-argo-rollouts-linux-amd64
chmod +x ./kubectl-argo-rollouts-linux-amd64
mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
rollout.yaml --- 金丝雀发布策略:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: myapp-rollout
namespace: myapp
spec:
replicas: 5
strategy:
canary:
canaryService: myapp-canary # 金丝雀 Service
stableService: myapp-stable # 稳定版 Service
trafficRouting:
istio:
virtualService:
name: myapp-vsvc
routes:
- primary
destinationRules:
name: myapp-dr
steps:
- setWeight: 10 # 10% 流量到金丝雀
- pause: {duration: 5m} # 观察 5 分钟
- analysis:
templates:
- templateName: error-rate-check
args:
- name: service-name
value: myapp-canary.default.svc.cluster.local
- setWeight: 30 # 分析通过,30% 流量
- pause: {duration: 5m}
- analysis:
templates:
- templateName: latency-check
- setWeight: 60
- pause: {duration: 2m}
- setWeight: 100 # 全量发布
revisionHistoryLimit: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: registry.internal/company/myapp:v2.4.1
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
AnalysisTemplate --- 基于 Prometheus 的自动化分析:
yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: error-rate-check
namespace: myapp
spec:
args:
- name: service-name
metrics:
- name: error-rate
interval: 30s
count: 6 # 6 次采样 = 3 分钟
successLimit: 5 # 至少 5 次通过
failureLimit: 2 # 2 次失败就中止金丝雀
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: >
sum(rate(http_requests_total{status_code=~"5..",
app="{{args.service-name}}"}[1m]))
/
sum(rate(http_requests_total{app="{{args.service-name}"}[1m]))
successCondition: result[0] < 0.01 # 错误率 < 1%
failureCondition: result[0] >= 0.05 # 错误率 >= 5%
yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: latency-check
namespace: myapp
spec:
metrics:
- name: p99-latency
interval: 30s
count: 4
successLimit: 3
failureLimit: 2
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: >
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{app="myapp-canary"}[1m]))
by (le))
successCondition: result[0] < 2 # P99 < 2秒
failureCondition: result[0] >= 5 # P99 >= 5秒
Istio VirtualService + DestinationRule 配合金丝雀流量分割:
yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp-vsvc
namespace: myapp
spec:
hosts:
- myapp.company.com
gateways:
- myapp-gateway
http:
- name: primary
route:
- destination:
host: myapp-stable
weight: 100
- destination:
host: myapp-canary
weight: 0
yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: myapp-dr
namespace: myapp
spec:
host: myapp-stable
trafficPolicy:
connectionPool:
http:
h2UpgradePolicy: DEFAULT
操作命令:
bash
# 查看发布状态
kubectl argo-rollouts get rollout myapp-rollout -n myapp
# 手动推进金丝雀(如果设了 pause)
kubectl argo-rollouts promote myapp-rollout -n myapp
# 手动回滚
kubectl argo-rollouts undo myapp-rollout -n myapp
# 查看分析结果
kubectl argo-rollouts list analysisruns -n myapp
2.4 ArgoCD SSO/OIDC 认证
生产环境不能用 admin 账号,必须接 SSO。
argocd-cm.yaml --- OIDC 配置(以公司内部 IdP 为例):
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
url: https://argocd.company.com
oidc.config: |
name: CompanySSO
issuer: https://idp.company.com/realms/platform
clientID: argocd-prod
clientSecret: $oidc.company.clientSecret # 引用 argocd-secret 中的值
requestedScopes: ["openid", "profile", "email", "groups"]
requestedIDTokenClaims: {"groups": {"essential": true}}
RBAC 配置 --- argocd-rbac-cm.yaml:
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.csv: |
# 管理员组:全局读写
g, platform-admins, role:admin
# 开发组:只能操作 dev 環境的 Application
g, dev-team, role:dev-developer
# 定义自定义角色
p, role:dev-developer, applications, get, dev/*, allow
p, role:dev-developer, applications, sync, dev/*, allow
p, role:dev-developer, applications, create, dev/*, allow
# 生产组:只能查看,不能自动同步
g, prod-team, role:prod-viewer
p, role:prod-viewer, applications, get, prod/*, allow
p, role:prod-viewer, applications, sync, prod/*, deny
policy.default: role:readonly
2.5 通知配置
argocd-notification-cm.yaml:
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
template.app-deployed: |
email:
subject: "[ArgoCD] {{ .app.metadata.name }} deployed to {{ .app.spec.destination.namespace }}"
slack:
blocks:
- type: section
text:
type: mrkdwn
text: ":white_check_mark: **{{ .app.metadata.name }}** synced to **{{ .app.spec.destination.namespace }}**"
- type: context
elements:
- type: mrkdwn
text: "Revision: {{ .app.status.operationState.syncResult.revision }}"
webhook:
myapp-deployed:
method: POST
path: /deployments
body: |
{"app": "{{ .app.metadata.name }}", "env": "{{ .app.spec.destination.namespace }}", "revision": "{{ .app.status.operationState.syncResult.revision }}"}
trigger.on-deployed: |
- description: Application deployed
oncePer: app.metadata.name
send:
- template.app-deployed
when: app.status.operationState.phase in [Succeeded]
trigger.on-sync-failed: |
- description: Sync failed
send:
- template.app-sync-failed
when: app.status.operationState.phase in [Failed, Error]
service.slack: |
apiUrl: https://slack.com/api/chat.postMessage
token: $slack-token
channels:
- name: argocd-deployments
service.email: |
host: smtp.company.com
port: 587
from: argocd@company.com
username: argocd@company.com
password: $email-password
给 Application 添加通知订阅:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
annotations:
notifications.argoproj.io/subscribe.on-deployed.slack: argocd-deployments
notifications.argoproj.io/subscribe.on-sync-failed.slack: argocd-deployments
notifications.argoproj.io/subscribe.on-deployed.email: dev-team@company.com
spec:
# ... (Application 定义)
三、踩坑与排查
踩坑 1:ArgoCD Sync 成功但 Application 状态一直 Progressing
现象 : argocd app get myapp 显示 Sync Status: Synced,但 Health Status: Progressing,永远不变成 Healthy。
原因: ArgoCD 的 Health Check 不仅看资源是否创建成功,还看资源是否"就绪"。Deployment 必须所有 Pod Ready;Pod 必须所有 Container Running;Job 必须 Completed。如果你的 Pod 因为 readinessProbe 不通过而一直 Not Ready,Health 就卡在 Progressing。
bash
# 查看 ArgoCD 的健康判断逻辑
kubectl get deploy myapp -n myapp -o jsonpath='{.status.conditions}'
# 常见问题:replicas=3,availableReplicas=2,updatingReplicas=1
解决:
bash
# 方法 1:检查 Pod 状态
kubectl get pods -n myapp -l app=myapp
kubectl describe pod <pod-name> -n myapp | grep -A5 "Readiness"
# 方法 2:如果 Probe 配置合理但 ArgoCD 仍不识别,自定义 Health Check
# argocd-cm 中添加自定义健康规则:
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
resource.customizations.health.apps_Deployment: |
hs = {}
if obj.status ~= nil then
if obj.status.readyReplicas == obj.status.replicas then
hs.status = "Healthy"
hs.message = "All replicas ready"
else
hs.status = "Progressing"
hs.message = "Waiting for replicas: " .. obj.status.readyReplicas .. "/" .. obj.status.replicas
end
end
return hs
蹈坑 2:SelfHeal 把紧急手动修复又"拉回"了错误状态
现象 : 生产出了严重 bug,运维手动 kubectl scale deployment myapp --replicas=10 应急,ArgoCD 检测到 OutOfSync,5 分钟后自动把 replicas 拉回 Git 里的 3,应急措施失效。
原因 : selfHeal: true 会让 ArgoCD 在检测到任何偏差时自动同步。这在平时是好事(防止手动修改漂移),但在紧急场景下会" Undo"你的应急操作。
解决:
yaml
# 方法 1:临时关闭自愈(推荐)
# 在 Application 上加 annotation:
annotations:
argocd.argoproj.io/sync-options: SelfHeal=false
# 方法 2:先改 Git 再让 ArgoCD 同步(最安全)
# kubectl scale 后,立即在 Git 仓库改 values-prod.yaml 的 replicaCount=10
# ArgoCD 同步后集群状态和 Git 一致
# 方法 3:使用 ArgoCD 的 "Sync Window" 限制自愈时间
# 只在非工作时间自愈:
yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: default
namespace: argocd
spec:
syncWindows:
- kind: allow
schedule: "10 1 * * *" # 每天凌晨 1:10 允许同步
duration: 8h # 持续 8 小时
applications:
- name: myapp-prod
manualSync: true # 其他时间只允许手动同步
踩坑 3:Argo Rollouts 金丝雀 AnalysisTemplate 查不到 Prometheus 数据
现象 : 金丝雀到 analysis 步骤时,AnalysisRun 一直 Running 不出结果,最终金丝雀超时回滚。
原因: AnalysisTemplate 的 Prometheus query 写错了 service-name 变量,或者 Prometheus 在另一个集群,Argo Rollouts 网络不通。
bash
# 查看 AnalysisRun 详细状态
kubectl get analysisrun -n myapp -l rollouts=myapp-rollout
kubectl describe analysisrun <analysisrun-name> -n myapp
# 常见错误: "failed to query prometheus: connection refused"
解决:
bash
# 1. 验证 Prometheus 可达
kubectl run curl-test --rm -it --restart=Never --image=curlimages/curl \
-- curl -s "http://prometheus.monitoring:9090/api/v1/query?query=up"
# 2. 验证 query 语法(在 Prometheus UI 先试)
# 把 AnalysisTemplate 里的 query 拿到 Prometheus Graph 页面跑一遍
# 3. 确保 args 替换正确
# AnalysisTemplate 中 {{args.service-name}} 必须与 Rollout 的 analysis.args 匹配
# Rollout 定义:
# analysis:
# templates:
# - templateName: error-rate-check
# args:
# - name: service-name
# value: myapp-canary.myapp.svc.cluster.local # 完整 DNS 名称
踩坑 4:ApplicationSet 生成太多 Application 导致 ArgoCD 性能下降
现象 : ArgoCD UI 加载缓慢,argocd app list 响应慢,Application Controller CPU 持续高。
原因: ApplicationSet 的 List Generator 有 30 个集群 × 20 个应用 = 600 个 Application,ArgoCD 每个都要持续对比 Git 状态,API Server 扛不住。
解决:
yaml
# 方法 1:减少对比频率(降低 reconcile 循环)
# argocd-cm:
data:
timeout.reconciliation: 300s # 从默认 180s 改为 300s
# 方法 2:用 Git Directory Generator 替代 List Generator
# 让 Git 仓库结构决定 Application 数量,而不是硬编码
# 方法 3:按环境拆分多个 ApplicationSet
# 不要一个 AppSet 生成所有环境,每个环境一个 AppSet:
yaml
# prod-appset.yaml (只管 prod)
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapp-prod
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
env: prod # 只选择 prod 集群
template:
# ...
四、最佳实践
ArgoCD 生产部署清单
| 项目 | 建议 | 说明 |
|---|---|---|
| HA 部署 | Application Controller 3 replicas | 生产必须 HA |
| Redis | 用外部 Redis(HA) | 不用内置单节点 Redis |
| Repo Server | 2+ replicas | Git 仓库压力大时需要 |
| 资源限制 | Controller 2CPU/2Gi,Repo 1CPU/1Gi | 防止 OOM |
| SSO | 必须接 OIDC | 不用 admin 密码 |
| RBAC | 精细到 project+namespace | dev 不能操作 prod |
| 自愈 | prod 环境建议 manual sync | 紧急修改不被 Undo |
| 通知 | 必须配置 Slack/Email | 同步失败第一时间知道 |
| Git 分支 | prod 用 main 分支,dev 用 develop | 分支与环境对应 |
| 资源跟踪 | 使用 annotation-based tracking | 防止命名冲突 |
| Secret 管理 | 用 Sealed Secrets / SOPS | Secret 不裸放 Git |
GitOps 仓库结构推荐
platform-deploy/
├── argocd/
│ ├── appsets/ # ApplicationSet 定义
│ │ ├── dev.yaml
│ │ ├── staging.yaml
│ │ └── prod.yaml
│ ├── projects/ # AppProject 定义
│ └── notifications/ # 通知模板
├── envs/
│ ├── dev/
│ │ ├── myapp/
│ │ │ ├── kustomization.yaml
│ │ │ └── patch.yaml
│ ├── staging/
│ │ ├── myapp/
│ ├── prod/
│ │ ├── myapp/
├── base/ # Kustomize 基础(所有环境共享)
│ ├── myapp/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ ├── kustomization.yaml
Argo Rollouts 最佳实践
- 金丝雀步骤必须有
analysis节点,不能只靠人肉观察 - AnalysisTemplate 至少检查错误率和 P99 延迟两个指标
failureLimit设为 2(两次失败就中止),不要设太高- 生产环境 Rollout 先
pause,人工确认后再promote revisionHistoryLimit设为 3,避免保留太多旧 ReplicaSet- 蓝绿发布比金丝雀简单但资源消耗翻倍,流量波动大的场景选金丝雀
- Istio/SMI trafficRouting 精确到百分比,Nginx Ingress 只能按权重近似
五、小结
GitOps 的核心转变是:从"人推集群"变成"集群自己拉 Git"。ArgoCD 是这个转变的落地工具------声明式 Application 定义目标,Repo Server 拉取渲染,Controller 对比同步,Notification Controller 通知结果。多环境用 ApplicationSet 模板化,金丝雀发布用 Argo Rollouts + AnalysisTemplate 自动化,认证用 OIDC+RBAC 分权限,通知用 Slack+Email 全覆盖。关键教训:生产的 selfHeal 不要盲目开启,紧急场景下自愈会 Undo 应急操作;AnalysisTemplate 的 Prometheus query 必须提前验证,否则金丝雀会卡死在 analysis 步骤。
思考题
- 如果你的公司有 5 个集群(dev/staging/prod-cn/prod-us/prod-eu),怎么设计 ApplicationSet 让每个集群自动生成对应环境的 Application?
- ArgoCD 的 selfHeal 和手动 kubectl 修改之间如何平衡?生产环境应该 auto sync 还是 manual sync?
- 金丝雀发布的 AnalysisTemplate 除了 Prometheus,还支持 Web hook 和 Job 类型。什么场景下用 Web hook 比 Prometheus 更合适?