DEV Community

Cover image for KRO: A new generation tool to manage Kubernetes manifests and deployment

KRO: A new generation tool to manage Kubernetes manifests and deployment

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:

  1. Helm 3.x installed
  2. 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")'
  )
Enter fullscreen mode Exit fullscreen mode
helm install kro oci://ghcr.io/kro-run/kro/kro \
  --namespace kro \
  --create-namespace \
  --version=${KRO_VERSION}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
kubectl get crd

NAME                               CREATED AT
applications.kro.run               2025-05-22T07:23:13Z
resourcegraphdefinitions.kro.run   2025-05-22T07:10:25Z
Enter fullscreen mode Exit fullscreen mode

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}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Demonstration

1. Deploy Resource Graph Definition

In this complete Resource Graph Definition example, we defined three fields:

  1. An image field that defaults to using the image pj3677/color-app:latest.
  2. A string field named color with a default value of red.
  3. A string field named commonlabel with a default value of color-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
Enter fullscreen mode Exit fullscreen mode

Let's deploy this Resource Graph Definition to our Kubernetes cluster.

kubectl apply -f resource-definition.yaml

resourcegraphdefinition.kro.run/my-color-application created
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Deploy color-lightgreen.yaml instance.

kubectl apply -f color-lightgreen.yaml

application.kro.run/color-lightgreen created
Enter fullscreen mode Exit fullscreen mode

color-skyblue.yaml

apiVersion: kro.run/v1alpha1
kind: Application
metadata:
  name: color-skyblue
spec:
  name: color-skyblue-app
  color: "skyblue"
  commonlabel: "skyblue-application"
Enter fullscreen mode Exit fullscreen mode

Deploy color-skyblue instance.

kubectl apply -f color-skyblue.yaml

application.kro.run/color-skyblue created
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Visit color-lightgreen via http://localhost:3000

Image description

  • Check the color-skyblue Instance
kubectl port-forward service/color-skyblue-app-service 3000:3000
Enter fullscreen mode Exit fullscreen mode

Visit color-skyblue via http://localhost:3000

Image description

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}
Enter fullscreen mode Exit fullscreen mode

Our application will generate the specified background color through this environment variable.

Cleanup

  • Remove color-skyblue instance:
kubectl delete -f color-skyblue.yaml
Enter fullscreen mode Exit fullscreen mode
  • Remove color-lightgreen instance:
kubectl delete -f color-lightgreen.yaml
Enter fullscreen mode Exit fullscreen mode
  • Remove Resource Graph Definition:
kubectl delete -f resource-definition.yaml
Enter fullscreen mode Exit fullscreen mode
  • Uninstall KRO:
helm delete kro -n kro
Enter fullscreen mode Exit fullscreen mode

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)