Kubernetes Namespace Strategy: Multi-Tenant Cluster Management
Every team moving to Kubernetes hits the same question: how should we organize our namespaces? The answer seems simple — but the majority of production incidents we see trace back to this very decision.
Why it matters
Namespace isolation is the foundation of the Kubernetes security model. A poorly designed namespace structure leads to:
- Teams interfering with each other’s resources
- Runaway pods from one service exhausting the entire cluster’s memory
- RBAC rules that become unmanageable over time
- Accidental production deploys to the wrong namespace
Naming convention: team-environment
The most common and sustainable pattern is the <team>-<env> format:
# The structure we used at Teknosa
namespaces:
- frontend-dev
- frontend-uat
- frontend-prod
- backend-dev
- backend-uat
- backend-prod
- platform-prod # cross-cutting services (monitoring, ingress)
The advantage: kubectl get pods -n backend-prod tells you exactly what you’re looking at. Names like default, app, or production become ambiguous two months in.
Resource isolation with ResourceQuota
After creating a namespace, never skip defining a ResourceQuota. One team’s deployment going into an OOM kill can take down an entire node — and everything else running on it.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: backend-prod
spec:
hard:
requests.cpu: "8"
requests.memory: 16Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "50"
services: "20"
Use LimitRange to set per-container defaults as well — so deployments without explicit requests automatically get a sensible value:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: backend-prod
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
RBAC: least privilege per namespace
The classic mistake: granting cluster-admin. Each team should only have access within their own namespaces.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: frontend-team-edit
namespace: frontend-prod
subjects:
- kind: Group
name: frontend-team # OIDC / SSO group
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
The edit ClusterRole permits managing deployments, services, and configmaps by default, but does not allow modifying RBAC rules. A solid starting point for production.
Traffic isolation with Network Policy
By default, all pods in Kubernetes can reach each other. Namespace isolation does not provide automatic network-level isolation — Network Policy is required.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-cross-namespace
namespace: backend-prod
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: backend-prod
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: platform-prod # monitoring access
Production/DR separation on RKE2
At Teknosa we had four environments: dev / uat / prod / dr. We managed separate namespace groups for each environment on a single RKE2 cluster. The critical detail: prod and dr namespaces were pinned to a dedicated node pool using nodeSelector + taint/toleration — eliminating any chance of a dev deployment landing on a production node.
# Production pod spec
nodeSelector:
kubeatlas.io/tier: production
tolerations:
- key: "kubeatlas.io/tier"
operator: "Equal"
value: "production"
effect: "NoSchedule"
Summary
A namespace strategy set up correctly once significantly reduces operational burden over time. In short:
- Use the
team-environmentnaming convention - Define ResourceQuota and LimitRange for every namespace
- Manage RBAC at the namespace level, never with cluster-admin
- Isolation is incomplete without Network Policy
- Separate production workloads from dev with node taints
If you want to assess your cluster’s namespace organization, we can schedule a free 30-minute technical review.