Lesson 2.2: Namespaces and Resource Quotas


Kubernetes Namespaces

A Namespace in Kubernetes is a virtual cluster or a logical boundary that allows you to partition and isolate resources within a single physical Kubernetes cluster. Namespaces enable multiple teams, projects, or environments (e.g., development, staging, production) to share the same cluster while avoiding conflicts and maintaining resource separation.

Why Use Namespaces?

  • Resource Isolation:
    • Separate resources (e.g., Pods, Services, Deployments) for different teams, projects, or environments.
    • Example: A dev namespace for development and a prod namespace for production.
  • Access Control:
    • Apply role-based access control (RBAC) to restrict users or teams to specific namespaces.
  • Avoid Naming Conflicts:
    • Resources can have the same name in different namespaces (e.g., a frontend Deployment in both dev and prod).
  • Resource Quotas:
    • Enforce resource limits (CPU, memory) per namespace to prevent overconsumption.
  • Logical Grouping:
    • Organize resources into logical groups (e.g., monitoring for Prometheus and Grafana).

How Namespaces Work

  • Default Namespaces:
    • Kubernetes creates a few namespaces by default:
      • default: For resources created without specifying a namespace.
      • kube-system: For Kubernetes system components (e.g., kube-proxy, CoreDNS).
      • kube-public: For publicly accessible resources (rarely used).
      • kube-node-lease: For node lease objects (used internally for node heartbeats).
  • Custom Namespaces:
    • You can create namespaces like dev, prod, or team-a.
  • Scoped Resources:
    • Most Kubernetes objects (e.g., Pods, Services, Deployments) are namespaced.
    • Cluster-wide resources (e.g., Nodes, PersistentVolumes, ClusterRoles) are not namespaced.

Getting namespaces

[root@master ~]# kubectl get ns 
NAME                 STATUS   AGE
default              Active   3h47m
kube-node-lease      Active   3h47m
kube-public          Active   3h47m
kube-system          Active   3h47m
local-path-storage   Active   3h47m
# OR
[root@master ~]# kubectl get namespaces 
NAME                 STATUS   AGE
default              Active   3h47m
kube-node-lease      Active   3h47m
kube-public          Active   3h47m
kube-system          Active   3h47m
local-path-storage   Active   3h47m

Creating namespaces

[root@master ~]# kubectl create namespace dev 
namespace/dev created
# OR
[root@master ~]# cat ns.yml 
apiVersion: v1 
kind: Namespace
metadata: 
  name: prod
[root@master ~]# kubectl apply -f ns.yml 
namespace/prod created
 
[root@master ~]# kubectl get ns 
NAME                 STATUS   AGE
default              Active   3h48m
dev                  Active   27s
prod                 Active   5s

Creating Resources with namespace

[root@master ~]# cat deploy-nginx.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: dev
  labels:
    env: demo
spec:
  template:
    metadata:
      name: nginx
      labels:
        env: demo
      annotations:
        kubernetes.io/change-cause: "Deployment with nginx:1.27.4-alpine"
    spec:
      containers:
      - name: nginx
        image: nginx:1.27.4-alpine
  replicas: 3
  selector: 
    matchLabels:
      env: demo 
[root@master ~]# kubectl apply -f deploy-nginx.yml 
 
# Without providing the namespace 
[root@master ~]# kubectl get deployments 
No resources found in default namespace.
[root@master ~]# kubectl get pods 
NAME             READY   STATUS    RESTARTS   AGE
nginx-rc-8ct8h   1/1     Running   0          3h53m
nginx-rc-gfhzz   1/1     Running   0          3h53m
nginx-rc-k2wcr   1/1     Running   0          3h53m
 
# Using the provided namespace 
[root@master ~]# kubectl get deployments --namespace dev
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   3/3     3            3           3m43s
[root@master ~]# kubectl get pods --namespace dev
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-6dc6975759-bztj2   1/1     Running   0          3m49s
nginx-deploy-6dc6975759-c282t   1/1     Running   0          3m49s
nginx-deploy-6dc6975759-chwlt   1/1     Running   0          3m49s
 
