KubernetesCVII · Namespaces and Multi-TenancyMulti-tenancy
Tenant onboarding and isolation testing — the operational discipline
What you'll learn
- Build a tenant onboarding checklist
- Run isolation tests (network, RBAC, ResourceQuota, PSS)
- Audit isolation policies periodically
- Apply the operational discipline of testing every layer
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Tenant onboarding and isolation testing are the operational discipline of multi-tenancy. This lesson walks the onboarding checklist, the isolation tests, the audit cadence, and the operational discipline.
The onboarding checklist
flowchart LR
A[Tenant onboarding] --> B[Create namespace]
B --> C[Apply RBAC]
C --> D[Apply NetworkPolicy]
D --> E[Apply ResourceQuota]
E --> F[Apply PSS labels]
F --> G[Configure secrets]
G --> H[Document in runbook]
H --> I[Tenant is ready]
The onboarding checklist:
- Create namespace. With metadata labels (tenant ID, environment, owner).
- Apply RBAC. Roles and RoleBindings scoped to the namespace.
- Apply NetworkPolicy. Default-deny + explicit allow rules.
- Apply ResourceQuota. Bounded CPU, memory, object counts, storage.
- Apply PSS labels.
restrictedenforcement. - Configure secrets. Vault, sealed-secrets, or External Secrets Operator.
- Document in runbook. Tenant ID, contacts, quotas, policies.
A onboarding script
#!/bin/bash
# onboard-tenant.sh <tenant-name> <environment>
TENANT=$1
ENV=$2
NS="${TENANT}-${ENV}"
# 1. Create namespace
kubectl create namespace "$NS" \
--labels="tenant=$TENANT,env=$ENV,pod-security.kubernetes.io/enforce=restricted"
# 2. Apply NetworkPolicy (default-deny + DNS allow)
kubectl apply -n "$NS" -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- port: 53
protocol: UDP
EOF
# 3. Apply ResourceQuota
kubectl apply -n "$NS" -f - <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
spec:
hard:
requests.cpu: "32"
requests.memory: 64Gi
pods: "200"
persistentvolumeclaims: "50"
EOF
# 4. Apply LimitRange
kubectl apply -n "$NS" -f - <<EOF
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
EOF
# 5. Apply RBAC
kubectl create rolebinding "$TENANT-developers" \
--clusterrole=edit \
--namespace="$NS" \
--group="$TENANT-developers"
The script applies the full stack. Every tenant goes through the same onboarding.
The isolation tests
flowchart TD
A[Isolation tests] --> B[Cross-namespace network blocked]
B --> C[Cross-namespace RBAC denied]
C --> D[ResourceQuota enforced]
D --> E[PSS blocks privileged]
E --> F[External secrets not accessible]
F --> G[Audit log]
The isolation tests:
- Cross-namespace network blocked. A Pod in tenant A cannot reach a Pod in tenant B.
- Cross-namespace RBAC denied. A user with RoleBinding in tenant A cannot list objects in tenant B.
- ResourceQuota enforced. A namespace that exceeds its quota is rejected.
- PSS blocks privileged. A Pod that requests
privileged: truein arestrictednamespace is rejected. - External secrets not accessible. A Pod in tenant A cannot mount a Secret from tenant B.
Each test verifies a different layer.
An isolation test script
#!/bin/bash
# isolation-test.sh
PASS=0
FAIL=0
# Test 1: cross-namespace network blocked
kubectl run --rm -it --image=busybox -n tenant-a test -- \
wget --timeout=2 tenant-b-pod-ip 2>&1 > /tmp/test1
if grep -q "timeout" /tmp/test1; then
echo "PASS: cross-namespace network blocked"
PASS=$((PASS+1))
else
echo "FAIL: cross-namespace network allowed"
FAIL=$((FAIL+1))
fi
# Test 2: cross-namespace RBAC denied
kubectl auth can-i list pods --namespace=tenant-b \
--as=tenant-a-user
# Should be "no"
# Test 3: ResourceQuota enforced
# Create a Pod that exceeds the quota
kubectl apply -n tenant-a -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: over-quota
spec:
containers:
- name: app
image: myapp
resources:
requests:
cpu: 1000 # exceeds the quota of 32 cores for the namespace
EOF
# Should be rejected by the quota admission controller
echo "Results: $PASS passed, $FAIL failed"
The script automates the isolation tests. Run nightly or in CI.
The audit cadence
flowchart LR
A[Audit cadence] --> B["Daily: automated isolation tests"]
B --> C["Weekly: review namespace list"]
C --> D["Monthly: review RBAC bindings"]
D --> E["Quarterly: review policies and quotas"]
E --> F["Annually: external security review"]
The cadence:
- Daily. Automated isolation tests; alert on failures.
- Weekly. Review the namespace list; new tenants applied the full stack?
- Monthly. Review RBAC bindings; any over-permissioned identities?
- Quarterly. Review policies (NetworkPolicy, ResourceQuota, PSS); any drift?
- Annually. External security review; verify the multi-tenancy model is appropriate.
Quiz
Knowledge check · 4 questions
Q1. How should tenant isolation be verified after onboarding?
Q2. Confirming that RBAC, NetworkPolicy, and quota objects exist is sufficient evidence of tenant isolation.
Q3. A namespace created by hand during an incident has carried production traffic for six weeks; bring it up to the tenancy standard without an outage.
During a failover last quarter someone ran `kubectl create namespace hotfix-billing` and deployed three services into it. The weekly audit script now reports no NetworkPolicy, no ResourceQuota, no LimitRange, no PSS labels, and a ClusterRoleBinding granting `cluster-admin` to the group `billing-devs`. The namespace serves live billing traffic.
Q4. Write the command that proves a ServiceAccount bound only in `tenant-a` cannot list Pods in `tenant-b`, and say why a `no` from it is not evidence that the two tenants are network-isolated.
Passing score: 75%. Answers are checked in this browser.
The operational discipline
Tenant onboarding and isolation testing in production rest on five non-negotiable elements:
- Onboarding script. Every tenant goes through the same process.
- Runbook entry. Each tenant has documented quotas, policies, contacts.
- Automated isolation tests. Daily or in CI.
- Audit cadence. Daily, weekly, monthly, quarterly, annually.
- Drift detection. Alert when a tenant’s policies change unexpectedly.
Multi-tenancy is a process, not a one-time setup. The discipline is the process: onboarding, testing, auditing, drift detection.