Skip to main content

Namespace

A Kubernetes mechanism for partitioning cluster resources into isolated virtual segments. Namespaces allow multiple teams, projects, or environments to share the same physical cluster while maintaining logical separation of workloads, access controls, and resource quotas. They do not provide network isolation by themselves — that requires Network Policies.

Namespace — Splitting One Cluster into Many Worlds

The Real-World Analogy

Think of a Kubernetes cluster as an office building. Namespaces are the individual company floors. Different teams share the same physical building (cluster resources) but have their own locked floors, separate directories (service discovery), and different access cards (RBAC).

◈ DIAGRAM
+------------------------------------------+
| Cluster: mumbai-prod-cluster |
+------------------------------------------+
| | |
v v v
+-------------+ +-----------+ +-----------+
| frontend- | | backend- | | monitoring|
| team | | team | | |
| | | | | |
| web-app-1 | | api-svc-1 | | prometheus|
| web-svc | | db-secret | | grafana |
+-------------+ +-----------+ +-----------+
|
v
+------------------------------------------+
| kube-system (Kubernetes internals) | <- Never delete anything here
| coredns, kube-proxy, metrics-server |
+------------------------------------------+

Default Namespaces That Ship with Kubernetes

Namespace Purpose Touch it?
default Where workloads go if you don't specify a namespace Avoid for production — too easy to create clutter
kube-system Kubernetes control plane components (DNS, proxy, scheduler) Never delete anything here
kube-public Publicly readable cluster data, rarely used Leave it alone
kube-node-lease Node heartbeat tracking objects Leave it alone
Common Mistake

Running everything in the default namespace in production. One accidental kubectl delete pod --all with no -n flag wipes your entire production workload. Use dedicated namespaces per team or environment — always.

Creating and Switching Namespaces

Bash
# Create a namespace imperatively
kubectl create namespace payments-team
# Or with a manifest (preferred for GitOps workflows)
kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: payments-team
labels:
team: payments
environment: production
EOF
# Run commands scoped to a specific namespace
kubectl get pods -n payments-team
# Set your kubeconfig default namespace so you stop typing -n every time
kubectl config set-context --current --namespace=payments-team
# Confirm which namespace your context is using
kubectl config view --minify | grep namespace

What Namespaces Isolate — and What They Don't

◈ DIAGRAM
+------------------------------------------+
| Namespaces DO isolate: |
| |
| * Resource names (two teams can each |
| have a Service called api-svc) |
| * RBAC policies (dev access to |
| frontend-team only) |
| * ResourceQuotas (cap backend-team |
| to 16 CPU total) |
| * Secrets and ConfigMaps |
+------------------------------------------+
+------------------------------------------+
| Namespaces do NOT isolate: |
| |
| * Network traffic — pods in different |
| namespaces can still talk freely |
| * Node assignment — all namespaces |
| share the same physical nodes |
| * StorageClasses, Nodes, PVs — |
| these are cluster-scoped |
+------------------------------------------+
Remember

For true network isolation between namespaces, you need NetworkPolicies with a deny-all default rule. Namespaces alone are organizational containers — they provide zero network security.

Attaching a ResourceQuota to a Namespace

This is how Zerodha's platform team prevents one trading service team from consuming all cluster resources:

YAML
apiVersion: v1
kind: ResourceQuota
metadata:
name: payments-team-quota
namespace: payments-team
spec:
hard:
requests.cpu: "8" # Total CPU requests across all pods in this namespace
requests.memory: 16Gi # Total memory requests
limits.cpu: "16" # Total CPU limits ceiling
limits.memory: 32Gi # Total memory limits ceiling
pods: "50" # Maximum number of pods allowed
secrets: "20" # Maximum number of Secrets
services: "10" # Maximum number of Services
Bash
# Check current quota usage vs limits
kubectl describe quota payments-team-quota -n payments-team
# Output:
# Resource Used Hard
# -------- ---- ----
# limits.cpu 6 16
# limits.memory 12Gi 32Gi
# pods 18 50

Cross-Namespace Service Discovery

Namespaces create separate DNS zones. Services in different namespaces are still reachable, but require the full DNS name:

Bash
# Short name — only works within the SAME namespace
curl http://api-svc:8080
# Full DNS name — works from ANY namespace in the cluster
curl http://api-svc.backend-team.svc.cluster.local:8080
# Format: <service-name>.<namespace>.svc.cluster.local:<port>
# Real examples:
curl http://payment-service.payments-team.svc.cluster.local:8080
curl http://redis.cache.svc.cluster.local:6379
curl http://postgres-0.postgres.production.svc.cluster.local:5432
Common Mistake

Using the short service name from a different namespace and wondering why the connection times out. curl http://api-svc from frontend-team tries to resolve api-svc in the frontend-team namespace — and finds nothing. Always use the full DNS name for cross-namespace communication.

Tip

Use namespace labels consistently (team: payments, environment: production) from day one. Monitoring tools like Prometheus and log aggregators like Loki use these labels to automatically scope metrics and logs per team — retroactively adding labels to a cluster with 30+ namespaces is painful.

Security

Apply a default deny-all NetworkPolicy to every new namespace immediately after creation. This forces engineers to explicitly declare which services can communicate — preventing accidental data exposure between payment and analytics namespaces on a CRED-scale shared cluster.

Frequently Asked Questions

Does a Kubernetes Namespace provide network isolation between workloads?

No — by default, any pod in any namespace can send traffic to any pod in any other namespace on a cluster; Namespaces only provide logical separation for naming, RBAC scoping, and resource quotas (like limiting how much CPU or memory a team's namespace can consume). Actual network isolation requires a NetworkPolicy resource, and even that only takes effect if the cluster's CNI plugin (like Calico or Cilium) supports enforcing NetworkPolicies — some CNIs ignore them entirely.

What's a common mistake teams make when structuring Namespaces?

Creating a namespace per microservice instead of per team or environment often backfires — it multiplies the number of RBAC bindings, quotas, and NetworkPolicies to maintain without a clear isolation benefit, since services within one team usually need to talk to each other anyway. A more common working pattern is namespace-per-environment (dev/staging/prod) or namespace-per-team, with resource quotas and NetworkPolicies applied deliberately rather than by default.