概述

KRO 是 Kubernetes SIG Cloud Provider 下的子项目,旨在简化 Kubernetes 中复杂自定义资源创建管理

核心概念

KRO 的核心自定义资源ResourceGraphDefinition - RGD,它允许你:

  1. 多个 Kubernetes 资源组合成一个可复用的组件
  2. 定义资源之间依赖关系
  3. 为这些资源提供默认配置

工作原理

主要优势

特性 说明
Kubernetes 原生 无缝集成现有工具链,保留熟悉的操作流程
厂商无关 不依赖任何特定云厂商
统一管理 通过一个 CRD 管理多个关联资源
依赖解析 自动处理资源间依赖关系创建顺序

使用场景

  1. 假设你需要部署一个典型的三层应用(前端 + 后端 + 数据库)
  2. 通常需要分别创建 Deployment、Service、ConfigMap、Secret 等多个资源,

使用 KRO 后,用户只需创建一个基于该 RGD资源实例,KRO 就会自动创建和管理所有底层资源

1
2
3
4
5
6
7
8
9
10
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: webapp
spec:
resources:
# 一次定义,包含所有相关资源
- deployment: {...}
- service: {...}
- configmap: {...}

核心价值

  1. KRO 的价值在于将复杂的多资源组合抽象单一的自定义资源
  2. 让应用开发者能够以更简洁的方式定义和管理 Kubernetes 上的复杂应用栈

常见问题

KRO 是什么?

Kube Resource Orchestrator (KRO) 是一个 Kubernetes Operator,用于简化复杂 Kubernetes 资源配置的创建

核心要素

概念 说明
ResourceGraphDefinition (RGD) KRO 的基础自定义资源
资源组 多个 K8s 资源组合成一个逻辑单元
功能关系 定义资源之间依赖关联

工作流程

KRO 如何工作?

核心机制

关键设计

特性 说明
原生 K8s 原语 使用 K8s 核心能力,无额外依赖
动态 CRD 生成 自动为每个 RGD 创建对应的 CRD
微控制器架构 每个 RGD专用的控制器管理实例

如何使用 KRO?

基本步骤

1
定义 → 应用 → 创建实例 → 自动管理

示例场景

简单场景:WebApp

复杂场景:WebAppWithDB (组合现有 RGD)

使用流程总结

步骤 操作 KRO 自动处理
1 编写 ResourceGraphDefinition YAML -
2 kubectl apply RGD 到集群 创建 CRD
3 部署微控制器 部署控制器
4 创建 CRD 实例 管理所有底层资源

为什么构建这个项目?

问题背景

痛点 说明 KRO 解决方案
多资源协同 需要同时管理多个相关资源 统一资源组,一次性管理
依赖复杂 资源间依赖关系难以维护 自动解析依赖,智能编排
编排困难 规模扩大后手动管理复杂 微控制器自动管理生命周期
配置繁琐 重复配置相似资源组合 可复用ResourceGraphDefinition

设计目标

目标 说明
简化构建 降低 K8s 上层应用开发的复杂度
依赖管理 自动处理资源间的依赖关系
可扩展性 支持简单复杂的自定义资源
标准化 提供统一可复用资源组合方式

API 变更说明

当前状态

1
2
3
API 版本: v1alpha1
状态: 早期开发阶段
稳定性: 可能有破坏性变更

承诺与保障

使用建议

注意事项 说明
跟进更新 关注版本发布和变更日志
测试迁移 在升级前测试新的 API 版本
社区反馈 参与项目讨论,影响 API 设计

总结

方面 核心要点
定位 简化复杂 K8s 资源编排的 Operator
机制 动态 CRD 生成 + 微控制器管理
价值 统一资源组合 + 自动依赖解析
现状 v1alpha1,积极开发中
适用 需要管理多资源组合应用开发者

What is kro?

KRO 是什么?

KRO 的本质

1
将一组 Kubernetes 资源 → 可复用的 API

三步定义流程

步骤 操作 说明
定义 API Schema 描述用户接口输入参数
YAML 描述资源 定义底层 Kubernetes 资源
CEL 表达式连接 CEL参数绑定到资源