# Getting all the resources 
[root@master ~]# kubectl get deployments --all-namespaces
NAMESPACE            NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
dev                  nginx-deploy             3/3     3            3           4m59s
kube-system          coredns                  2/2     2            2           3h57m
local-path-storage   local-path-provisioner   1/1     1            1           3h57m
 
[root@master ~]# kubectl get pods --all-namespaces
NAMESPACE            NAME                                                 READY   STATUS    RESTARTS   AGE
default              nginx-rc-8ct8h                                       1/1     Running   0          3h54m
default              nginx-rc-gfhzz                                       1/1     Running   0          3h54m
default              nginx-rc-k2wcr                                       1/1     Running   0          3h54m
dev                  nginx-deploy-6dc6975759-bztj2                        1/1     Running   0          5m9s
dev                  nginx-deploy-6dc6975759-c282t                        1/1     Running   0          5m9s
dev                  nginx-deploy-6dc6975759-chwlt                        1/1     Running   0          5m9s

Deleting deployment with namespace

# nginx-deploy deployment not deleted becuase it lies in the namespace
[root@master ~]# kubectl delete deployment nginx-deploy
Error from server (NotFound): deployments.apps "nginx-deploy" not found
 
# You have to mention the namespace
[root@master ~]# kubectl delete deployment nginx-deploy --namespace dev
deployment.apps "nginx-deploy" deleted

Common Use Cases

  • Multi-Tenancy:
    • Different teams (e.g., team-a, team-b) use separate namespaces to avoid conflicts.
  • Environment Separation:
    • Use dev, staging, and prod namespaces for different stages of the software lifecycle.
  • Access Control:
    • Restrict developers to the dev namespace while allowing admins full cluster access.
  • Resource Quotas:
    • Limit the dev namespace to 4 CPUs and 8GB RAM, while prod has higher limits.
  • Monitoring and Logging:
    • Deploy monitoring tools (e.g., Prometheus, Grafana) in a dedicated monitoring namespace.

Limitations of Namespaces

  • No Nested Namespaces:
    • Namespaces cannot be nested (e.g., dev/frontend is not allowed).
  • Cluster-Scoped Resources:
    • Some resources (e.g., Nodes, PersistentVolumes) are not namespaced.
  • DNS for Services:
    • Services in different namespaces can be accessed via <service-name>.<namespace>.svc.cluster.local.
  • No Network Isolation:
    • Namespaces do not isolate network traffic by default. Use Network Policies for this.

Example of namespace

# Information dev
[root@master ~]# kubectl get deploy --namespace=dev
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy-dev   3/3     3            3           16h
[root@master ~]# kubectl get pods --namespace=dev -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE                   NOMINATED NODE   READINESS GATES
nginx-deploy-dev-6dc6975759-b6fpg   1/1     Running   0          16h   10.244.1.10   cka-cluster2-worker    <none>           <none>
nginx-deploy-dev-6dc6975759-fxh8j   1/1     Running   0          16h   10.244.2.8    cka-cluster2-worker2   <none>           <none>
nginx-deploy-dev-6dc6975759-zhxvf   1/1     Running   0          16h   10.244.2.7    cka-cluster2-worker2   <none>           <none>
 
[root@master ~]# kubectl get svc --namespace=dev
No resources found in dev namespace.
 
# Accessing prod pod using pod ip 
[root@master ~]# kubectl exec -it nginx-deploy-dev-6dc6975759-b6fpg --namespace=dev -- sh 
/ # curl 10.244.1.8
<html>
<h1>Welcome to nginx!</h1>
</html>
 
# Create service in dev namespace 
[root@master ~]# kubectl expose deployment nginx-deploy-dev --name=svc-dev --port 80 --namespace=dev
service/svc-dev exposed
[root@master ~]# kubectl get svc --namespace=dev
NAME      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
svc-dev   ClusterIP   10.96.69.18   <none>        80/TCP    15s
 
