Skip to content

Commit b489b51

Browse files
authored
chore: Add K8s examples to doc (#874)
* chore: docusaurus/theme-mermaid to package.json * chore: fix update-doc-examples.sh Implement a process to add Kubernetes examples to update-doc-examples.sh * chore: update doc of kubernetes examples update script to update Kubernetes examples using update-doc-examle.sh * docs: backport kubernetes examples to v0.7.0 docs backport some documents about k8s examples to v0.7.0
1 parent 0caa9b2 commit b489b51

File tree

5 files changed

+548
-2
lines changed

5 files changed

+548
-2
lines changed

scripts/update-doc-examples.sh

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,34 @@ update_azure_example_docs() {
6666
echo "TODO: implement azure examples"
6767
}
6868
update_kubernetes_example_docs() {
69-
echo "TODO: implement kubernetes examples"
69+
# Create the Kubernetes examples directory if it doesn't exist
70+
mkdir -p website/docs/examples/kubernetes
71+
# Initialize position counter
72+
position=705
73+
# Find all rgd.yaml files in examples/gcp directory and its subdirectories
74+
find examples/kubernetes -name "*rgd.yaml" | while read -r yaml_file; do
75+
# Extract the directory name as the example name
76+
example_path=$(dirname "$yaml_file")
77+
dir_name=$(basename $example_path)
78+
readme_file=$example_path/README.md
79+
out_file="website/docs/examples/kubernetes/${dir_name}.md"
80+
81+
# Convert directory name to title case (e.g., k8s-cluster -> K8s Cluster)
82+
# title=$(echo "$dir_name" | sed -E 's/-/ /g' | awk '{for(i=1;i<=NF;i++)sub(/./,toupper(substr($i,1,1)),$i)}1')
83+
84+
# copy all images
85+
cp $example_path/*.png website/docs/examples/kubernetes/ 2>/dev/null
86+
# Generate the markdown content
87+
create_example "$out_file" "$position" "$readme_file" "$yaml_file"
88+
89+
# Increment position for next file
90+
((position+=1))
91+
92+
echo "Generated documentation for ${dir_name} at ${out_file}"
93+
done
7094
}
7195

7296
update_gcp_example_docs
7397
update_aws_example_docs
7498
update_azure_example_docs
75-
update_kubernetes_example_docs
99+
update_kubernetes_example_docs
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
sidebar_position: 708
3+
---
4+
5+
6+
7+
<details>
8+
<summary>ResourceGraphDefinition</summary>
9+
```yaml title="rgd.yaml"
10+
apiVersion: kro.run/v1alpha1
11+
kind: ResourceGraphDefinition
12+
metadata:
13+
name: job-deployment.kro.run
14+
spec:
15+
schema:
16+
apiVersion: v1alpha1
17+
kind: JobDeployment
18+
spec:
19+
replicas: integer | default=1
20+
delayInSeconds: integer | default=30
21+
resources:
22+
- id: job
23+
readyWhen:
24+
- ${job.status.completionTime != null}
25+
template:
26+
apiVersion: batch/v1
27+
kind: Job
28+
metadata:
29+
name: ${schema.metadata.name}-job
30+
spec:
31+
# NOTE: will not work if we delete the job after it finishes. It will try to recreate the job.
32+
#ttlSecondsAfterFinished: 30
33+
template:
34+
spec:
35+
restartPolicy: Never
36+
containers:
37+
- name: sleeper
38+
image: busybox
39+
command: ["sleep", "${string(schema.spec.delayInSeconds)}"]
40+
resources:
41+
limits:
42+
cpu: "1"
43+
- id: deployment
44+
template:
45+
apiVersion: apps/v1
46+
kind: Deployment
47+
metadata:
48+
name: ${schema.metadata.name}
49+
spec:
50+
replicas: ${schema.spec.replicas}
51+
selector:
52+
matchLabels:
53+
app: ${schema.metadata.name}
54+
template:
55+
metadata:
56+
labels:
57+
app: ${schema.metadata.name}
58+
spec:
59+
containers:
60+
- name: web
61+
image: nginx
62+
ports:
63+
- containerPort: 80
64+
```
65+
</details>
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
---
2+
sidebar_position: 707
3+
---
4+
5+
# SaaS Multi-Tenant example
6+
7+
This example demonstrates how to create a multi-tenant SaaS application using Kro ResourceGraphDefinitions. It creates isolated tenant environments with dedicated applications, following a hierarchical structure of ResourceGraphDefinitions.
8+
9+
## Overview
10+
11+
This example creates a multi-tenant architecture with:
12+
13+
1. **TenantEnvironment**: Creates isolated namespaces with resource quotas and NetworkPolicy
14+
2. **TenantApplication**: Deploys applications within tenant environments
15+
3. **Tenant**: Orchestrates tenant environments and applications together
16+
17+
The example uses a hierarchical approach where each ResourceGraphDefinition builds upon standard Kubernetes resources.
18+
19+
## Architecture
20+
21+
```mermaid
22+
graph TB
23+
subgraph "Kubernetes Cluster"
24+
subgraph "tenant-a namespace"
25+
TA_D[Deployment]
26+
TA_S[Service]
27+
TA_RQ[ResourceQuota]
28+
TA_NP[NetworkPolicy]
29+
TA_NS[Namespace]
30+
end
31+
32+
subgraph "tenant-b namespace"
33+
TB_D[Deployment]
34+
TB_S[Service]
35+
TB_RQ[ResourceQuota]
36+
TB_NP[NetworkPolicy]
37+
TB_NS[Namespace]
38+
end
39+
40+
subgraph "Kro ResourceGraphDefinitions"
41+
RGD1[TenantEnvironment RGD]
42+
RGD2[TenantApplication RGD]
43+
RGD3[Tenant RGD]
44+
end
45+
end
46+
RGD1 --> TA_NS
47+
RGD1 --> TB_NS
48+
RGD1 --> TA_RQ
49+
RGD1 --> TB_RQ
50+
RGD1 --> TA_NP
51+
RGD1 --> TB_NP
52+
53+
RGD2 --> TA_D
54+
RGD2 --> TA_S
55+
RGD2 --> TB_D
56+
RGD2 --> TB_S
57+
RGD3 --> RGD1
58+
RGD3 --> RGD2
59+
60+
style RGD1 fill:#e1f5fe
61+
style RGD2 fill:#f3e5f5
62+
style RGD3 fill:#e8f5e8
63+
```
64+
65+
## Getting Started
66+
67+
Apply the ResourceGraphDefinitions and instance in the following order:
68+
69+
### Create ResourceGraphDefinition
70+
71+
Apply the tenant environment RGD:
72+
73+
```bash
74+
kubectl apply -f tenant-environment-rgd.yaml
75+
```
76+
77+
Apply the tenant application RGD:
78+
79+
```bash
80+
kubectl apply -f tenant-application-rgd.yaml
81+
```
82+
83+
Apply the main tenant RGD:
84+
85+
```bash
86+
kubectl apply -f tenant-rgd.yaml
87+
```
88+
89+
Check all RGDs are in Active state:
90+
91+
```bash
92+
kubectl get rgd
93+
```
94+
95+
Expected result:
96+
97+
```bash
98+
NAME APIVERSION KIND STATE AGE
99+
tenantenvironment.kro.run v1alpha1 TenantEnvironment Active 2m
100+
tenantapplication.kro.run v1alpha1 TenantApplication Active 1m
101+
tenant.kro.run v1alpha1 Tenant Active 30s
102+
```
103+
104+
### Create Tenant Instance
105+
106+
Apply the tenant instance:
107+
108+
```bash
109+
kubectl apply -f tenant-instance.yaml
110+
```
111+
112+
Check tenant instance status:
113+
114+
```bash
115+
kubectl get tenant
116+
```
117+
118+
Expected result:
119+
120+
```bash
121+
NAME STATE SYNCED AGE
122+
tenant001 ACTIVE True 5m
123+
```
124+
125+
## Clean Up
126+
127+
Remove resources in reverse order:
128+
129+
Remove Tenant Instance:
130+
131+
```bash
132+
kubectl delete -f tenant-instance-tmpl.yaml
133+
```
134+
135+
Remove ResourceGraphDefinitions:
136+
137+
```bash
138+
kubectl delete -f tenant-rgd.yaml
139+
kubectl delete -f tenant-application-rgd.yaml
140+
kubectl delete -f tenant-environment-rgd.yaml
141+
```
142+
143+
<details>
144+
<summary>ResourceGraphDefinition</summary>
145+
```yaml title="rgd.yaml"
146+
apiVersion: kro.run/v1alpha1
147+
kind: ResourceGraphDefinition
148+
metadata:
149+
name: tenantenvironment.kro.run
150+
spec:
151+
schema:
152+
apiVersion: v1alpha1
153+
kind: TenantEnvironment
154+
spec:
155+
tenantId: string
156+
resources:
157+
- id: tenantNamespace
158+
template:
159+
apiVersion: v1
160+
kind: Namespace
161+
metadata:
162+
name: ${schema.spec.tenantId}
163+
labels:
164+
name: ${schema.spec.tenantId}
165+
- id: tenantQuota
166+
template:
167+
apiVersion: v1
168+
kind: ResourceQuota
169+
metadata:
170+
name: ${schema.spec.tenantId}-quota
171+
namespace: ${schema.spec.tenantId}
172+
labels:
173+
saas/tenant-id: ${schema.spec.tenantId}
174+
spec:
175+
hard:
176+
requests.cpu: "1"
177+
requests.memory: "1Gi"
178+
limits.cpu: "2"
179+
limits.memory: "2Gi"
180+
- id: tenantNetworkpolicy
181+
template:
182+
apiVersion: networking.k8s.io/v1
183+
kind: NetworkPolicy
184+
metadata:
185+
name: ${schema.spec.tenantId}-isolation
186+
namespace: ${schema.spec.tenantId}
187+
labels:
188+
saas/tenant-id: ${schema.spec.tenantId}
189+
spec:
190+
podSelector:
191+
matchLabels:
192+
ingress:
193+
- from:
194+
- podSelector: {}
195+
```
196+
</details>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
sidebar_position: 708
3+
---
4+
5+
6+
7+
<details>
8+
<summary>ResourceGraphDefinition</summary>
9+
```yaml title="rgd.yaml"
10+
apiVersion: kro.run/v1alpha1
11+
kind: ResourceGraphDefinition
12+
metadata:
13+
name: job-deployment.kro.run
14+
spec:
15+
schema:
16+
apiVersion: v1alpha1
17+
kind: JobDeployment
18+
spec:
19+
replicas: integer | default=1
20+
delayInSeconds: integer | default=30
21+
resources:
22+
- id: job
23+
readyWhen:
24+
- ${job.status.completionTime != null}
25+
template:
26+
apiVersion: batch/v1
27+
kind: Job
28+
metadata:
29+
name: ${schema.metadata.name}-job
30+
spec:
31+
# NOTE: will not work if we delete the job after it finishes. It will try to recreate the job.
32+
#ttlSecondsAfterFinished: 30
33+
template:
34+
spec:
35+
restartPolicy: Never
36+
containers:
37+
- name: sleeper
38+
image: busybox
39+
command: ["sleep", "${string(schema.spec.delayInSeconds)}"]
40+
resources:
41+
limits:
42+
cpu: "1"
43+
- id: deployment
44+
template:
45+
apiVersion: apps/v1
46+
kind: Deployment
47+
metadata:
48+
name: ${schema.metadata.name}
49+
spec:
50+
replicas: ${schema.spec.replicas}
51+
selector:
52+
matchLabels:
53+
app: ${schema.metadata.name}
54+
template:
55+
metadata:
56+
labels:
57+
app: ${schema.metadata.name}
58+
spec:
59+
containers:
60+
- name: web
61+
image: nginx
62+
ports:
63+
- containerPort: 80
64+
```
65+
</details>

0 commit comments

Comments
 (0)