KRO 自动完成的工作 - Schema + Resources + CEL

ResourceGraphDefinition (RGD) 详解

RGD 的角色

RGD = 蓝图

Key Value
描述接口 用户交互的界面
描述资源输出 每个实例应生成的资源

RGD 组成结构

组件 作用 示例
API Schema 定义用户可见的接口 replicas, image, port
Resources 声明底层 K8s 资源 Deployment, Service, ConfigMap
CEL 表达式 连接参数资源 spec.replicas → deployment.spec.replicas

提前验证机制

验证时机

Key Value
传统方式 运行时才发现错误
RGD 方式 定义时捕获错误

验证内容

错误类型 RGD 验证时机 传统方式
Schema 错误 定义时 ❌→✅ 运行时
CEL 表达式无效 定义时 ❌→✅ 运行时
引用错误 定义时 ❌→✅ 运行时

价值对比

完整工作流示例

示例:定义一个 WebApp RGD

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
# 1. API Schema - 用户接口
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: webapp
spec:
schema:
# 用户可配置的参数
properties:
replicas:
type: integer
image:
type: string
port:
type: integer

# 2. Resources - 底层资源
resources:
- deployment:
spec:
replicas: "${spec.replicas}" # 3. CEL 表达式
template:
spec:
containers:
- image: "${spec.image}"

- service:
spec:
ports:
- port: "${spec.port}"

从定义到运行

核心价值总结

