About KRO
KRO (Kube Resource Orchestrator) is an open-source, Kubernetes-native project that allows you to define custom Kubernetes APIs using simple and straightforward configuration.
KRO is currently governed by a small group of maintainers - from Google, Amazon, and Microsoft - who are responsible for the overall direction and management of the project, as well as for the technical decisions that affect the project.
Overview
When you mention manifest and deployment management tools on Kubernetes, the first things that come to mind are Helm or Kustomization. Later, there was even a project in CNCF called Crossplane that allows you to implement IaC through YAML files, making it very convenient for you to deploy infrastructure on Cloud Service Providers.
KRO proposed a brand new approach, allowing you to manage manifests and deployments on Kubernetes through very intuitive YAML file writing, and also enabling infrastructure deployment like Crossplane.
Since KRO is still in a very early stage, some features are not yet complete. This article will use a very simple example to introduce how KRO performs manifest and deployment management.
Installation
1. Installing KRO
Before you begin, ensure you have the following:
- Helm 3.x installed
- kubectl installed and configured to interact with your Kubernetes cluster
export KRO_VERSION=$(curl -sL \
https://api.github.com/repos/kro-run/kro/releases/latest | \
jq -r '.tag_name | ltrimstr("v")'
)
helm install kro oci://ghcr.io/kro-run/kro/kro \
--namespace kro \
--create-namespace \
--version=${KRO_VERSION}
2. Check KRO Readiness
kubectl get all -n kro
NAME READY STATUS RESTARTS AGE
pod/kro-69b4b67b67-xhvht 1/1 Running 0 1d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kro 1/1 1 1 1d
NAME DESIRED CURRENT READY AGE
replicaset.apps/kro-69b4b67b67 1 1 1 1d
kubectl get crd
NAME CREATED AT
applications.kro.run 2025-05-22T07:23:13Z
resourcegraphdefinitions.kro.run 2025-05-22T07:10:25Z
Resource Graph Definitions
Resource Graph Definitions are a very important concept in KRO. You can think of Resource Graph Definitions as a blueprint drawn by an architect for a house in real life, which specifies the specifications for each part. Anyone who gets this blueprint can build an identical house. In some flexible areas, you can even make small modifications, such as the paint color or the style of the pendant light.
Deep Dive Into Resource Graph Definitions
Let's explain with a simple Resource Graph Definition example. After KRO is installed, it will create two Custom Resource Definition (CRD) on your Kubernetes cluster: applications.kro.run
and resourcegraphdefinitions.kro.run
.
Lines 6 to 16: We will declare a scheme that includes some fields that can be adjusted by the user, just like the paint color or the style of the pendant light mentioned in the previous section. You can assign a default value to these fields or specify their type, such as string or integer.
Lines 17 to 44: A common Kubernetes deployment is declared here. Some field values within it will reference the values defined in the schema. Referencing values is very simple; you just need to use the $ sign and {} brackets to specify the Key location of the field inside.
This completes a simple Resource Graph Definition. In the next section, we will gradually explain how to construct the application we want on Kubernetes using this Resource Graph Definition.
rgd.yaml
1 apiVersion: kro.run/v1alpha1
2 kind: ResourceGraphDefinition
3 metadata:
4 name: my-color-application
5 spec:
6 schema:
7 apiVersion: v1alpha1
8 kind: Application
9 spec:
10 name: string
11 image: string | default="pj3677/color-app:latest"
12 color: string | default="red"
13 commonlabel: string | default="color-application"
14 status:
15 deploymentConditions: ${deployment.status.conditions}
16 availableReplicas: ${deployment.status.availableReplicas}
17 resources:
18 - id: deployment
19 template:
20 apiVersion: apps/v1
21 kind: Deployment
22 metadata:
23 name: ${schema.spec.name}
24 labels:
25 purpose: ${schema.spec.commonlabel}
26 spec:
27 replicas: 2
28 selector:
29 matchLabels:
30 app: ${schema.spec.name}
31 template:
32 metadata:
33 labels:
34 app: ${schema.spec.name}
35 purpose: ${schema.spec.commonlabel}
36 spec:
37 containers:
38 - name: ${schema.spec.name}
39 image: ${schema.spec.image}
40 ports:
41 - containerPort: 3000
42 env:
43 - name: BG_COLOR
44 value: ${schema.spec.color}
Deploy Applications with Instances
An instance represents your deployed application. When you create an instance, you're telling KRO controller "I want to create this set of resources running in my Kubernetes cluster via the Resource Graph Definition".
Below is an example of an Instance. From this example, we can see there is a field called color and specified to lightgreen
.
When instance.yaml
is deployed to Kubernetes, the KRO controller will receive the request and refer to the Resource Graph Definition specified in instance.yaml to generate the corresponding set of resources, which is the Application we want to construct.
instance.yaml
apiVersion: kro.run/v1alpha1
kind: Application
metadata:
name: color-lightgreen
spec:
name: color-lightgreen-app
color: "lightgreen"
Demonstration
1. Deploy Resource Graph Definition
In this complete Resource Graph Definition example, we defined three fields:
- An
image
field that defaults to using the imagepj3677/color-app:latest
. - A string field named
color
with a default value ofred
. - A string field named
commonlabel
with a default value ofcolor-application
.
This Resource Graph Definition includes both Kubernetes Deployment
and Service
resources. Some fields within it will reference the values defined in the schema
.
resource-definition.yaml
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: my-color-application
spec:
schema:
apiVersion: v1alpha1
kind: Application
spec:
name: string
image: string | default="pj3677/color-app:latest"
color: string | default="red"
commonlabel: string | default="color-application"
status:
deploymentConditions: ${deployment.status.conditions}
availableReplicas: ${deployment.status.availableReplicas}
resources:
- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${schema.spec.name}
labels:
purpose: ${schema.spec.commonlabel}
spec:
replicas: 2
selector:
matchLabels:
app: ${schema.spec.name}
template:
metadata:
labels:
app: ${schema.spec.name}
purpose: ${schema.spec.commonlabel}
spec:
containers:
- name: ${schema.spec.name}
image: ${schema.spec.image}
ports:
- containerPort: 3000
env:
- name: BG_COLOR
value: ${schema.spec.color}
- id: service
template:
apiVersion: v1
kind: Service
metadata:
name: ${schema.spec.name}-service
labels:
purpose: ${schema.spec.commonlabel}
spec:
selector: ${deployment.spec.selector.matchLabels}
ports:
- protocol: TCP
port: 3000
targetPort: 3000
Let's deploy this Resource Graph Definition to our Kubernetes cluster.
kubectl apply -f resource-definition.yaml
resourcegraphdefinition.kro.run/my-color-application created
Check the Resource Graph Definition readiness.
kubectl get resourcegraphdefinition.kro.run -o wide
NAME APIVERSION KIND STATE TOPOLOGICALORDER AGE
my-color-application v1alpha1 Application Active ["deployment","service"] 59s
You can see our my-color-application
Resource Graph Definition has been deployed to Kubernetes cluster and it contains two Kubernetes resources deployment
and service
.
2. Deploy Instances
Next, we constructed two Instances. The purpose is to generate two different Applications using the same Resource Graph Definition.
color-lightgreen.yaml
apiVersion: kro.run/v1alpha1
kind: Application
metadata:
name: color-lightgreen
spec:
name: color-lightgreen-app
color: "lightgreen"
commonlabel: "lightgreen-application"
Deploy color-lightgreen.yaml
instance.
kubectl apply -f color-lightgreen.yaml
application.kro.run/color-lightgreen created
color-skyblue.yaml
apiVersion: kro.run/v1alpha1
kind: Application
metadata:
name: color-skyblue
spec:
name: color-skyblue-app
color: "skyblue"
commonlabel: "skyblue-application"
Deploy color-skyblue
instance.
kubectl apply -f color-skyblue.yaml
application.kro.run/color-skyblue created
3. Check Application Readiness
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/color-lightgreen-app-6f58f87b75-7l5p9 1/1 Running 0 4m
pod/color-lightgreen-app-6f58f87b75-v62mf 1/1 Running 0 4m
pod/color-skyblue-app-5fdcd5fbbc-gwpw7 1/1 Running 0 10s
pod/color-skyblue-app-5fdcd5fbbc-psv2m 1/1 Running 0 10s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/color-lightgreen-app-service ClusterIP 10.96.181.168 <none> 3000/TCP 3m32s
service/color-skyblue-app-service ClusterIP 10.96.236.33 <none> 3000/TCP 1s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5m2s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/color-lightgreen-app 2/2 2 2 4m
deployment.apps/color-skyblue-app 2/2 2 2 11s
NAME DESIRED CURRENT READY AGE
replicaset.apps/color-lightgreen-app-6f58f87b75 2 2 2 4m
replicaset.apps/color-skyblue-app-5fdcd5fbbc 2 2 2 10s
Let's use kubectl port-forward
to check the application's behavior as we expected.
- Check the
color-lightgreen
Instance
kubectl port-forward service/color-lightgreen-app-service 3000:3000
Visit color-lightgreen
via http://localhost:3000
- Check the
color-skyblue
Instance
kubectl port-forward service/color-skyblue-app-service 3000:3000
Visit color-skyblue
via http://localhost:3000
Perfect the result as we expected. The two applications have different background colors: lightgreen
and skyblue
.
- Behavior Analyze
The reason for having different background colors is because we provided different parameters in the two instances: color: "lightgreen"
and color: "skyblue"
.
And this parameter will be passed into this snippet within the Kubernetes Deployment
defined in the Resource Graph Definition.
env:
- name: BG_COLOR
value: ${schema.spec.color}
Our application will generate the specified background color through this environment variable.
Cleanup
- Remove color-skyblue instance:
kubectl delete -f color-skyblue.yaml
- Remove color-lightgreen instance:
kubectl delete -f color-lightgreen.yaml
- Remove Resource Graph Definition:
kubectl delete -f resource-definition.yaml
- Uninstall KRO:
helm delete kro -n kro
Conclusion
KRO provides an easier way to write and manage Kubernetes manifests and deployments compared to Helm or Kustomization. It also enables the currently popular Infrastructure as Code architectural design.
This means that by learning just one tool, you can accomplish both Kubernetes deployment management and Infrastructure as Code.
It must be noted that KRO is currently in the Alpha stage and is not yet suitable for your production environment. You can continue to follow this project, and when it matures, it may be able to replace your current complex toolchain.
Top comments (0)