Simple Schema
kro follows a different approach for defining your API schema and shapes. It uses a human-friendly and readable syntax that is OpenAPI specification compatible. Here's an example:
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: web-application
spec:
schema:
apiVersion: v1alpha1
kind: WebApplication
spec:
# Basic types
name: string | required=true immutable=true description="My Name"
replicas: integer | default=1 minimum=1 maximum=100
image: string | required=true
# Unstructured objects
values: object | required=true
# Structured type
ingress:
enabled: boolean | default=false
host: string | default="example.com"
path: string | default="/"
# Array type
ports: "[]integer"
# Map type
env: "map[string]myType"
# Custom Types
types:
myType:
value1: string | required=true
value2: integer | default=42
status:
# Status fields with auto-inferred types
availableReplicas: ${deployment.status.availableReplicas}
serviceEndpoint: ${service.status.loadBalancer.ingress[0].hostname}Type Definitions
Basic Types
kro supports these foundational types:
string: Text valuesinteger: Whole numbersboolean: True/False valuesfloat: Decimal numbers
For example:
name: string
age: integer
enabled: boolean
price: floatStructure Types
You can create complex objects by nesting fields. Each field can use any type, including other structures:
# Simple structure
address:
street: string
city: string
zipcode: string
# Nested structures
user:
name: string
address: # Nested object
street: string
city: string
contacts: "[]string"# Array of stringsUnstructured Objects
Unstructured objects are declared using object as a type.
This disables the field-validation normally offered by kro, and forwards the values to your RGD as-is. This is generally discouraged and should therefore be used with caution. In most cases, using a structured object is a better approach.
kind: ResourceGraphDefintion
metadata: {}
spec:
schema:
spec:
additionalHelmChartValues: objectThis allows you to pass data to your CRDs directly in cases where the schema is not known in advance. This type supports any valid object, and can mix and match different primitives as well as structured types.
apiVersion: kro.run/v1alpha1
kind: CRDWithUnstructuredObjects
metadata:
name: test-instance
spec:
additionalHelmChartValues:
boolean-value: true
numeric-value: 42
structural-type:
with-additional:
nested: fields
string-value: my-string
mapping-value:
- item1
- item2
- item3
Array Types
Arrays are denoted using [] syntax:
- Basic arrays:
[]string,[]integer,[]boolean
Examples:
tags: []string
ports: []integerMap Types
Maps are key-value pairs denoted as map[keyType]valueType:
map[string]string: String to string mappingmap[string]integer: String to integer mapping
Examples:
labels: "map[string]string"
metrics: "map[string]float"Nested Arrays and Maps
Arrays and maps can be nested to create more complex data structures:
| Pattern | Description | Example |
|---|---|---|
[][]Type | Array of arrays | matrix: "[][]integer" |
map[string][]Type | Map of arrays | tags: "map[string][]string" |
[]map[string]Type | Array of maps | configs: "[]map[string]string" |
Custom Types
Custom types are specified in the separate types section.
They provide a map of names to type specifications that follow the simple schema.
Example:
schema:
types:
Person:
name: string
age: integer
spec:
people: '[]Person | required=true'Recursive Type References
Custom types can reference other custom types. kro automatically resolves dependencies using topological sorting:
schema:
types:
Address:
street: string
city: string
Company:
name: string
headquarters: Address
Employee:
name: string
company: Company
spec:
ceo: Employeekro processes types in dependency order (Address → Company → Employee) and expands them inline in the generated CRD.
Cyclic Dependency Detection
kro detects and rejects cyclic dependencies between custom types:
# This will fail validation
schema:
types:
Person:
name: string
employer: Company
Company:
name: string
employees: "[]Person"# Creates cycle: Person → Company → PersonTo resolve cycles, restructure types to break the circular reference or use inline object definitions.