一次误删 ConfigMap,让我重新想发布这件事
年初我们还是"人肉发布":本地打镜像、kubectl set image、改几个 ConfigMap。有次同事手滑把生产环境的 ConfigMap 改错了一个 value,Pod 起来就读不到正确配置,故障持续了 12 分钟。事后复盘,我意识到问题不在某个人,而在发布动作没有"单一可信源"。那之后我开始推 GitOps,主力工具选了 ArgoCD。
GitOps 的核心:Git 是唯一真相
GitOps 的想法很朴素:集群里跑什么,完全由 Git 仓库里的声明式清单决定。任何变更(镜像版本、副本数、配置)都先提 PR 到 Git,而不是去 kubectl 敲命令。ArgoCD 就是那个不停对比"Git 期望状态"和"集群实际状态"的控制器。
ArgoCD 怎么工作:声明式 + 自动同步
在 ArgoCD 里注册一个 Application,告诉它 Git 仓库地址、路径、目标集群和 namespace:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: order-service
namespace: argocd
spec:
project: default
source:
repoURL: https://git.xxx.com/platform/manifests.git
path: overlays/prod/order
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: prod
syncPolicy:
automated:
prune: true # 删除 Git 里已不存在的资源
selfHeal: true # 集群被手动改了,自动纠正回 Git 状态
关键是两个开关:prune 让 Git 删资源时集群也跟着删;selfHeal 是防漂移——有人手敲 kubectl edit 改了线上,ArgoCD 会发现不一致并把集群拉回 Git 定义的状态。前面那个 ConfigMap 误删,如果在 GitOps 下,只需要在 Git 里改一行,集群自动收敛,根本不需要人去线上敲命令。
同步与回滚:比人快,也比人稳
ArgoCD 的同步状态机分几个阶段:Progressing(应用清单中)→ Healthy/Degraded。它能识别 Deployment 是否就绪、Pod 是否 Running,只有 Healthy 才算成功。
回滚是我最喜欢的能力。因为所有历史版本都在 Git 里,回滚就是把 targetRevision 指回上一个 commit:
# 查看 ArgoCD 记录的同步历史
$ argocd app history order-service
ID STATUS REVISION
1 Succeeded a1b2c3d
2 Succeeded e4f5g6h <- 当前
3 Degraded i7j8k9l
# 一键回滚到上一个健康版本
$ argocd app rollback order-service 2
真实数字:上次一次有问题的发布,从发现异常到 ArgoCD 回滚完成,不到 90 秒;而以前人工回滚要找上一个镜像 tag、改 yaml、等滚动,至少 5 分钟。
我们定下的几条规矩
- main 分支受保护,任何变更必须 PR + 两人 review,禁止直接 push。
- ArgoCD 只读 Git,集群权限收口,开发不能在 prod 命名空间用 kubectl 改资源。
- 敏感配置走 sealed-secrets,明文不进 Git。
- sync 失败要报警,接 Prometheus:
argocd_app_condition异常就发钉钉。
小结
- GitOps 不是工具,是"Git 即集群真相"的工作方式,ArgoCD 是它的执行引擎。
selfHeal解决了"线上被手改"的漂移问题,这是人肉发布永远做不到的。- 回滚从"找上一个版本重发"变成"指回上一个 commit",速度差一个数量级。
推广 GitOps 半年,最大的变化不是发布变快了,而是再没有人在生产环境敲过 kubectl。那次 ConfigMap 事故之后再没发生过,因为唯一能改生产的人,是 Git 仓库和 ArgoCD。