
Git中的配置写着两个副本,集群里多了一项未声明的特权配置。如果比较器只遍历期望配置里的键,它可能报告“一致”。这样的漂移检查,恰好漏掉最值得注意的新增字段。
比较键的并集
下面的标准库例子比较JSON兼容的字典和列表:字典看双方键的并集,列表按位置比较,缺失与显式null分开处理。路径采用类似JSON Pointer的转义,避免键里出现斜线时难以定位。
import json
MISSING = object()
def escape(key):
return str(key).replace("~", "~0").replace("/", "~1")
def differences(want, actual, path=""):
if isinstance(want, dict) and isinstance(actual, dict):
result = []
for key in sorted(set(want) | set(actual)):
a, b = want.get(key, MISSING), actual.get(key, MISSING)
child = path + "/" + escape(key)
if a is MISSING or b is MISSING:
result.append(child)
else:
result.extend(differences(a, b, child))
return result
if isinstance(want, list) and isinstance(actual, list):
result = []
for i in range(max(len(want), len(actual))):
child = path + "/" + str(i)
if i >= len(want) or i >= len(actual): result.append(child)
else: result.extend(differences(want[i], actual[i], child))
return result
return [] if type(want) is type(actual) and want == actual else [path or "/"]
want = json.loads('{"replicas":2,"nullable":null,"items":[1]}')
actual = json.loads('{"replicas":2,"privileged":true,"items":[1,2]}')
assert differences(want, actual) == ["/items/1", "/nullable", "/privileged"]
assert differences({"a/b": 1}, {"a/b": 2}) == ["/a~1b"]
assert differences({"x": True}, {"x": 1}) == ["/x"]
print("drift union checks: passed")

真实集群不能直接拿原始JSON硬比
Kubernetes会补默认值、写状态字段,控制器也会维护部分字段。应先定义哪些字段归Git声明管理,怎样归一化,哪些差异只告警。列表有的按位置,有的按键集合表达,不能一概排序后比较。
这里保留类型差异,1与1.0也会被当作不同;业务若把它们等价,应显式归一化。重复JSON键和非标准数值同样需要在解析边界严格处理,本例不承担完整配置安全验证。
OpenGitOps强调声明式、版本化、自动拉取和持续协调。持续协调意味着不断尝试使实际状态靠近期望状态,不代表永远没有漂移,更不代表发现任何差异都应立刻覆盖。
此程序未连接集群、未执行修复,只验证差异检测边界。先把“谁拥有这个字段”解释清楚,再决定由控制器恢复、由人确认,还是允许临时例外。
参考
- OpenGitOps四项原则
网硕互联帮助中心


评论前必须登录!
注册