# Curl using the svc IP 
[root@master ~]#  kubectl exec -it nginx-deploy-dev-6dc6975759-b6fpg --namespace=dev -- sh 
/ # curl 10.96.219.79
<html>
<h1>Welcome to nginx!</h1>
</html>
 
# Curl using the svc name of prod 
/ # curl svc-prod
curl: (6) Could not resolve host: svc-prod
 
# Curl using FQDN, if the ndots is set to 5 then remove this part for dev pods 
/ # cat /etc/resolv.conf
search dev.svc.cluster.local svc.cluster.local cluster.local localdomain
nameserver 10.96.0.10
# options ndots:5
 
/ # curl svc-prod.prod.svc.cluster.local
<html>
<title>Welcome to nginx!</title>
</html>
 
# -------------
 
# Information prod 
[root@master ~]# kubectl get deploy --namespace=prod 
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy-prod   3/3     3            3           16h
[root@master ~]# kubectl get pods --namespace=prod -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP           NODE                   NOMINATED NODE   READINESS GATES
nginx-deploy-prod-6dc6975759-dzfvl   1/1     Running   0          16h   10.244.1.8   cka-cluster2-worker    <none>           <none>
nginx-deploy-prod-6dc6975759-ldtlw   1/1     Running   0          16h   10.244.2.6   cka-cluster2-worker2   <none>           <none>
nginx-deploy-prod-6dc6975759-m2cj9   1/1     Running   0          16h   10.244.1.9   cka-cluster2-worker    <none>           <none>
[root@master ~]# kubectl get svc --namespace=prod
No resources found in prod namespace.
[root@master ~]# 
 
# Accessing dev pod using pod ip 
/ # curl 10.244.1.10
<html>
<title>Welcome to nginx!</title>
</html>
 
# Create service in prod namespace 
[root@master ~]# kubectl expose deployment nginx-deploy-prod --name=svc-prod --port=80 --namespace=prod
service/svc-prod exposed
[root@master ~]# kubectl get svc --namespace=prod
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
svc-prod   ClusterIP   10.96.219.79   <none>        80/TCP    8s
 
# Curl using the svc IP 
[root@master ~]#  kubectl exec -it nginx-deploy-prod-6dc6975759-dzfvl --namespace=prod -- sh 
/ # curl 10.96.69.18
<html>
<h1>Welcome to nginx!</h1>
</html>
 
# Curl using the svc name of dev
/ # curl svc-dev
curl: (6) Could not resolve host: svc-dev
 
# Curl using FQDN, if the ndots is set to 5 then remove this part for prod pods
/ # cat /etc/resolv.conf
search prod.svc.cluster.local svc.cluster.local cluster.local localdomain
nameserver 10.96.0.10
# options ndots:5
 
/ # curl svc-dev.dev.svc.cluster.local
<!DOCTYPE html>
<html>
<title>Welcome to nginx!</title>
</html>

In this example:

  • dev namespace contains nginx-deploy-dev deployment and svc-dev service
  • prod namespace contains nginx-deploy-prod deployment and svc-prod service

Resources in different namespaces can communicate directly using:

  • Pod IP addresses (cluster-wide)
    • (e.g., 10.244.1.10) are cluster-wide unique:
    • curl 10.244.1.8 (pod in prod namespace) worked
    • curl 10.244.1.10 (pod in dev namespace) worked
  • Service IP addresses (cluster-wide)
    • curl 10.96.219.79 (prod service) worked
    • curl 10.96.69.18 (dev service) worked
  • Fully Qualified Domain Names (FQDNs)
    • When you tried curl svc-prod from dev namespace, it didn't work curl: (6) Could not resolve host: svc-prod
    • But using FQDN worked: curl svc-prod.prod.svc.cluster.local Namespaces don't provide network isolation by default - they only provide logical separation.

ndots:5: "If a domain name has 5 or more dots, try it as-is first before appending search domains", so remove it.

All systems normal

© 2025 2023 Sanjeeb KC. All rights reserved.