KubernetesCVII · Namespaces and Multi-TenancyMulti-tenancy
Soft multi-tenancy with RBAC, NetworkPolicy, and Quotas — the production stack
What you'll learn
- Build the production multi-tenancy stack with RBAC, NetworkPolicy, ResourceQuota, PSS
- Apply default-deny NetworkPolicy with explicit allow rules
- Configure PSS (privileged, baseline, restricted)
- 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
The soft multi-tenancy production stack combines RBAC, NetworkPolicy, ResourceQuota, and PSS. This lesson walks each layer, the integration, the anti-patterns, and the operational discipline.
The stack
flowchart LR
A[Production stack] --> B[RBAC]
A --> C[NetworkPolicy]
A --> D[ResourceQuota]
A --> E[PSS]
B --> B1["Identity: who can do what"]
C --> C1["Traffic: who can talk to who"]
D --> D1["Resources: how much can be used"]
E --> E1["Workloads: what can run"]
The four layers:
- RBAC. Identity and authorisation. Who can create, read, update, delete objects.
- NetworkPolicy. Network traffic. Who can talk to whom.
- ResourceQuota. Compute and storage limits. How much can be used.
- PSS. Workload security. What kinds of Pods can run.
Each layer addresses a different isolation requirement. Missing any one breaks the stack.
RBAC for multi-tenancy
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tenant-a-developer
namespace: tenant-a-prod
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["pods", "services", "configmaps", "deployments", "statefulsets", "jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tenant-a-developers
namespace: tenant-a-prod
subjects:
- kind: Group
name: tenant-a-developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: tenant-a-developer
apiGroup: rbac.authorization.k8s.io
RBAC best practices for multi-tenancy:
- Roles are namespace-scoped. Use Roles, not ClusterRoles, for tenant permissions.
- Subjects are Groups. Bind to groups, not individual users.
- No wildcards in verbs or resources. Be specific.
- ClusterRoles only for platform components. cert-manager, Argo CD, etc.
NetworkPolicy for multi-tenancy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: tenant-a-prod
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: tenant-a-prod
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # any pod in the same namespace
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: tenant-a-prod
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
NetworkPolicy best practices:
- Default-deny first. Block all traffic.
- Explicit allow rules. Allow same-namespace traffic, DNS egress, ingress from specific sources.
- No default-allow. A cluster without NetworkPolicy is default-allow; add explicit policies.
ResourceQuota for multi-tenancy
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-a-quota
namespace: tenant-a-prod
spec:
hard:
requests.cpu: "32"
requests.memory: 64Gi
limits.cpu: "64"
limits.memory: 128Gi
pods: "200"
persistentvolumeclaims: "50"
requests.storage: 1Ti
services: "100"
secrets: "100"
configmaps: "100"
count/deployments.apps: "50"
count/statefulsets.apps: "20"
ResourceQuota best practices:
- Bound compute. CPU and memory requests and limits.
- Bound storage. requests.storage for PVCs.
- Bound object counts. pods, services, secrets, configmaps, etc.
- Per-namespace. Each tenant has its own quota.
PSS for multi-tenancy
apiVersion: v1
kind: Namespace
metadata:
name: tenant-a-prod
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: latest
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: latest
PSS levels:
- privileged. Unrestricted; no security controls. Avoid.
- baseline. Minimal restrictions; prevents known privilege escalations.
- restricted. Strong restrictions; hardened baseline.
Production namespaces should use restricted.
The integration
flowchart LR
A[User authenticates] --> B[kubectl]
B --> C{API server: RBAC check}
C -->|Denied| D[403 Forbidden]
C -->|Allowed| E[Object created]
E --> F{Admission: PSS check}
F -->|Failed| G[Rejected]
F -->|Passed| H[Object stored]
H --> I{Pod scheduled}
I --> J{CNI: NetworkPolicy check}
J -->|Denied| K[Traffic blocked]
J -->|Allowed| L[Traffic flows]
The layers integrate:
- RBAC checks the user’s identity and permissions.
- Admission (including PSS) checks the object’s spec against policy.
- The scheduler places the Pod on a node.
- The CNI enforces NetworkPolicy.
A failure at any layer blocks the action. The discipline is to apply every layer.
Quiz
Knowledge check · 4 questions
Q1. Which layer of the soft multi-tenancy stack bounds a tenant's resource consumption?
Q2. A ResourceQuota on `requests.cpu` alone prevents a namespace from exhausting node CPU.
Q3. A namespace has RBAC, NetworkPolicy, and a quota, but a privileged Pod is running in it; identify the missing layer and restore it.
`tenant-c-prod` was created from the tenant template three weeks ago. `kubectl get ns tenant-c-prod --show-labels` shows `tenant=c,env=prod` and no `pod-security.kubernetes.io/*` labels at all. A Pod named `debug-shell` in that namespace has `privileged: true` and `hostPID: true` in its security context, has no owning controller, and has been running for nine days.
Q4. In what order do RBAC, Pod Security admission, the scheduler, and NetworkPolicy act on a request to create a Pod, and which of the four is not enforced by the API server?
Passing score: 75%. Answers are checked in this browser.
The operational discipline
The multi-tenancy stack in production rests on five non-negotiable elements:
- Apply every layer. RBAC, NetworkPolicy, ResourceQuota, PSS. None is optional.
- Default-deny NetworkPolicy. Block by default; allow explicitly.
- PSS restricted. No privileged containers in production namespaces.
- Test every layer. Quarterly: verify each layer is enforced.
- Audit policies. Periodic review of every namespace.
The stack is a system. Missing any layer breaks the system. The discipline is to apply every layer and test each one.