Work with Namespaces

Learn how to work with Kubernetes namespaces for Python environments. This lesson covers the core concepts, practical steps, and troubleshooting tips to help you isolate and organize your Python services.

Focus: work with namespaces for python environments

Sponsored

You’ve got your Python service containerized, wired into a Deployment, and exposed through a Service — maybe even an Ingress. But now your team grows, you add a staging environment, a few cron jobs, and suddenly everything is fighting for the same resources. Endpoints are colliding, kubectl get pods returns a wall of unrelated workloads, and you have no way to say “this is the production Python API” versus “this is a dev experiment.” That chaos is exactly the problem Kubernetes namespaces solve. In this lesson, you’ll learn how to create, manage, and use namespaces to isolate and organize your Python environments — and why this simple step is the difference between a demo cluster and a production-ready one.

The problem this lesson solves

When you first start with Kubernetes, everything goes into the default namespace. It feels fine — your Python app is tiny, you know exactly what’s running. But as you progress, several problems creep in:

  • Resource contention — your staging API competes with production for CPU and memory.
  • Naming collisions — you can’t have two Services both named api in the same namespace, even if they belong to different environments.
  • Unclear ownership — you can’t tell which Pod belongs to which team or environment just by looking at a list.
  • Security risks — any Pod can talk to any Service, and access control becomes a mess.

Without namespaces, you’re flying blind. You might think, “I’ll just name things api-prod and api-staging,” but that’s a band-aid that doesn’t give you resource quotas, network policies, or Role-Based Access Control (RBAC) scoped to an environment. Namespaces are the fundamental unit of isolation in Kubernetes, and if you skip them, you’ll hit a wall the moment you deploy more than a toy app.

Pro tip: Even for personal projects, get into the habit of using namespaces from day one. It costs almost nothing and saves hours of debugging later.

Core concept / mental model

Think of a Kubernetes cluster as an apartment building. The cluster is the whole building, and each namespace is an apartment. Each apartment has its own rooms (Pods, Services, Deployments), its own front door (Service DNS), and its own rules (ResourceQuota, LimitRange, NetworkPolicy). One apartment doesn’t know or care about the others — until you choose to share a hallway (via a cross-namespace Service or Ingress).

In technical terms, a namespace is a logical partition of cluster resources. Kubernetes API objects like Pods, Services, and Deployments belong to exactly one namespace. Cluster-wide resources like Nodes and PersistentVolumes are not namespaced — they exist at the cluster level.

Here’s a word-based diagram of how your Python environments might be organized:

Cluster
├── namespace: production
│   ├── Deployment: fastapi-api
│   ├── Service: fastapi-api
│   └── ConfigMap: app-config
├── namespace: staging
│   ├── Deployment: fastapi-api
│   └── Service: fastapi-api
└── namespace: development
    ├── Deployment: fastapi-api
    └── Service: fastapi-api

Notice that fastapi-api exists in every namespace — that’s allowed because namespaces provide isolation. You can have the same name in different namespaces without conflict.

How it works step by step

Working with namespaces involves creating them, deploying workloads into them, and managing access. Here’s the logical sequence:

Step 1: List existing namespaces

First, see what you already have. Kubernetes always comes with four default namespaces: default, kube-system, kube-public, and kube-node-lease. Don’t delete or modify these.

kubectl get namespaces

Step 2: Create a namespace

You can create a namespace imperatively (quick, for testing) or declaratively (best for version control).

# Imperative
kubectl create namespace production

# Declarative — save this to namespace-production.yaml and run kubectl apply -f
apiVersion: v1
kind: Namespace
metadata:
  name: production

Step 3: Deploy your Python app into the namespace

When you apply a manifest, either set the namespace in the file or pass -n on the command line.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-api
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: fastapi-api
  template:
    metadata:
      labels:
        app: fastapi-api
    spec:
      containers:
      - name: api
        image: python:3.11-slim
        command: ["/bin/sh", "-c"]
        args:
          - pip install fastapi uvicorn && uvicorn main:app --host 0.0.0.0 --port 8000
kubectl apply -f deployment.yaml

Step 4: Switch context to the namespace

To avoid typing -n every time, set your default namespace with kubectl config.

kubectl config set-context --current --namespace production

Now kubectl get pods will only show pods in production.

Step 5: Verify and manage

Check your resources, inspect logs, and clean up when done.

kubectl get pods -n production
kubectl logs deployment/fastapi-api -n production
kubectl delete namespace production  # deletes everything inside it

Hands-on walkthrough

Let’s put this into practice. You’ll create two namespaces — dev and prod — deploy a simple Python “hello” HTTP server to each, and prove they’re isolated.

1. Write a minimal Python server

Create a file server.py (or use a pre-built image like python:3.11-slim with inline code). For simplicity, let’s use a one-line command that runs an HTTP server:

# server.py
from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Hello from Python!")

HTTPServer(('0.0.0.0', 8000), Handler).serve_forever()

2. Create two namespaces

kubectl create namespace dev
kubectl create namespace prod

3. Deploy the same app to both

Create a deployment manifest with the namespace field, but we’ll apply it twice with different namespaces using -n.

