← 中文资源

简体中文版本

对运行时配置漂移告警

把线上 ConfigMap 与 Git 中的清单做 diff,出现差异时告警,避免应急手改变成永久状态并在下次发布时被静默回滚。

阅读英文原文

概述

Git 本应是唯一事实来源,但 kubectl、Helm 回滚或控制台操作都可能在不改动仓库的情况下修改线上对象。于是集群中存在一份没有任何仓库解释的配置,下一次自动同步会把它删除。这正是应急修复变成重复故障的原因。漂移检查会比较渲染出的期望状态与线上对象,在修改者还记得原因时报告差异。

步骤

  1. 将渲染清单与线上集群做 diff:
kubectl diff -f rendered/ -n prod
  1. 把差异转成告警,而不是直接让任务失败:
#!/usr/bin/env bash
set -uo pipefail
kubectl diff -f rendered/ -n prod > /tmp/drift.diff 2>/tmp/drift.err
code=$?
if [ "$code" -eq 1 ]; then
  curl -fsS -X POST "$ALERT_WEBHOOK" --data-binary @/tmp/drift.diff
elif [ "$code" -gt 1 ]; then
  echo "diff failed: $(cat /tmp/drift.err)" >&2
  exit 1
fi
  1. 过滤控制器会正常改写的字段:
kubectl diff -f rendered/ -n prod \
  | grep -vE '^[+-][[:space:]]+(resourceVersion|uid|generation|managedFields)'
  1. 为应急手改提供回到 Git 的路径,并为告警指定负责人。

验证

无差异时命令不输出且退出码为 0;有差异时退出码为 1 并输出具体字段;集群不可达或权限不足时退出码大于 1,应作为错误单独上报,不能计入漂移。过滤后 resourceVersion、managedFields 等噪声应消失,但 spec 中的真实变更必须保留。告警内容应包含 diff 文本,值班人员无需集群权限即可判断。

注意事项

  • kubectl diff 无法覆盖在 Git 之外创建的资源。
  • 轮询间隔过长会漏掉在两次检查之间被还原的修改。
  • 错误与漂移必须区分,否则凭证过期会伪装成配置变更。
  • 过滤规则只应屏蔽元数据,不能整类排除对象。
  • 每条告警都应在当天闭环:要么回退线上修改,要么合并进 Git。