Multi-tenancy
Deploy Laminar in a multi-tenant configuration with isolated environments.
Overview
Laminar supports multi-tenant deployments where each tenant has:
- Isolated namespace - Dedicated Kubernetes namespace
- Separate storage - Isolated RocksDB and object storage paths
- Resource quotas - Configurable resource limits
Architecture
Shared Infrastructure
├── Ingress Controller (nginx/ALB)
├── Monitoring Stack (optional)
└── Cert Manager
Per-Tenant Namespace (tenant-{name})
├── API Server
├── Controller (with RocksDB)
├── Workers (dynamic)
└── ConfigMaps/Secrets
Namespace Per Tenant
Create Tenant Namespace
apiVersion: v1
kind: Namespace
metadata:
name: tenant-acme
labels:
tenant: acme
environment: productionResource Quotas
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
namespace: tenant-acme
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
persistentvolumeclaims: "10"
pods: "50"Limit Ranges
apiVersion: v1
kind: LimitRange
metadata:
name: tenant-limits
namespace: tenant-acme
spec:
limits:
- default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
type: ContainerTenant Installation
Tenant Values File
Create tenant-acme-values.yaml:
nameOverride: acme
fullnameOverride: laminar-acme
api:
replicas: 2
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
controller:
replicas: 2
persistence:
size: 50Gi
# Storage paths - isolated per tenant
storage:
artifacts:
url: "s3://laminar-data/tenants/acme/artifacts"
checkpoints:
url: "s3://laminar-data/tenants/acme/checkpoints"
# Tenant-specific ingress
ingress:
enabled: true
hosts:
- host: acme.laminar.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: acme-tls
hosts:
- acme.laminar.example.comInstall Tenant
helm install laminar-acme laminar/laminar \
--namespace tenant-acme \
--create-namespace \
-f tenant-acme-values.yamlNetwork Isolation
Network Policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: tenant-acme
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressRBAC Configuration
Tenant Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: laminar-acme
namespace: tenant-acme
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: laminar-acme
namespace: tenant-acme
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: laminar-acme
namespace: tenant-acme
subjects:
- kind: ServiceAccount
name: laminar-acme
namespace: tenant-acme
roleRef:
kind: Role
name: laminar-acme
apiGroup: rbac.authorization.k8s.ioShared vs Dedicated Components
| Component | Shared | Dedicated | Recommendation |
|---|---|---|---|
| Ingress Controller | Yes | Optional | Shared with tenant-specific rules |
| RocksDB Storage | No | Yes | Always dedicated per tenant |
| Object Storage | Yes | Yes | Isolated paths per tenant |
| Monitoring | Yes | Optional | Shared with tenant labels |
| Cert Manager | Yes | No | Shared cluster-wide |
Managing Multiple Tenants
With ArgoCD
Create an app-of-apps for tenants:
# tenants-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: laminar-tenants
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/laminar-config.git
targetRevision: main
path: tenants
destination:
server: https://kubernetes.default.svc
namespace: argocdTenant directory structure:
tenants/
├── acme/
│ ├── namespace.yaml
│ ├── values.yaml
│ └── application.yaml
├── beta/
│ ├── namespace.yaml
│ ├── values.yaml
│ └── application.yaml
└── gamma/
├── namespace.yaml
├── values.yaml
└── application.yaml
With Helm
# Install multiple tenants
for tenant in acme beta gamma; do
helm install laminar-$tenant laminar/laminar \
--namespace tenant-$tenant \
--create-namespace \
-f tenants/$tenant/values.yaml
doneTenant Onboarding Checklist
- Create namespace with appropriate labels
- Apply resource quotas and limit ranges
- Configure network policies
- Create service account and RBAC
- Provision storage paths (S3, GCS, etc.)
- Configure ingress with TLS
- Install Laminar with tenant values
- Verify installation and test connectivity
Tenant Removal
# Uninstall Helm release
helm uninstall laminar-acme -n tenant-acme
# Delete namespace (removes all resources)
kubectl delete namespace tenant-acme
# Clean up external storage
aws s3 rm s3://laminar-data/tenants/acme/ --recursiveNext Steps
- High Availability - HA configuration
- Security Hardening - Security best practices
- Resource Sizing - Capacity planning