mcpField
K
kubebuilder-api-design

kubebuilder-api-design

github.com/configbutler开发045 次安装8 周前更新
代码仓库

关于 kubebuilder-api-design

kubebuilder-api-design 是使用 Kubebuilder 以 Go 设计 Kubernetes API 的技能,重点涵盖 CRD 类型、标记和状态。它专注于 API 结构与 CRD 生成,不负责控制器或 Webhook 业务逻辑。

主要功能

  1. 01起草 CRD 的 Go API 类型
  2. 02添加验证和 Schema 标记
  3. 03设计状态与条件
  4. 04建模对象引用和列表语义
  5. 05指导 CRD 生成与验证

适用场景

  1. 01设计新的 Kubernetes Operator API
  2. 02为 CRD 字段规定验证与默认值
  3. 03检查生成的 CRD Schema 和列表行为
  4. 04规划协调资源的状态条件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/configbutler/skills --skill kubebuilder-api-design

安装后在 Claude Code 中输入/kubebuilder-api-design确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api_reference.md
go-type-patterns.md
kubebuilder-markers.md
kubebuilder-workflow-essentials.md
status-and-conditions.md

详细介绍

Kubebuilder API 设计(Go)

使用 Kubebuilder 在 Go 中设计 Kubernetes API(主要用于 Kubernetes Operator):CRD 类型定义、Schema 标记、状态/条件,以及核心的脚手架生成/重新生成工作流。

默认范围:API 设计 + CRD 生成。除非明确提出要求,否则不实现控制器/Webhook 业务逻辑。

工具假设(生成所需的环境)

无需运行任何工具,本技能即可协助完成纯 API 设计(Go 类型 + 标记);但要生成脚手架并重新生成 CRD/清单,用户的环境/项目通常需要具备:

  • go 工具链(符合项目 go.mod 的要求)
  • kubebuilder CLI(或封装了 Kubebuilder 的 Operator SDK)
  • make(Kubebuilder 项目通过 Makefile 驱动生成)

说明:

  • controller-gen 通常由项目的 Makefile 目标自动安装(并锁定版本),因此不一定是单独的前置条件。
  • 只有在用户希望针对集群运行/测试时才需要集群工具(kubectl、kind 等);除非明确提出要求,否则不在此范围内。
与 k8s-crd-design-review 的关系

将生成的 CRD YAML 视为已编译的 API 契约。设计好 Go 类型和标记并运行生成后,使用 ../k8s-crd-design-review/SKILL.md 对生成的 CRD YAML(或差异)进行设计审查。

SSA / GitOps 说明:列表语义属于 API 契约的一部分。

版本控制 / 多版本 CRD(参考)

如果用户正在设计多版本 API(例如,v1alpha1 → v1beta1 → v1)或需要转换 Webhook:

在 Spec/Status 中设计关系(对象引用)

当 CRD 需要指向另一个 Kubernetes 对象(或其字段/键)时,应将“引用”视为 API 设计,而不是方便起见的导入。

优先使用作用域明确、由 API 自行定义的引用类型(避免使用通用核心类型)

避免在新 API 中嵌入通用 Kubernetes 引用结构体,例如 corev1.LocalObjectReference 或 corev1.ObjectReference。

Kubernetes 上游明确不鼓励在新代码中使用 corev1.LocalObjectReference 和 corev1.ObjectReference,因为它们的定义不够明确,且难以针对不同用法进行验证/文档说明:

  • 要点:“不要使用这些通用类型,而应创建一个本地提供并使用、专门针对你的引用的类型。”

此建议同样适用于你可能在旧 API 中遇到的其他过于通用的引用类型(它们往往语义不明、验证方式不一致,且默认值处理不便)。

模式:为每种关系定义专用的 <Thing>Ref 类型

针对你的 CRD,为每种关系定义一个小型的、专门设计的结构体:

  • 让必填字段确实为必填字段(不要照搬上游为向后兼容而采用的技巧,例如 omitempty + 默认空字符串)
  • 在架构中编码关系的实际约束(名称格式、允许的 Kind、命名空间规则)
  • 为每个字段添加符合领域语义的文档说明(让 kubectl explain 真正有用)

示例(按名称引用同一命名空间中的对象):

// ConfigMapRef identifies a ConfigMap in the same namespace.
// The referenced ConfigMap must exist before this resource becomes Ready.
type ConfigMapRef struct {
    // Name is the name of the referenced ConfigMap.
    // +kubebuilder:validation:MinLength=1
    // Consider adding a stricter pattern if you want to enforce DNS-1123 label.
    Name string `json:"name"`
}

示例(如果设计上允许跨命名空间,则使用命名空间 + 名称):

// SecretRef identifies a Secret.
// If Namespace is omitted, it defaults to the resource namespace.
type SecretRef struct {
    // +kubebuilder:validation:MinLength=1
    Name string `json:"name"`

    // +optional
    // +kubebuilder:validation:MinLength=1
    Namespace string `json:"namespace,omitempty"`
}
预先确定并记录引用语义

对于每种关系,都要明确选择并记录:

  • 作用范围:仅限同一命名空间,还是允许跨命名空间(跨命名空间通常需要额外的授权/保护措施)
  • 标识:仅名称、名称 + 命名空间,还是(少数情况下)UID/resourceVersion(大多数 API 应采用名称/命名空间)
  • 允许的目标:固定 Kind(推荐),还是“一组选一”的 Kind(如果选择后者,应明确建模)
  • 生命周期行为:目标缺失、改名、删除或重新创建时会发生什么
  • 状态映射:如果要公开已解析的详细信息(例如已观测到的 UID),请将其放入 Status,而不是 Spec

