https://github.com/kro-run/kro
export KRO_VERSION=$(curl -sL \
https://api.github.com/repos/kro-run/kro/releases/latest | \
jq -r '.tag_name | ltrimstr("v")'
)
echo "KRO_VERSION: $KRO_VERSION"
helm install kro oci://ghcr.io/kro-run/kro/kro \
--namespace kro \
--create-namespace \
--version=${KRO_VERSION}
helm -n kro list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
kro kro 1 2025-05-11 18:06:30.464559329 +0000 UTC deployed kro-0.2.3 0.2.3
kubectl get pods -n kro
NAME READY STATUS RESTARTS AGE
kro-86d5b5b5bd-jlqfr 1/1 Running 0 54s
# vim RGD.yaml
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: pingpongapp
spec:
schema:
apiVersion: v1alpha1
kind: PingPongApp
spec:
namespace: string | default="app"
replicas: integer | default=1
image: string | required=true
tag: string | default="latest"
port: integer | default=8080
host: string | default="cka.local"
resources:
- id: ns
template:
apiVersion: v1
kind: Namespace
metadata:
name: ${schema.spec.namespace}
- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ${schema.spec.namespace}
name: ${schema.metadata.name}
spec:
replicas: ${schema.spec.replicas}
selector:
matchLabels:
app: ${schema.metadata.name}
template:
metadata:
labels:
app: ${schema.metadata.name}
spec:
containers:
- name: ${schema.metadata.name}
image: ${schema.spec.image}:${schema.spec.tag}
- id: service
template:
apiVersion: v1
kind: Service
metadata:
namespace: ${schema.spec.namespace}
name: ${schema.metadata.name}
spec:
selector:
app: ${schema.metadata.name}
ports:
- port: ${schema.spec.port}
targetPort: ${schema.spec.port}
- id: ingress
template:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: ${schema.spec.namespace}
name: ${schema.metadata.name}-ingress
spec:
rules:
- host: ${schema.spec.host}
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: ${schema.metadata.name}
port:
number: ${schema.spec.port}
k apply -f RGD.yaml
k get crd pingpongapps.kro.run
NAME CREATED AT
pingpongapps.kro.run 2025-05-20T17:17:32Z
# vim resouses.yaml
apiVersion: kro.run/v1alpha1
kind: PingPongApp
metadata:
name: app-prod
spec:
namespace: app
replicas: 2
image: viktoruj/ping_pong
tag: latest
port: 8080
host: cka.local
k apply -f resouses.yaml
k get all -n app
k get po,deployment,svc,ing -n app
NAME READY STATUS RESTARTS AGE
pod/app-prod-7b7749b69b-65xgv 1/1 Running 0 55s
pod/app-prod-7b7749b69b-tgrwb 1/1 Running 0 55s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/app-prod 2/2 2 2 55s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/app-prod ClusterIP 10.99.202.9 <none> 8080/TCP 52s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/app-prod-ingress <none> cka.local 80 49s
# curl cka.local:30102
Server Name: ping_pong_server
URL: http://cka.local:30102/
Client IP: 10.0.221.132
Method: GET
Protocol: HTTP/1.1
responseDelay: 0
maxResponseWorker: 65535
ResponseWorker: 1
additionalResponseSize: 0 Kb
---------------
Headers:
X-Request-Id: abd0c90a66faccc7f4367d7880af23f3
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Scheme: http
User-Agent: curl/7.81.0
X-Real-Ip: 10.10.2.73
X-Forwarded-For: 10.10.2.73
X-Forwarded-Host: cka.local:30102
X-Forwarded-Scheme: http
Accept: */*
---------------
Headers size :
X-Real-Ip: 10 byte
X-Forwarded-For: 10 byte
X-Forwarded-Host: 15 byte
X-Forwarded-Scheme: 4 byte
Accept: 3 byte
X-Request-Id: 32 byte
X-Forwarded-Port: 2 byte
X-Forwarded-Proto: 4 byte
X-Scheme: 4 byte
User-Agent: 11 byte
---------------
total size of headers: 95 byte
---------------
total request size : 113 byte
# k edit pingpongapps.kro.run app-prod
........
spec:
host: cka.local
image: viktoruj/ping_pong
namespace: app
port: 8080
replicas: 3 # update it
tag: latest
........
# k get pods -n app
NAME READY STATUS RESTARTS AGE
app-prod-7b7749b69b-26wrg 1/1 Running 0 6s
app-prod-7b7749b69b-dqsvq 1/1 Running 0 5m
app-prod-7b7749b69b-ljbrc 1/1 Running 0 5m
k delete pingpongapps.kro.run app-prod
# k get ns app
Error from server (NotFound): namespaces "app" not found