1. 作用与应用场景
Karmada 的 ResourceInterpreterCustomization 允许用户通过 Lua 脚本自定义多集群资源的状态聚合、保留、健康判定等逻辑,解决如 CRD 状态同步、混沌实验等多集群一致性与差异性场景。
典型场景:
- chaos-mesh 等 CRD 资源的 status 聚合
- HPA、Job 等原生/自定义资源的副本数、健康等自定义同步
- 解决成员集群本地控制器与 Karmada 控制面冲突
2. CRD 字段结构与关键字段
以 chaos-mesh 的 PodChaos CRD 为例,ResourceInterpreterCustomization 资源结构如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| apiVersion: config.karmada.io/v1alpha1
kind: ResourceInterpreterCustomization
metadata:
name: podchaos-chaos-mesh
spec:
target:
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
customizations:
statusReflection:
luaScript: |
...
statusAggregation:
luaScript: |
...
retention:
luaScript: |
...
|
常用字段说明:
statusReflection
:定义如何从成员集群资源提取 status 字段statusAggregation
:定义如何聚合所有成员集群的 status 到控制面retention
:定义保留哪些字段,解决本地控制器与控制面冲突
3. 常用自定义脚本用法
3.1 statusReflection 示例(以 PodChaos 为例)
1
2
3
4
5
6
7
8
9
10
| function ReflectStatus(observedObj)
status = {}
if observedObj == nil or observedObj.status == nil then
return status
end
-- 只提取 conditions 和 experiment 字段,适配 PodChaos CRD
status.conditions = observedObj.status.conditions
status.experiment = observedObj.status.experiment
return status
end
|
3.2 statusAggregation 优化聚合示例(以 PodChaos 为例,含注释)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
| function AggregateStatus(desiredObj, statusItems)
-- 聚合所有成员集群的 conditions 字段
allConditions = {}
-- 用于收集所有有效 experiment
local experiments = {}
-- 用于收集包含 Succeeded 事件的 experiment
local succeededExperiments = {}
-- 遍历所有成员集群的 status
for i = 1, #statusItems do
local status = statusItems[i].status
if status ~= nil then
-- 聚合 conditions
if status.conditions ~= nil then
for _, cond in ipairs(status.conditions) do
table.insert(allConditions, cond)
end
end
-- 收集 experiment 字段
if status.experiment ~= nil then
table.insert(experiments, status.experiment)
-- 检查 experiment 是否包含 Succeeded 事件
local exp = status.experiment
if exp.containerRecords ~= nil then
for _, record in ipairs(exp.containerRecords) do
if record.events ~= nil then
for _, event in ipairs(record.events) do
if event.type == "Succeeded" then
-- 只要有 Succeeded 事件就收集该 experiment
table.insert(succeededExperiments, exp)
break
end
end
end
end
end
end
end
end
desiredObj.status = desiredObj.status or {}
desiredObj.status.conditions = allConditions
-- 判断所有 experiment 是否完全一致
local function isAllSame(exps)
if #exps == 0 then return false end
local first = exps[1]
for i = 2, #exps do
for k, v in pairs(first) do
if exps[i][k] ~= v then
return false
end
end
for k, v in pairs(exps[i]) do
if first[k] ~= v then
return false
end
end
end
return true
end
-- 聚合优先级判断
if #experiments == 0 then
-- 所有成员集群都没有 experiment 字段,聚合默认值
desiredObj.status.experiment = {
desiredPhase = "",
containerRecords = {},
message = "no experiment field in any cluster"
}
elseif isAllSame(experiments) then
-- 所有 experiment 完全一致,聚合该 experiment
desiredObj.status.experiment = experiments[1]
elseif #succeededExperiments > 0 then
-- 有 experiment 不一致,但有 Succeeded,聚合第一个 Succeeded 的 experiment
desiredObj.status.experiment = succeededExperiments[1]
else
-- 有 experiment 但都不一致且无 Succeeded,聚合默认对象并提示
desiredObj.status.experiment = {
desiredPhase = "",
containerRecords = {},
message = "experiment fields are inconsistent across clusters"
}
end
return desiredObj
end
|
3.3 retention 示例(以 PodChaos 为例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| function Retain(desiredObj, observedObj)
-- 控制面已删除时不保留
if desiredObj == nil then
return nil
end
-- 控制面资源正在被删除时不保留
if desiredObj.metadata ~= nil and desiredObj.metadata.deletionTimestamp ~= nil then
return desiredObj
end
-- 其他情况下保留 status 字段
if observedObj.status ~= nil then
desiredObj.status = observedObj.status
end
return desiredObj
end
|
4. CRD 及 RBAC 注意事项
- 目标 CRD 必须声明
subresources.status
,否则无法写回 status 字段:1
2
3
4
5
6
| spec:
versions:
- name: v1alpha1
...
subresources:
status: {}
|
- Karmada 控制面 ServiceAccount 需有目标资源
/status
的 patch/update 权限:1
2
3
| - apiGroups: ["chaos-mesh.org"]
resources: ["podchaos/status"]
verbs: ["get", "update", "patch"]
|
5. 常见问题与排查建议
- 控制面 status 字段无内容:优先排查 CRD 是否声明 status 子资源、RBAC 权限是否齐全。
- 聚合失败报类型错误:聚合脚本返回的字段类型需与 CRD schema 完全一致(如 experiment 必须为 object,不能为 array 或缺失 required 字段)。
- 部分成员集群无 workload:聚合时应只统计有有效 status 的成员集群,避免因部分集群无状态导致整体聚合失真。
- Lua 脚本报错:可用
karmadactl interpret
本地调试脚本。
6. chaos-mesh 场景最佳实践
- statusReflection 只提取 conditions/experiment 字段,避免冗余。
- statusAggregation 优先聚合一致 experiment,不一致时优先聚合已 Succeeded 的 experiment。
- retention 只保留 status 字段,避免本地控制器与控制面冲突。
- CRD 必须声明 status 子资源,RBAC 权限需齐全。
- 建议先用
karmadactl interpret
本地验证 Lua 脚本。
7. gopher-lua 支持特性与限制
Karmada 的 Lua 运行环境基于 gopher-lua,其特性如下:
- 兼容 Lua 5.1 语法和标准库,支持 table、string、math、table.insert、ipairs、pairs 等常用操作。
- 支持自定义函数注册,Karmada 会将资源对象、参数等以 table 形式注入 Lua 环境。
- 不支持 C 扩展库(如 LuaSocket、lfs 等),仅支持纯 Lua 标准库。
- 沙箱环境,无法访问文件、网络、系统等敏感资源。
- 不支持 Lua 5.2/5.3 新特性,如 goto、bit32 等。
- 推荐用法:聚合、遍历、条件判断、table 操作等常规 Lua 5.1 语法均可放心使用。
示例:
1
2
3
4
5
| local arr = {}
table.insert(arr, 1)
for i, v in ipairs(arr) do
print(i, v)
end
|
如需更复杂的聚合逻辑,可参考 gopher-lua 官方文档 和 Lua 5.1 语法手册。
8. 参考资料