如果用户要求“引用任意对象”,应提出异议并缩小范围:要求指定一个 Kind 或一小组明确的 Kind,然后在 API 类型中体现这一点。

工作流

步骤 0 — 收集输入(只询问必要信息)
  1. API 身份信息:Group、Version、Kind、Plural、Scope(Namespaced 或 Cluster)
  2. 期望的 Spec 字段(包括哪些字段必填)以及任何不可变性要求
  3. Status 需求:conditions?observedGeneration?摘要字段?
  4. 任何约束:枚举值、范围、模式、最大项数、唯一性、对其他对象的引用

当用户提到关系/引用时,记录:

  • 目标 Kind,以及是否允许跨命名空间
  • 引用是否为必填
  • 需要引用整个对象还是子字段(例如 secretKeyRef)
  • 目标不存在或发生变化时的预期行为

如果用户已有 CRD 的 YAML,应将其视为契约,并映射为 Go 类型 + 标记。

步骤 1 — 起草 Go API 类型

创建:

  • type <Kind>Spec struct { ... }
  • type <Kind>Status struct { ... }
  • type <Kind> struct { metav1.TypeMeta; metav1.ObjectMeta; Spec; Status }
  • type <Kind>List struct { metav1.TypeMeta; metav1.ListMeta; Items []<Kind> }

经验法则:

  • 对可选标量和可选结构体使用指针,以保留“未设置”和零值之间的区别。
  • 相关情况下优先使用 Kubernetes 原生类型(metav1.Time、resource.Quantity、intstr.IntOrString)。
  • 将 Status 与 Spec 分开。适用时包含 ObservedGeneration 和 Conditions。
  • 对于关系,优先使用 API 自有的 <Thing>Ref 结构体,而不是嵌入通用的 Kubernetes 引用类型(参见“设计关系”)。

阅读 ./references/go-type-patterns.md,了解常见的 Go/Kubernetes 类型选择。

步骤 2 — 添加 Kubebuilder 标记(验证、默认值、打印)

添加标记以匹配期望的 API 契约:

  • 根对象 + 子资源:
    • +kubebuilder:object:root=true
    • +kubebuilder:subresource:status
  • 字段上的验证 + 默认值(最小值/最大值、模式、枚举、长度、项数等)
  • SSA 和正确性所需的列表语义(listType=set|map、listMapKey=...)
  • 打印列,以便一目了然地显示最重要的状态/规范信息

阅读 ./references/kubebuilder-markers.md。

如需快速了解“我需要什么标记?”(根标记、字段验证/默认值、列表语义和打印列),请参阅 ./references/api_reference.md。

第 3 步 — 设计状态和条件

除非有充分理由自定义条件类型,否则优先使用 []metav1.Condition。仅在有助于提升用户体验时,才添加辅助摘要字段。

对于长期运行且由控制器协调的资源,应按与 kstatus 兼容的就绪状态进行设计:用 Ready 作为聚合信号,用 Reconciling 表示正在推进,用 Stalled 表示推进受阻或出现故障,并在状态新鲜度至关重要的地方使用 observedGeneration。

阅读 ./references/status-and-conditions.md(Kubebuilder/Go 实现附录)。关于规范的概念语义和评审启发式,请参考 k8s-crd-design-review/references/conditions-and-status.md;尤其是 ../k8s-crd-design-review/references/kstatus-readiness.md,其中介绍了适配 Flux/Argo/kstatus 的 CRD。

第 3.5 步 — Kubebuilder 工作流要点(脚手架搭建 + 代码生成)

如果用户需要 Kubebuilder 脚手架搭建和重新生成方面的帮助(而非控制器/Webhook 业务逻辑),请遵循 ./references/kubebuilder-workflow-essentials.md 中的简短检查清单。

第 4 步 — 提供“生成 + 验证”检查清单(不要实现)

向用户提供重新生成 CRD 并验证架构的标准 Kubebuilder 步骤,不要编写控制器逻辑:

  • 运行 make generate / make manifests
  • 检查生成的 CRD YAML 并确认:
    • 必填字段符合预期
    • 默认值出现在预期的位置
    • 列语义和映射键正确
    • 打印列能正常显示

然后(建议):使用 ../k8s-crd-design-review/SKILL.md,对生成的 CRD YAML(或差异)进行一次契约评审,重点关注兼容性/迁移影响、生命周期/状态语义,以及 SSA/GitOps 易用性。

如果用户需要更多 API 形状方面的指导,请指向Kubernetes API 约定的官方长篇文档,尤其是 Spec 和 Status 和典型状态属性。

输出格式

交付代码时,每个文件输出一个 Go 代码片段:

  1. package + imports
  2. 标记
  3. Spec、Status
  4. 根对象 + 列表
  5. 任何类型别名和嵌套结构体

注释应简洁。代码后用简短的项目符号说明设计理由(例如为何使用指针、为何使用 listType map 等)。

资源

Kubebuilder 手册(本仓库中的上游文档镜像)

如需了解规范的 Kubebuilder 说明(超出本技能的速查内容),请优先参考以下页面:

references/

仅在需要时加载这些内容(以减少上下文占用):


此技能目前仅包含 references/。稍后可根据需要添加 scripts/ 或 assets/,用于自动化辅助工具或样板模板。

评论

支持 Markdown