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 aprod
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).
- Kubernetes creates a few namespaces by default:
- 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
.
- Services in different namespaces can be accessed via
- 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 containsnginx-deploy-dev
deployment andsvc-dev
serviceprod
namespace containsnginx-deploy-prod
deployment andsvc-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) workedcurl 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
- curl
- Fully Qualified Domain Names (FQDNs)
- When you tried
curl svc-prod
from dev namespace, it didn't workcurl: (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.
- When you tried
ndots:5:
"If a domain name has 5 or more dots, try it as-is first before appending search domains", so remove it.