核心概念

  1. ResourceGraphDefinition (RGD) 的 schema 部分定义了自定义 API 的形状
  2. 创建一个 RGD 时,kro 会基于这个 schema 生成一个 CRD,用户就可以实例化这个 CRD

核心功能

API 身份标识

生成的 CRD API 将是 mycompany.io/v1alpha1,资源名为 applications.mycompany.io

1
2
3
4
schema:
apiVersion: v1alpha1 # API 版本
kind: Application # 资源类型
group: mycompany.io # API 组(可选,默认 kro.run)

作用域

1
2
schema:
scope: Cluster # 或 Namespaced(默认)
描述
Namespaced 实例存在于 namespace 内(默认)
Cluster 实例是集群级别的
  1. 使用 scope: Cluster 时,所有 namespaced 资源必须显式设置 metadata.namespace
  2. 否则 kro 会在 RGD 创建验证失败

Spec 字段(用户输入)

使用 SimpleSchema 语法定义用户可配置的字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spec:
# 基础类型 + 验证
name: string | required=true
replicas: integer | default=3 minimum=1 maximum=100
enabled: boolean | default=false

# 结构化类型
ingress:
enabled: boolean | default=false
host: string

# 集合类型
env: "map[string]string"
ports: "[]integer"

常用验证标记

  • required=true - 必填字段
  • default=value - 默认值
  • minimum/maximum - 数值约束
  • enum=”val1,val2” - 枚举值
  • pattern=”regex” - 正则验证

Status 字段(运行时状态)

使用 CEL 表达式被管理资源提取状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
status:
# 直接引用资源字段
availableReplicas: ${deployment.status.availableReplicas}

# 嵌套值提取
serviceIP: ${service.spec.clusterIP}

# 复合值构造
endpoint: "http://${service.status.loadBalancer.ingress[0].hostname}"

# CEL 函数
isHealthy: ${deployment.status.availableReplicas >= deployment.spec.replicas}

# 数组过滤
readyPods: ${deployment.status.conditions.filter(c, c.type == "Ready")}

kro 自动处理的字段

conditionsstate 不可覆盖

1
2
3
4
status:
# 自动添加,不可覆盖
conditions: [...] # 追踪实例状态的条件数组
state: ACTIVE # ACTIVE | IN_PROGRESS | FAILED | DELETING | ERROR

完整工作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ RGD Schema │───▶│ CRD 生成 │───▶│ 用户创建实例 │
│ SimpleSchema │ │ OpenAPI v3 │ │ kubectl apply │
└─────────────────┘ └──────────────────┘ └─────────────────┘


┌─────────────────┐
│ Kubernetes 验证 │
│ 类型检查/必填 │
└─────────────────┘


┌─────────────────┐
│ kro 处理 │
│ CEL 表达式求值 │
│ 状态持续更新 │
└─────────────────┘

高级特性

自定义类型

1
2
3
4
5
6
7
8
9
10
schema:
types:
ContainerConfig:
image: string | required=true
tag: string | default="latest"
env: "map[string]string"

spec:
primary: ContainerConfig
sidecars: "[]ContainerConfig" # 类型复用

递归类型

kro 会自动解析依赖检测循环引用

1
2
3
4
5
6
7
8
schema:
types:
Address:
street: string
city: string
Person:
name: string
address: Address # 引用其他自定义类型

Additional Printer Columns

控制 kubectl get 的输出列

1
2
3
4
5
6
7
8
schema:
additionalPrinterColumns:
- name: Replicas
type: integer
jsonPath: .spec.replicas
- name: Available
type: integer
jsonPath: .status.availableReplicas
1
2
3
输出效果:
NAME REPLICAS AVAILABLE AGE
my-app 5 5 10m

CRD 元数据

标签注释会应用到 CRD 本身,而不是实例

1
2
3
4
5
6
7
schema:
metadata:
labels:
team: platform
managed-by: kro
annotations:
description: "Application resource for managing web applications"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
graph TB
subgraph "User Creates"
RGD["ResourceGraphDefinition (RGD)<br/>apiVersion: kro.run/v1alpha1"]
end

RGD -->|"contains"| SCHEMA["schema:<br/>- apiVersion, kind<br/>- spec, status<br/>- metadata"]

SCHEMA -->|"generates"| CRD["CustomResourceDefinition (CRD)<br/>Generated by kro"]

SCHEMA_METADATA["schema.metadata<br/>{labels, annotations}"] -->|"applies to"| CRD

CRD -->|"defines schema for"| INSTANCE["Custom Resource Instances<br/>{Application, WebApp, etc.}"]

INSTANCE_METADATA["instance.metadata<br/>{name, namespace, labels}"] -->|"applies to"| INSTANCE

style RGD fill:#e1f5fe
style SCHEMA fill:#fff3e0
style SCHEMA_METADATA fill:#ffe0b2
style CRD fill:#c8e6c9
style INSTANCE fill:#f3e5f5
style INSTANCE_METADATA fill:#e1bee7

classDef dotted stroke-dasharray: 5 5
class SCHEMA_METADATA,INSTANCE_METADATA dotted
位置 应用目标 示例
schema.metadata CRD 本身 team: platform, managed-by: kro
实例的 metadata 具体实例 name: my-app, namespace: prod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
graph LR
subgraph "CRD Level"
CRD_OBJ["CustomResourceDefinition<br/>{kind: Application}"]
CRD_LABELS["labels:<br/>team: platform<br/>managed-by: kro"]
end

subgraph "Instance Level"
APP1["app-one<br/>{name: app-one}"]
APP2["app-two<br/>{name: app-two}"]
end

CRD_OBJ -. "owns" .- APP1
CRD_OBJ -. "owns" .- APP2
CRD_LABELS --> CRD_OBJ

style CRD_OBJ fill:#c8e6c9
style CRD_LABELS fill:#a5d6a7
style APP1 fill:#f3e5f5
style APP2 fill:#f3e5f5

更新与兼容性

更新 RGD 的 schema 时,kro 会检查变更是否与现有实例兼容,破坏性变更(默认被阻止

  1. 删除字段
  2. 修改字段类型
  3. 添加必填字段无默认值

需要通过 Breaking Changes 机制显式允许这些变更