Skip to main content
Version: 0.7.1

SaaS Multi-Tenant

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.

Overview

This example creates a multi-tenant architecture with:

  1. TenantEnvironment: Creates isolated namespaces with resource quotas and NetworkPolicy
  2. TenantApplication: Deploys applications within tenant environments
  3. Tenant: Orchestrates tenant environments and applications together

The example uses a hierarchical approach where each ResourceGraphDefinition builds upon standard Kubernetes resources.

Architecture

Getting Started

Apply the ResourceGraphDefinitions and instance in the following order:

Create ResourceGraphDefinition

Apply the tenant environment RGD:

kubectl apply -f tenant-environment-rgd.yaml

Apply the tenant application RGD:

kubectl apply -f tenant-application-rgd.yaml

Apply the main tenant RGD:

kubectl apply -f tenant-rgd.yaml

Check all RGDs are in Active state:

kubectl get rgd

Expected result:

NAME                               APIVERSION   KIND              STATE    AGE
tenantenvironment.kro.run v1alpha1 TenantEnvironment Active 2m
tenantapplication.kro.run v1alpha1 TenantApplication Active 1m
tenant.kro.run v1alpha1 Tenant Active 30s

Create Tenant Instance

Apply the tenant instance:

kubectl apply -f tenant-instance.yaml

Check tenant instance status:

kubectl get tenant

Expected result:

NAME          STATE    SYNCED   AGE
tenant001 ACTIVE True 5m

Clean Up

Remove resources in reverse order:

Remove Tenant Instance:

kubectl delete -f tenant-instance-tmpl.yaml

Remove ResourceGraphDefinitions:

kubectl delete -f tenant-rgd.yaml
kubectl delete -f tenant-application-rgd.yaml
kubectl delete -f tenant-environment-rgd.yaml
ResourceGraphDefinition
rgd.yaml
apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
name: tenantenvironment.kro.run
spec:
schema:
  apiVersion: v1alpha1
  kind: TenantEnvironment
  spec:
    tenantId: string
resources:
- id: tenantNamespace
  template:
    apiVersion: v1
    kind: Namespace
    metadata:
      name: ${schema.spec.tenantId}
      labels:
        name: ${schema.spec.tenantId}
- id: tenantQuota
  template:
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: ${schema.spec.tenantId}-quota
      namespace: ${schema.spec.tenantId}
      labels:
        saas/tenant-id: ${schema.spec.tenantId}
    spec:
      hard:
        requests.cpu: "1"
        requests.memory: "1Gi"
        limits.cpu: "2"
        limits.memory: "2Gi"
- id: tenantNetworkpolicy
  template:
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: ${schema.spec.tenantId}-isolation
      namespace: ${schema.spec.tenantId}
      labels:
        saas/tenant-id: ${schema.spec.tenantId}
    spec:
      podSelector:
        matchLabels:
      ingress:
      - from:
        - podSelector: {}

Brought to you with ♥ by SIG Cloud Provider