后端与接口
编写 grafana-app-sdk 的…
适用于在 grafana-app-sdk 应用中实现协调循环、Watcher、UnmanagedKinds 或把控制器注册进 app.go 的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
编写 grafana-app-sdk 的特定
解决思路
- 用 `grafana-app-sdk project component add operator` 为 standalone app 生成 operator stubs。
- 实现 `ReconcileFunc`,参考 TypedReconciler 模式。
- 在 `app.go` 中注册 reconciler,参考 `references/registration.md`。
- 运行 `grafana-app-sdk generate`,再执行 `go build ./...` 和 `go run ./cmd/operator` 验证;用 `kubectl-apply` 创建资源时应能在日志中看到 reconcile 条目。
- 如果 operator 启动但创建资源不触发 reconcile,检查 `BasicReconcileOptions.Namespace` 是否与资源 namespace 匹配。
- 检查 `BasicReconcileOptions.LabelFilters` / `FieldSelectors`;多数“无事件”是过滤器不匹配,可用 `kubectl get <resource> -o yaml` 查看 labels。
- 确认 reconciler 已绑定到正确的、最新的 kind version。
- 优先使用 `operator.TypedReconciler[*v1alpha1.MyKind]`,它处理类型断言并提供强类型 `ReconcileFunc`。
- 定义 reconciler struct,内嵌 `operator.TypedReconciler[*v1alpha1.MyKind]` 并持有 `client resource.Client`;在构造函数中设置 `r.ReconcileFunc = r.reconcile`。
- 实现 `reconcile(ctx context.Context, req operator.TypedReconcileRequest[*v1alpha1.MyKind]) (operator.ReconcileResult, error)`,先取 `obj := req.Object`。
- 在 reconcile 顶部做 generation-based skip:当 `obj.GetGeneration() == obj.Status.LastObservedGeneration` 且 `req.Action != operator.ReconcileActionDeleted` 时返回 `operator.ReconcileResult{}, nil`。
- 创建上下文字段 logger:`logging.FromContext(ctx).With("name", obj.GetName(), "namespace", obj.GetNamespace())`,并 `log.Info("reconciling", "action", operator.ResourceActionFromReconcileAction(req.Action))`。
- 如果 `req.Action == operator.ReconcileActionDeleted`,在示例模式中返回 `operator.ReconcileResult{}, nil`;如需删除清理逻辑则在此处理。
- 执行业务逻辑。
- 状态更新使用 `resource.UpdateObject`:传入 `ctx`、`r.client`、`obj.GetStaticMetadata().Identifier()`,在更新函数中设置 `obj.Status.LastObservedGeneration = obj.GetGeneration()`、`obj.Status.State = "Ready"` 等,并使用 `resource.UpdateOptions{Subresource: "status"}`。
- 使用 `ReconcileAction` 值时区分 `ReconcileActionCreated`、`ReconcileActionUpdated`、`ReconcileActionDeleted`、`ReconcileActionResynced`。
- 需要延迟重新入队时返回 `operator.ReconcileResult{RequeueAfter: 10 * time.Second}, nil`,例如轮询外部系统。
- 状态写入始终使用 `resource.UpdateObject`,因为它会先获取最新版本再应用更新函数,避免多个 reconcile 事件竞争导致 `409 Conflict`。
- 不要用 `client.Update` 写状态,因为它发送完整对象,会与用户对 spec 的修改竞争。
- 在 `AppManagedKind` 条目上用 `simple.BasicReconcileOptions` 控制 informer 行为:`Namespace` 指定只 watch 一个 namespace(默认是所有 namespace)、`LabelFilters` 如 `[]string{"env=prod"}` 只协调匹配资源、`FieldSelectors` 如 `[]string{"status.phase=Running"}`、`UsePlain` 控制包装。
- `UsePlain: false` 是默认值,会把 reconciler 包装进 `OpinionatedReconciler`,自动管理 finalizers,使 SDK 能保证干净删除。
- 需要事件风格处理时使用 `Watcher`(Add/Update/Delete 回调),并参考 `references/watchers.md` 中的 Watcher vs Reconciler 决策矩阵选择。
- 需要协调应用不拥有的资源时使用 `UnmanagedKinds`,遵循 `UseOpinionated: false` 指导并留意 `references/unmanaged-kinds.md` 中的常见失败模式。
- 在 `app.go` 完成完整 wiring:client setup、多版本注册、`ValidateManifest`,并留意 `references/registration.md` 中的常见失败模式。
- 需要更多资料时查看 `grafana-app-sdk GitHub` 和 `operator package docs`。
适用边界 · 注意事项
- 不适用于非 grafana-app-sdk 或非 Kubernetes 控制器场景。
- 如果只需要同步请求-响应逻辑,不需要监听/协调资源状态变化,则不需要 Reconciler/Watcher。
- 无法使用 Go 工具链或 grafana-app-sdk 的项目不应直接采用。