特性 传统 Operator 开发 KRO 方式
定义方式 手写 Go 代码 + CRD YAML + CEL
验证时机 运行时 定义时
学习曲线 陡峭(需要掌握 Controller-Runtime 平缓(YAML + CEL)
开发速度
维护成本
复用性 需要额外设计 天然支持 RGD 组合

image-20260428180342243

How it works

RGD 的两个核心部分

Schema vs Resource Templates

方面 Schema Resource Templates
作用 定义 API 接口 描述底层资源
目标用户 终端用户 kro 内部处理
内容 字段名类型默认值 K8s 资源 YAML + CEL
示例 replicas: integer replicas: “${spec.replicas}”

CEL 表达式的连接作用

CEL 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Schema 部分
schema:
properties:
replicas: { type: integer }
image: { type: string }
port: { type: integer }

# Resource Templates 部分
resources:
- deployment:
spec:
replicas: "${spec.replicas}" # CEL 引用
template:
spec:
containers:
- image: "${spec.image}" # CEL 引用
ports:
- containerPort: "${spec.port}" # CEL 引用

kro 的处理流程

详细步骤说明

步骤 操作 说明
解析 CEL 分析所有 CEL 表达式 提取字段引用关系
推断依赖图 基于表达式构建依赖 确定资源创建顺序
生成 CRD 自动创建 OpenAPI schema 注册到 Kubernetes API
启动 Controller 部署专用微控制器 监听实例变化
运行时 全部动态完成 无需预编译重启

依赖图推断示例

输入:RGD 定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
resources:
- configMap: # 资源 1
data:
config: "${spec.config}"

- deployment: # 资源 2(依赖 ConfigMap)
spec:
template:
spec:
containers:
- envFrom:
- configMapRef:
name: "${configMap.metadata.name}"

- service: # 资源 3(依赖 Deployment)
spec:
selector:
app: "${deployment.metadata.labels.app}"

kro 自动推断的依赖图

创建顺序

顺序 资源 原因
1 ConfigMap 无依赖,首先创建
2 Deployment 引用 ConfigMap
3 Service 引用 Deployment 的 label

运行时生成的意义

维度 传统 Operator KRO
开发语言 Go YAML + CEL
构建流程 编译构建部署二进制 直接应用动态生成
修改生效 ❌ 需重新编译 ✅ 修改即生效
技能要求 ❌ 需掌握 Go ✅ 只需 YAML + CEL
开发周期 ❌ 周期长 ✅ 快速迭代

官方示例

image-20260428183119629

image-20260428182948197

In practice

用户视角:使用生成的 API

创建 WebApp 实例

1
2
3
4
5
6
7
apiVersion: kro.run/v1alpha1
kind: WebApp
metadata:
name: my-app
spec:
image: nginx
bucketName: my-app-assets

kro 自动创建的资源

查看状态反馈

1
2
3
$ kubectl get webapp my-app -o yaml
status:
bucketArn: arn:aws:s3:::my-app-assets # kro 回写有用信息

RGD 定义结构解析

完整结构图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────────────────────┐
│ ResourceGraphDefinition: webapp │
├─────────────────────────────────────────────────────────────┤
│ │
│ spec.schema │
│ ├─ apiVersion: v1alpha1 │
│ ├─ kind: WebApp │
│ ├─ spec: │
│ │ ├─ image: string (default=nginx) │
│ │ └─ bucketName: string │
│ └─ status: │
│ └─ bucketArn: ${bucket.status.arn} ◄── CEL 输出 │
│ │
│ spec.resources │
│ ├─ config (ConfigMap) │
│ ├─ bucket (S3 Bucket) │
│ ├─ deployment (Deployment) │
│ └─ service (Service) │
│ │
└─────────────────────────────────────────────────────────────┘

Schema 部分:定义 API

字段 类型 默认值 说明
image string nginx 容器镜像
bucketName string 必填 S3 存储桶名称
status.bucketArn - - 输出:存储桶 ARN

资源模板详解

资源 1:ConfigMap

1
2
3
4
5
6
7
8
- id: config
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${schema.metadata.name}-config # 引用实例名称
data:
APP_NAME: ${schema.metadata.name}
1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────────────────────────────────────────────────┐
│ ConfigMap 生成逻辑 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 输入: metadata.name = "my-app" │
│ │ │
│ ▼ │
│ ${schema.metadata.name} → my-app │
│ ${schema.metadata.name}-config → my-app-config │
│ │
│ 输出: ConfigMap named "my-app-config" │
│ │
└─────────────────────────────────────────────────────────────┘

资源 2:S3 Bucket

1
2
3
4
5
6
7
8
- id: bucket
template:
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
name: ${schema.spec.bucketName}
spec:
name: ${schema.spec.bucketName}
1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────────────────────────────────────────────────┐
│ Bucket 生成逻辑 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 输入: spec.bucketName = "my-app-assets" │
│ │ │
│ ▼ │
│ ${schema.spec.bucketName} → my-app-assets │
│ │
│ 输出: S3 Bucket named "my-app-assets" │
│ 状态: bucket.status.arn (异步生成) │
│ │
└─────────────────────────────────────────────────────────────┘

资源 3:Deployment

1
2
3
4
5
6
7
8
9
10
11
12
- id: deployment
template:
spec:
containers:
- name: app
image: ${schema.spec.image} # 引用用户输入
envFrom:
- configMapRef:
name: ${config.metadata.name} # 引用 ConfigMap
env:
- name: BUCKET_ARN
value: ${bucket.status.arn} # 引用 Bucket 状态

资源 4:Service

1
2
3
4
- id: service
template:
spec:
selector: ${deployment.spec.selector.matchLabels} # 引用 Deployment

kro 的依赖解析

自动推断的依赖图

创建顺序与时序

依赖规则总结

资源 依赖 原因
ConfigMap 独立资源
Bucket 独立资源
Deployment ConfigMap ${config.metadata.name}
Deployment Bucket ${bucket.status.arn}
Service Deployment ${deployment.spec.selector}

kro 的智能等待机制

异步状态处理

1
2
3
4
5
6
7
8
9
10
11
┌─────────────────────────────────────────────────────────────┐
│ bucket.status.arn 的生命周期 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. apply RGD → Bucket 创建开始 │
│ 2. Bucket Provisioning → status.arn: null │
│ 3. kro 等待 → Deployment 暂停创建 │
│ 4. Bucket Ready → status.arn: "arn:aws:..." │
│ 5. kro 检测到 → Deployment 继续创建 │
│ │
└─────────────────────────────────────────────────────────────┘

kro 如何知道依赖关系

CEL 引用类型 kro 推断
${schema.spec.*} 用户输入,无依赖
${config.metadata.name} 依赖 config 资源
${bucket.status.arn} 依赖 bucket 及其状态
${deployment.spec.selector} 依赖 deployment 资源

资源引用映射表

资源 ID 类型 引用的变量 依赖
config ConfigMap ${schema.metadata.name}
bucket Bucket ${schema.spec.bucketName}
deployment Deployment ${schema.spec.image}
${config.metadata.name}
${bucket.status.arn}
config
bucket
service Service ${deployment.spec.selector} deployment

关键要点

特性 说明
1 个实例 → N 个资源 用户创建 1 个 WebApp,kro 创建 4 个底层资源
双向绑定 spec 输入参数status 回写状态
自动依赖解析 kro 分析 CEL 表达式自动推断依赖图
智能等待 等待异步状态(如 bucketArn)就绪后再继续
任意资源 支持原生 K8s 资源任何 CRD(ACK/ASO/Config Connector)
统一接口 复杂的多资源组合简化为单一 API

What kro handles for you

Simple Schema - 内联 API 定义

传统方式 vs KRO

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
┌─────────────────────────────────────────────────────────────┐
│ 传统 OpenAPI Schema vs KRO Simple Schema │
├─────────────────────────────────────────────────────────────┤
│ │
│ 传统 OpenAPI (冗长): KRO Simple Schema (简洁): │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ openAPI: 3.0.0 │ │ spec: │ │
│ │ info: │ │ replicas: int | │ │
│ │ title: WebApp │ │ default=1 │ │
│ │ version: 1.0.0 │ │ image: string | │ │
│ │ paths: {...} │ │ required │ │
│ │ components: │ │ port: int | │ │
│ │ schemas: │ │ min=1 max=65535 │ │
│ │ WebAppSpec: │ │ │ │
│ │ type: object │ └─────────────────────┘ │
│ │ properties: │ │
│ │ replicas: │ 一行搞定! │
│ │ type: │ │
│ │ integer │ │
│ │ image: │ │
│ │ type: │ │
│ │ string │ │
│ │ required: │ │
│ │ - image │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

语法示例

特征 语法 示例
类型声明 fieldName: type replicas: int
默认值 ` default=value`
必填 required `image: string
约束 min= max= `port: int
组合 链式约束 `count: int

Wires data that doesn’t exist yet - 连接尚不存在的数据

问题场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────────────────┐
│ 异步资源创建的"鸡生蛋"问题 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Deployment 需要 │
│ bucketArn ←─────────────────────────────┐ │
│ │ │ │
│ │ 但 Bucket 还没创建! │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ Bucket │ │ │
│ │ (异步创建) │ ─────────────────────────┘ │
│ │ │ status.arn 稍后才可用 │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

kro 的解决方案

对比

方式 传统 Controller KRO
处理异步 手写 Reconcile 循环 + 重试逻辑 自动等待
代码量 ~50-100 行 1 行 CEL
错误处理 需要处理超时失败 内置处理

Infers ordering from expressions - 从表达式推断顺序

无需声明顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────────────────┐
│ 传统方式 vs KRO │
├─────────────────────────────────────────────────────────────┤
│ │
│ 传统方式: KRO: │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ resources: │ │ resources: │ │
│ │ - name: db │ │ - db │ │
│ │ order: 1 │ │ connStr: │ │
│ │ - name: app │ │ ${db. │ │
│ │ order: 2 │ │ connStr} │ │
│ │ dependsOn: │ │ - app │ │
│ │ - db │ │ image: ... │ │
│ └─────────────────┘ └─────────────────┘ │
│ ❌ 手动管理顺序 ✅ CEL 自动推断 │
│ │
└─────────────────────────────────────────────────────────────┘

推断示例

1
2
3
4
5
6
7
8
9
resources:
- id: db
template: ...

- id: app
template:
env:
- name: DB_CONN
value: ${db.status.connString} # ← 引用 db,自动推断依赖

依赖图自动生成

Conditional resources - 条件资源

语法

1
2
3
4
5
6
7
8
9
10
11
12
resources:
- id: standardStorage
if: "${schema.storageType == 'standard'}" # 条件表达式
template:
spec:
storageClass: standard

- id: premiumStorage
if: "${schema.storageType == 'premium'}" # 条件表达式
template:
spec:
storageClass: premium

行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌─────────────────────────────────────────────────────────────┐
│ 条件资源的级联跳过 │
├─────────────────────────────────────────────────────────────┤
│ │
│ storageType = "standard" │
│ │ │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ standardStorage │ ──────▶ │ 依赖它的资源 │ │
│ │ ✅ 创建 │ │ ✅ 创建 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ premiumStorage │ ──────▶ │ 依赖它的资源 │ │
│ │ ⏭️ 跳过 │ │ ⏭️ 跳过 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

级联跳过示例

One template, many resources - forEach

语法

1
2
3
4
5
6
7
8
9
10
resources:
- id: shards
forEach: "${range(0, schema.replicas)}" # 生成多个资源
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${schema.metadata.name}-shard-${forEach.index}
data:
shardId: ${forEach.index}

效果

1
2
3
4
5
6
输入: replicas = 3

输出:
├─ ConfigMap: my-app-shard-0 (index=0)
├─ ConfigMap: my-app-shard-1 (index=1)
└─ ConfigMap: my-app-shard-2 (index=2)

forEach 变量

变量 说明 示例
${forEach.index} 当前索引 0, 1, 2, …
${forEach.value} 当前值 遍历列表时的元素
${forEach.key} 当前键 遍历对象时的键

Non-Turing complete by design - 非图灵完备设计

图灵完备

基本定义

  1. 图灵完备是指一个计算系统能够模拟图灵机的所有功能
  2. 简单来说:只要一个系统图灵完备,它就能计算任何可计算的函数
1
2
3
4
5
6
7
8
9
┌─────────────────────────────────────────────────────────────┐
│ 图灵机 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 由 Alan Turing 于 1936 年提出 │
│ 是现代计算机的理论模型 │
│ 图灵完备 = 具备通用计算能力 │
│ │
└─────────────────────────────────────────────────────────────┘

图灵完备的必要条件

一个系统要成为图灵完备,通常需要具备

条件 说明 示例
条件分支 if/else 判断 if x > 0 { … }
无限循环 while/for 递归 while true { … }
任意内存访问 读写任意位置的数据 数组、指针
1
2
3
4
5
6
7
8
9
10
┌─────────────────────────────────────────────────────────────┐
│ 图灵完备的最小特征 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 分支 │ + │ 循环 │ + │ 内存 │ = 图灵完备 │
│ │ if/else │ │ while │ │ 读写 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

图灵完备 vs 非图灵完备

详细对比

特性 图灵完备 非图灵完备
计算能力 可计算任何可计算函数 只能计算特定类型问题
无限循环 ✅ 可能 ❌ 不可能
停机问题 ❌ 无法判定 ✅ 保证终止
安全性 需要额外控制 内置安全
用途 通用编程 配置、查询、模板

在 KRO 中的意义

为什么 KRO 选择 CEL(非图灵完备)?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────────────────┐
│ KRO 的设计考量 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 安全性 > 灵活性 │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 图灵完备 │ vs │ 非图灵完备 │ │
│ │ │ │ │ │
│ │ • 无限循环风险 │ │ • 保证终止 │ │
│ │ • 资源耗尽风险 │ │ • 性能可预测 │ │
│ │ • 难以审计 │ │ • 易于审计 │ │
│ │ │ │ │ │
│ │ ❌ 生产危险 │ │ ✅ 生产安全 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

实际影响

场景 图灵完备语言 CEL
表达式执行 可能永不结束 必然结束
资源消耗 不可预测 可预测
安全性 需要沙箱/超时 内置安全
审计 难以证明正确性 易于验证

CEL 的安全特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌─────────────────────────────────────────────────────────────┐
│ CEL (Common Expression Language) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 总是终止 不会有无限循环 │
│ ✅ 无副作用 不会修改外部状态 │
│ ✅ 类型检查 apply 时验证类型 │
│ ✅ 可证明性 可以证明定义的行为 │
│ │
│ ❌ 没有 while 循环 │
│ ❌ 没有递归 │
│ ❌ 没有文件 I/O │
│ ❌ 没有网络调用 │
│ │
└─────────────────────────────────────────────────────────────┘

对比

特性 通用脚本语言 CEL
图灵完备 ✅ 是 ❌ 否
无限循环风险 ✅ 存在 ❌ 不可能
副作用 ✅ 可能有 ❌ 无
类型安全 运行时检查 编译时检查
性能预测 不可预测 可预测

安全示例

1
2
3
4
5
6
7
8
9
# ✅ CEL - 安全
template:
replicas: "${schema.replicas + 1}" # 简单表达式,必然终止

# ❌ 如果用通用语言 - 危险
template:
replicas: |
while true: # 可能无限循环!
replicas += 1

特性对比总结

特性 传统 Controller KRO
Schema 定义 OpenAPI 冗长 Simple Schema 一行
异步状态 手写重试逻辑 自动等待
依赖顺序 手动声明 CEL 自动推断
条件资源 if/else 代码块 if 表达式
批量创建 for 循环代码 forEach
安全性 图灵完备,有风险 CEL 非图灵完备
类型检查 运行时 应用时

Quick Start

什么是 ResourceGraphDefinition (RGD)?

核心概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────────────────┐
│ RGD = 多资源组合的蓝图 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户只需要创建一个 API 实例 │
│ │ │
│ ▼ │
│ kro 自动创建并管理多个关联资源 │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Application API │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │Deployment│ │ Service │ │ Ingress │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

kro 在幕后做什么

步骤 说明
构建 DAG 将资源视为有向无环图,理解依赖关系
验证定义 检查资源定义是否正确
确定顺序 检测正确的部署顺序
创建 CRD 集群中创建新的 API
监听实例 配置自己监听和服务该 API实例

前置条件

条件 说明
kro 已安装并在 K8s 集群中运行
kubectl 已安装并配置连接到集群

创建 RGD

完整结构图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────────────────┐
│ ResourceGraphDefinition: my-application │
├─────────────────────────────────────────────────────────────┤
│ │
│ schema (API 表面) │
│ ├─ kind: Application │
│ ├─ spec: │
│ │ ├─ name: string │
│ │ ├─ image: string (default=nginx) │
│ │ ├─ replicas: integer (default=3) │
│ │ └─ ingress.enabled: boolean (default=false) │
│ └─ status: │
│ ├─ deploymentConditions │
│ └─ availableReplicas │
│ │
│ resources (底层资源) │
│ ├─ deployment → Deployment │
│ ├─ service → Service │
│ └─ ingress → Ingress (条件创建) │
│ │
└─────────────────────────────────────────────────────────────┘

Schema 解析

字段 类型 默认值 说明
name string 必填 应用名称
image string nginx 容器镜像
replicas integer 3 副本数
ingress.enabled boolean false 是否创建 Ingress

Status 输出

字段 来源 说明
deploymentConditions ${deployment.status.conditions} Deployment 状态
availableReplicas ${deployment.status.availableReplicas} 可用副本数

资源依赖关系

依赖链

resourcegraphdefinition.yaml

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
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: my-application
spec:
# kro uses this simple schema to create your CRD schema and apply it
# The schema defines what users can provide when they instantiate the RGD (create an instance).
schema:
apiVersion: v1alpha1
kind: Application
spec:
# Spec fields that users can provide.
name: string
image: string | default="nginx"
replicas: integer | default=3
ingress:
enabled: boolean | default=false
status:
# Fields the controller will inject into instances status.
deploymentConditions: ${deployment.status.conditions}
availableReplicas: ${deployment.status.availableReplicas}

# Define the resources this API will manage.
resources:
- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${schema.spec.name} # Use the name provided by user
spec:
replicas: ${schema.spec.replicas} # Use the replicas provided by user
selector:
matchLabels:
app: ${schema.spec.name}
template:
metadata:
labels:
app: ${schema.spec.name}
spec:
containers:
- name: ${schema.spec.name}
image: ${schema.spec.image} # Use the image provided by user
ports:
- containerPort: 80

- id: service
template:
apiVersion: v1
kind: Service
metadata:
name: ${schema.spec.name}-svc
spec:
selector: ${deployment.spec.selector.matchLabels} # Use the deployment selector
ports:
- protocol: TCP
port: 80
targetPort: 80

- id: ingress
includeWhen:
- ${schema.spec.ingress.enabled} # Only include if the user wants to create an Ingress
template:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${schema.spec.name}-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/healthcheck-path: /health
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=60
spec:
rules:
- http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: ${service.metadata.name} # Use the service name
port:
number: 80

部署流程

1
2
3
4
5
6
7
8
9
10
11
步骤 1: 创建 RGD 文件

# 保存为 resourcegraphdefinition.yaml

步骤 2: 应用 RGD

kubectl apply -f resourcegraphdefinition.yaml

步骤 3: 检查 RGD 状态

kubectl get rgd my-application -owide

输出解读

1
2
3
$ k get rgd my-application -owide
NAME APIVERSION KIND STATE READY TOPOLOGICALORDER AGE
my-application v1alpha1 Application Active True ["deployment","service","ingress"] 14s
字段 说明
STATE Active = 已就绪可用
READY True = 准备接受实例
TOPOLOGICALORDER 资源创建顺序
1
2
3
4
$ k get crd | grep kro
applications.kro.run 2026-04-28T12:58:19Z
graphrevisions.internal.kro.run 2026-04-28T12:24:15Z
resourcegraphdefinitions.kro.run 2026-04-28T12:24:15Z

SandBoxPool

1
2
3
$ k get rgd -A -owide
NAME APIVERSION KIND STATE READY TOPOLOGICALORDER AGE
sandbox-pool v1alpha1 SandboxPool Active True ["sandboxset","trafficpolicy"] 2d21h

创建应用实例

实例文件

1
2
3
4
5
6
7
8
9
10
apiVersion: kro.run/v1alpha1
kind: Application
metadata:
name: my-app-instance
spec:
name: my-app
replicas: 1
image: nginx # 使用默认值,可不写
ingress:
enabled: true # 启用 Ingress

应用实例

1
2
$ k apply -f instance.yaml
application.kro.run/my-app-instance created

检查实例状态

1
2
3
$ k get applications
NAME STATE READY AGE
my-app-instance ACTIVE True 76s

自动创建的资源

1
2
3
4
5
6
7
8
9
10
$ k get deployments,services,ingresses
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app 1/1 1 1 2m40s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 192.168.194.129 <none> 443/TCP 25d
service/my-app-svc ClusterIP 192.168.194.157 <none> 80/TCP 2m40s

NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/my-app-ingress <none> * 80 2m40s

创建结果

资源类型 名称 说明
Deployment my-app 1 个副本
Service my-app-svc ClusterIP, 80端口
Ingress my-app-ingress AWS ALB 类型

实验:kro 的自动调和

实验 1: 修改副本数

1
2
3
# 编辑 instance.yaml
spec:
replicas: 3 # 从 1 改为 3
1
2
3
4
5
6
$ k edit applications my-app-instance
application.kro.run/my-app-instance edited

$ k get deployment my-app
NAME READY UP-TO-DATE AVAILABLE AGE
my-app 3/3 3 3 6m37s

实验 2: 删除自动恢复

1
2
3
4
5
# 手动删除 Service
kubectl delete service my-app-svc

# 监控自动重建
kubectl get service my-app-svc -w

清理资源

1
2
3
4
5
6
$ kubectl delete application my-app-instance
application.kro.run "my-app-instance" deleted from default namespace

$ k get deployments,services,ingresses
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 192.168.194.129 <none> 443/TCP 25

清理链

1
2
3
4
5
6
7
8
9
10
11
删除 Application 实例


┌─────────────────────────────────────────────────────────────┐
│ kro 自动清理所有相关资源 │
│ │
│ • Ingress 被删除 │
│ • Service 被删除 │
│ • Deployment 被删除 │
│ │
└─────────────────────────────────────────────────────────────┘

完整流程总结

关键要点

概念 要点
RGD 定义多资源组合蓝图
Schema 用户可见的 API 接口
Resources 实际创建的 K8s 资源
CEL 表达式 连接 Schema 和 Resources
条件资源 includeWhen 控制是否创建
自动调和 kro 持续监控并恢复期望状态
一键清理 删除实例即清理所有关联资源