# hello-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-python
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: hello
        image: python:3.11-slim
        command: ["/bin/sh", "-c"]
        args:
          - pip install --no-cache-dir -q fastapi uvicorn && echo 'from fastapi import FastAPI; app = FastAPI(); @app.get("/") def root(): return {"msg": "hello"}' > main.py && uvicorn main:app --host 0.0.0.0 --port 8000
        ports:
        - containerPort: 8000
kubectl apply -f hello-deployment.yaml -n dev
kubectl apply -f hello-deployment.yaml -n prod

4. Verify isolation

List pods in each namespace:

kubectl get pods -n dev
kubectl get pods -n prod

Expected output:

NAME                            READY   STATUS    RESTARTS   AGE
hello-python-7d5b9f8d4b-9x1k2   1/1     Running   0          30s

Both namespaces have a pod with the same naming pattern, but they are independent. Try to access the Service — if you expose them, they’ll have different DNS names.

5. Clean up

kubectl delete namespace dev prod

Pro tip: Use kubectl get all -n <namespace> to see everything running in a namespace at a glance.

Compare options / when to choose what

There are several ways to isolate environments in Kubernetes. Let’s compare them.

Approach Use case Pros Cons
Single namespace Early dev, tiny apps Simple, zero overhead No isolation, risk of collisions
Multiple namespaces per environment Common for staging/prod Clear separation, resource quotas, RBAC per environment Slightly more overhead to manage
Separate clusters Compliance, hard multi-tenancy Strongest isolation Cost, operational complexity
Labels + selectors Organizing within a namespace Flexible, no namespace overhead Doesn’t provide isolation or quotas

When to choose what: - Personal project? You can get away with one namespace, but trust me, use two — dev and prod — so you learn the discipline. - Team with staging and production? Use namespaces per environment. - Strict regulatory data separation? Separate clusters are the safer bet.

Troubleshooting & edge cases

Even with namespaces, things go wrong. Here are the common ones and how to fix them.

Error: namespace not found

When you try to apply a manifest with a namespace that doesn’t exist, you get:

Error from server (NotFound): error when creating ... namespaces "production" not found

Fix: Create the namespace first (kubectl create namespace production) or ensure the manifest includes the Namespace object and you apply it first.

Problem: I see all pods, not just mine

If you run kubectl get pods and see everything, your context is set to default. Set your namespace or pass -n.

kubectl config set-context --current --namespace dev

Edge case: Cross-namespace DNS

Services in different namespaces are not reachable by short name. You need the full DNS name: service-name.namespace.svc.cluster.local. If your Python app tries to call http://api but api is in another namespace, it will fail. Use the FQDN.

Gotcha: Deleting a namespace deletes everything

There’s no undo. Make sure you have backups or YAML files before kubectl delete namespace. Use --cascade=orphan if you want to keep the objects but remove the namespace (advanced).

What you learned & what's next

You now understand the purpose of namespaces, how to create them, how to deploy your Python workloads into them, and how to switch between them. You also know the key edge cases like DNS and deletion behavior. You connected this to your Python environments — dev, staging, prod — and you’re ready for the next lesson.

Next up in the Kubernetes for Python Developers track, you’ll dive into Resource Limits and Quotas — how to set CPU and memory boundaries per namespace so one chatty service can’t starve the rest. You’ll use namespaces you just created as the sandbox for those experiments.

Remember: Namespaces are your first tool for organization and isolation. Master them, and the rest of Kubernetes becomes much more manageable.

Practice recap

Create two namespaces, dev and prod, and deploy a simple Python HTTP server to each. Verify they are isolated by listing pods in each and attempting to access a Service by short name from the other namespace. Then clean up by deleting both namespaces.

Common mistakes

  • Forgetting to create the namespace before applying a manifest that references it — you get a 'namespace not found' error.
  • Deploying everything into the default namespace and then wondering why you can't tell environments apart.
  • Trying to call a Service in another namespace using its short name — you need the FQDN (service.namespace.svc.cluster.local).
  • Deleting a namespace without realizing it cascades and deletes all Pods, Services, and ConfigMaps inside it.

Variations

  1. Use kubectl create namespace for quick setup, or manage namespaces as declarative YAML in Git for version control.
  2. Rely on labels and selectors instead of namespaces if you only need organizational grouping without isolation or quotas.
  3. Use separate clusters instead of namespaces when you require hard security isolation or compliance boundaries.

Real-world use cases

  • A SaaS company runs separate namespaces for each customer environment to enforce resource quotas and network policies.
  • A Python microservices team uses dev, staging, and prod namespaces to keep deployments isolated while sharing one cluster.
  • A machine learning platform isolates training jobs in dedicated namespaces with their own GPU quotas and RBAC rules.

Key takeaways

  • Namespaces are logical partitions that isolate resources like Pods, Services, and ConfigMaps within a cluster.
  • Use namespaces per environment (dev, staging, prod) to avoid naming collisions and share cluster resources safely.
  • Set your default namespace with kubectl config set-context --current --namespace <name> to reduce command clutter.
  • Services across namespaces are only reachable via their full DNS name: service.namespace.svc.cluster.local.
  • Deleting a namespace recursively deletes all contained resources — always back up manifests first.
  • Namespaces enable additional management tools like ResourceQuotas and RBAC, making them foundational for production Python deployments.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.