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.