Skip to main content
Version: main

Graph Inference

kro automatically infers dependencies from CEL expressions. You don't specify the order - you describe relationships, and kro figures out the rest.

How It Works

When you reference one resource from another using a CEL expression, you create a dependency:

resources:
- id: configmap
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_URL: ${schema.spec.dbUrl}

- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
spec:
containers:
- env:
- name: DATABASE_URL
value: ${configmap.data.DATABASE_URL}

The expression ${configmap.data.DATABASE_URL} creates a dependency: deployment depends on configmap. kro will create the configmap first, wait for the expression to be resolvable, then create the deployment.

Dependency Graph (DAG)

kro builds a Directed Acyclic Graph (DAG) where:

  • Nodes are resources
  • Edges are dependencies (created by CEL references)
  • Directed means dependencies have direction (A depends on B)
  • Acyclic means no circular dependencies

Common Patterns

Dependency graphs follow common patterns that you'll encounter in most RGDs. Understanding these patterns helps you design effective resource relationships. Real-world RGDs often combine multiple patterns - a complex application might have parallel branches that converge into a diamond, followed by a linear chain.

In a linear chain, each resource depends on the previous one. This pattern is common when you have a sequence of resources where each step requires data from the previous step - like a ConfigMap that feeds into a Deployment, which then informs a Service.

configmap ──▶ deployment ──▶ service
resources:
- id: configmap
template:
apiVersion: v1
kind: ConfigMap
data:
key: ${schema.spec.value}

- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- envFrom:
- configMapRef:
name: ${configmap.metadata.name}

- id: service
template:
apiVersion: v1
kind: Service
spec:
selector: ${deployment.spec.selector.matchLabels}

The deployment references ${configmap.metadata.name}, creating a dependency. The service references ${deployment.spec.selector.matchLabels}, adding another link. kro creates them in sequence: configmap first, then deployment, then service.

Combining Patterns

Real-world RGDs typically combine multiple patterns. A complex application might have parallel branches (independent microservices), a diamond (services converging into a gateway), and linear chains (each service with its own config → deployment → service sequence). kro handles any valid DAG structure - these patterns are just common building blocks.

Topological Order

kro computes a topological order - the sequence resources can be processed such that all dependencies are satisfied.

Creation: Resources created in topological order Deletion: Resources deleted in reverse order

View the computed order:

kubectl get rgd my-app -o jsonpath='{.status.topologicalOrder}'

Example output:

status:
topologicalOrder:
- configmap
- deployment
- service

Circular Dependencies

Circular dependencies are not allowed and will cause validation to fail:

# ✗ This will fail
resources:
- id: serviceA
template:
spec:
targetPort: ${serviceB.spec.port} # A → B

- id: serviceB
template:
spec:
targetPort: ${serviceA.spec.port} # B → A (circular!)

Fix: Break the cycle by using schema.spec instead:

resources:
- id: serviceA
template:
spec:
targetPort: ${schema.spec.portA} # Use schema

- id: serviceB
template:
spec:
targetPort: ${serviceA.spec.port} # This is fine

What Happens at Runtime

When kro reconciles an instance:

  1. Evaluate static expressions - Expressions referencing only schema.spec are evaluated once
  2. Process in topological order - For each resource:
    • Wait for all dependency expressions to be resolvable
    • Create or update the resource
    • Move to next resource in order
  3. Delete in reverse order - During deletion, process resources backwards

kro waits for CEL expressions to be resolvable before proceeding. This means the referenced resource exists and has the field being accessed.

Next Steps

Brought to you with ♥ by SIG Cloud Provider