Tenancy Basics
This section covers the hands-on primitives of shared-cluster tenancy: creating namespaces and attaching the RBAC, quota, and network policy that turn a name scope into a real boundary.
Search across all documentation pages
This section covers the hands-on primitives of shared-cluster tenancy: creating namespaces and attaching the RBAC, quota, and network policy that turn a name scope into a real boundary.
kubectl configured against a context you can create namespaces in.helm (Helm 3) if you template tenant bundles as charts.kubectl version -o yaml | grep gitVersion
kubectl auth can-i create namespacesThe namespace is the unit of tenancy. Everything else binds to it.
kubectl create namespace team-a
kubectl label namespace team-a tenant=team-a environment=prodkubectl create namespace makes the scope; the object itself isolates nothing yet.tenant and environment are how policies and NetworkPolicies later select this namespace.create for anything permanent.Managing the namespace declaratively keeps it in version control and GitOps flows.
apiVersion: v1
kind: Namespace
metadata:
name: team-a
labels:
tenant: team-a
environment: prod
pod-security.kubernetes.io/enforce: baselinepod-security.kubernetes.io/enforce label activates the built-in Pod Security admission for this namespace.privileged, baseline, and restricted; use restricted for untrusted tenants.kubectl apply -f namespace.yaml so re-applies are idempotent.Workloads authenticate to the API as a ServiceAccount, so each tenant should have its own.
apiVersion: v1
kind: ServiceAccount
metadata:
name: team-a-app
namespace: team-ateam-a-app is invisible to other tenants.spec.serviceAccountName to get a scoped identity.default ServiceAccount.automountServiceAccountToken where the workload does not call the API.RBAC decides who may act inside the namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-devs
namespace: team-a
subjects:
- kind: Group
name: team-a
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.ioRoleBinding grants rights only within its own namespace, even when it references a ClusterRole.edit ClusterRole is a sensible default for app teams; admin adds RBAC management.kubectl auth can-i --as-group=team-a get pods -n team-a.A quota stops a tenant from taking the whole cluster.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "8"
requests.memory: 16Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "50"pods to bound churn and etcd pressure.kubectl describe resourcequota team-a-quota -n team-a.A LimitRange fills in defaults so tenants are not forced to hand-set every value.
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Midefault supplies limits and defaultRequest supplies requests when a container omits them.max and min to enforce ceilings and floors per container.Confirm the boundary behaves as intended.
kubectl get all -n team-a
kubectl describe namespace team-a
kubectl auth can-i --list -n team-a --as-group=team-aget all shows only namespaced workload objects in that tenant.describe namespace surfaces attached quotas and Pod Security labels.auth can-i --list is the fastest way to audit a tenant's effective permissions.By default all pods can talk across namespaces; a default-deny policy reverses that.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: team-a
spec:
podSelector: {}
policyTypes:
- IngresspodSelector selects every pod in the namespace.Ingress with no ingress rules denies all inbound traffic.Follow default-deny with a narrow allow rule.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
tenant: team-anamespaceSelector matches the tenant: team-a label set on the namespace earlier.kubectl run pod and curl between namespaces.Ship namespace, quota, RBAC, and policy together so onboarding is repeatable.
kubectl apply -f tenant-team-a/
kubectl get resourcequota,limitrange,networkpolicy -n team-akubectl apply reconciles the whole set.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026