Namespaces and Multi-Tenancy
Namespace management, ResourceQuota, LimitRange, resource isolation, and cross-namespace communication
Overview
Namespaces provide a resource isolation mechanism within a Kubernetes cluster. The CKA exam focuses on namespace creation, ResourceQuota and LimitRange configuration, and namespace-level resource management.
1. Namespace Creation and Management
1.1 Creating Namespaces
kubectl create namespace team-a
kubectl create ns team-b
# Declarative YAML
apiVersion: v1
kind: Namespace
metadata:
name: team-a
# Generate YAML
kubectl create namespace team-a --dry-run=client -o yaml
1.2 Viewing Namespaces
# View all namespaces
kubectl get namespaces
kubectl get ns
# View namespace details
kubectl describe namespace team-a
# View resource quotas in a namespace
kubectl get quota -n team-a
kubectl describe quota -n team-a
# View resources in a namespace
kubectl get all -n team-a
kubectl get pods,svc,deploy -n team-a
1.3 Switching Namespaces
# Specify the namespace in commands
kubectl get pods -n team-a
kubectl get pods --namespace=team-a
# All namespaces
kubectl get pods --all-namespaces
kubectl get pods -A
# Set the default namespace for kubectl context (not commonly used in the exam; not persisted server-side)
kubectl config set-context --current --namespace=team-a
1.4 Deleting Namespaces
# Delete a namespace (deletes all resources within it)
kubectl delete namespace team-a
# Force delete a namespace stuck in Terminating state
kubectl delete namespace team-a --force --grace-period=0
2. ResourceQuota
ResourceQuota limits the total resource usage within a namespace.
2.1 Compute Resource Quota
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: team-a
spec:
hard:
requests.cpu: "4" # Total CPU requests upper limit
requests.memory: "8Gi" # Total memory requests upper limit
limits.cpu: "8" # Total CPU limits upper limit
limits.memory: "16Gi" # Total memory limits upper limit
# Imperative creation
kubectl create quota compute-quota -n team-a \
--hard=requests.cpu=4,requests.memory=8Gi,limits.cpu=8,limits.memory=16Gi
# View
kubectl get quota -n team-a
kubectl describe quota compute-quota -n team-a
# View usage (Used / Hard)
kubectl get quota compute-quota -n team-a -o yaml
2.2 Object Count Quota
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota
namespace: team-a
spec:
hard:
pods: "10"
services: "5"
configmaps: "5"
secrets: "5"
persistentvolumeclaims: "3"
replicationcontrollers: "5"
services.loadbalancers: "2"
services.nodeports: "0" # Disallow NodePort Services
# Imperative
kubectl create quota object-quota -n team-a \
--hard=pods=10,services=5,configmaps=5,secrets=5
2.3 Quota Scopes
apiVersion: v1
kind: ResourceQuota
metadata:
name: scoped-quota
namespace: team-a
spec:
hard:
cpu: "2"
memory: "2Gi"
scopes:
- BestEffort # Only applies to BestEffort QoS Pods
Available Scopes:
| Scope | Description |
|---|---|
BestEffort | BestEffort QoS Pod |
NotBestEffort | Non-BestEffort QoS Pod |
Terminating | spec.activeDeadlineSeconds is set |
NotTerminating | spec.activeDeadlineSeconds is not set |
PriorityClass | Specified PriorityClass |
# Quota for a specific PriorityClass
apiVersion: v1
kind: ResourceQuota
metadata:
name: priority-quota
namespace: team-a
spec:
hard:
pods: "5"
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values:
- high-priority
2.4 Relationship Between Quota and LimitRange
Important: When a ResourceQuota is set (e.g., requests.cpu), Pods must specify CPU requests when created. Therefore, a LimitRange must be used in conjunction to provide default values.
# Correct order:
# 1. Create LimitRange (provides default values)
# 2. Create ResourceQuota (limits total)
# 3. Create Pods (default to LimitRange values)
# LimitRange must exist before ResourceQuota, otherwise Pod creation will be rejected for lacking requests
3. LimitRange
LimitRange sets default resource limits for Pods/containers within a namespace.
3.1 Complete LimitRange Configuration
apiVersion: v1
kind: LimitRange
metadata:
name: resource-limits
namespace: team-a
spec:
limits:
- type: Pod
max:
cpu: "4"
memory: "8Gi"
min:
cpu: 100m
memory: 64Mi
- type: Container
default: # Default limits
cpu: 500m
memory: 256Mi
defaultRequest: # Default requests
cpu: 250m
memory: 128Mi
max:
cpu: "2"
memory: "4Gi"
min:
cpu: 50m
memory: 32Mi
- type: PersistentVolumeClaim
max:
storage: 100Gi
min:
storage: 1Gi
# Create LimitRange
kubectl apply -f limitrange.yaml
# View
kubectl get limitrange -n team-a
kubectl get limits -n team-a
kubectl describe limitrange resource-limits -n team-a
3.2 LimitRange Notes
- Only affects Pods created after the LimitRange is applied; does not affect existing Pods
- If a Pod's values exceed the LimitRange's max/min, the Pod will be rejected
- Different types (Pod / Container / PVC) can be configured separately
4. Namespace-Level Resource Isolation
4.1 Network Isolation
By default, Pods in different namespaces can communicate with each other. NetworkPolicies can restrict cross-namespace communication.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-cross-ns
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: team-a # Only allow this namespace
NetworkPolicy is in CKA Domain 5; this is for awareness only.
4.2 Service Discovery Isolation
# Cross-namespace Service access
# Format: <service>.<namespace>.svc.cluster.local
curl http://web-service.team-b.svc.cluster.local
# Same namespace: use the service name directly
curl http://web-service
4.3 Resource Quota Isolation
# Create isolated environments for each team
kubectl create namespace team-a
kubectl create namespace team-b
# team-a: CPU-intensive
kubectl create quota -n team-a --hard=requests.cpu=8,limits.cpu=16,requests.memory=16Gi,pods=20
# team-b: Memory-intensive
kubectl create quota -n team-b --hard=requests.cpu=4,limits.cpu=8,requests.memory=32Gi,pods=10
5. Cross-Namespace Communication
5.1 DNS Format
<service-name>.<namespace>.svc.cluster.local
# Access a database in team-b from the team-a namespace
kubectl run -n team-a test --image=busybox --rm -it --restart=Never -- \
wget -O- http://db-service.team-b.svc.cluster.local:3306
# Or use netshoot
kubectl run -n team-a netshoot --image=nicolaka/netshoot --rm -it --restart=Never -- \
curl http://db-service.team-b:3306
5.2 Cross-Namespace Secret/ConfigMap Access
# By default, cross-namespace references are not allowed
# Incorrect example: a Pod in team-a cannot reference a ConfigMap in team-b
# Solution: copy the configuration to the target namespace
kubectl get secret db-secret -n team-b -o yaml | sed 's/namespace: team-b/namespace: team-a/' | kubectl apply -f -
6. Practical Exam Commands
# 1. Quickly create a namespace and quota
kubectl create ns development
kubectl create quota dev-quota -n development \
--hard=requests.cpu=2,requests.memory=4Gi,limits.cpu=4,limits.memory=8Gi,pods=10
# 2. Simultaneously create a LimitRange (must exist, otherwise Pods will be rejected for lacking requests)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limits
namespace: development
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 256Mi
defaultRequest:
cpu: 250m
memory: 128Mi
EOF
# 3. Create resources in the namespace
kubectl run nginx -n development --image=nginx
kubectl create deployment web -n development --image=nginx --replicas=3
# 4. View resource usage in the namespace
kubectl get quota -n development
kubectl describe quota dev-quota -n development
# 5. List all Pods across all namespaces
kubectl get pods -A
# 6. Get resources from a specific namespace
kubectl get all -n team-a
# 7. Delete a namespace (and all its resources)
kubectl delete ns development
# 8. Restrict network port types in a namespace
kubectl create quota net-quota -n team-a \
--hard=services.loadbalancers=0,services.nodeports=0
7. Exam Key Points Summary
| Concept | Command / Syntax | Frequency |
|---|---|---|
| Create namespace | kubectl create ns <name> | High |
| ResourceQuota | kubectl create quota --hard=... | Medium |
| LimitRange | YAML creation, kubectl apply -f | Medium |
| Quota inspection | kubectl describe quota | Medium |
| Cross-namespace DNS | <svc>.<ns>.svc.cluster.local | Low |
| Delete namespace | kubectl delete ns <name> | Medium |
Typical Scenario: Creating an Isolated Environment for a Team
# Full workflow
kubectl create ns team-green
kubectl create quota green-quota -n team-green \
--hard=requests.cpu=4,requests.memory=8Gi,pods=15
kubectl apply -f - <<EOF
apiVersion: v1
kind: LimitRange
metadata:
name: green-limits
namespace: team-green
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 256Mi
defaultRequest:
cpu: 200m
memory: 128Mi
EOF
# Verify
kubectl get quota -n team-green
kubectl run nginx -n team-green --image=nginx
kubectl get pods -n team-green
Exam Tip: Note that
kubectl create quotamay not support--dry-run=client -o yaml(CKA 1.29+). If the exam version does not support it, usekubectl create quota --helpto confirm, or create directly via YAML.
🧪 Complete Hands-on Example: Setting ResourceQuota for a Namespace and Verifying Limits
Scenario
Create a namespace and set a ResourceQuota, then verify that Pod creation is rejected when the quota is exceeded.
Prerequisites
- A working Kubernetes cluster
- kubectl configured to connect to the cluster
Steps
Step 1: Create a Namespace and LimitRange
kubectl create namespace team-a
# Expected output: namespace/team-a created
# Create a LimitRange to provide default resource values (ResourceQuota requires Pods to set requests)
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: team-a
spec:
limits:
- default:
cpu: "500m"
memory: "256Mi"
defaultRequest:
cpu: "250m"
memory: "128Mi"
type: Container
EOF
# Expected output: limitrange/default-limits created
Step 2: Create a ResourceQuota
kubectl create quota team-quota -n team-a \
--hard=requests.cpu=1,requests.memory=1Gi,pods=3
# Expected output: resourcequota/team-quota created
# View the ResourceQuota
kubectl describe quota team-quota -n team-a
# Expected output:
# Name: team-quota
# Namespace: team-a
# Resource Used Hard
# ---- --- ----
# pods 0 3
# requests.cpu 0 1
# requests.memory 0 1Gi
Step 3: Create Pods Within the Quota
# Create the 1st Pod
kubectl run nginx-1 -n team-a --image=nginx
# Expected output: pod/nginx-1 created
# Create the 2nd Pod (both --limits and --requests are set, ensuring the CPU quota is not exceeded)
kubectl run nginx-2 -n team-a --image=nginx
# Expected output: pod/nginx-2 created
# Check quota usage
kubectl describe quota team-quota -n team-a
# Expected output:
# Resource Used Hard
# ---- --- ----
# pods 2 3
# requests.cpu 500m 1
# requests.memory 256Mi 1Gi
Step 4: Create a Pod Exceeding CPU Quota (Should Be Rejected)
kubectl run nginx-big -n team-a --image=nginx \
--requests='cpu=1,memory=512Mi'
# Expected output: Error from server (Forbidden): pods "nginx-big" is forbidden: exceeded quota: team-quota, requested: requests.cpu=1, used: requests.cpu=500m, limited: requests.cpu=1
# CPU requests quota: used 500m + requested 1 = 1.5, exceeds the quota of 1
Step 5: Create the 3rd Pod, Reaching the Pod Count Limit
# Create the 3rd normal Pod
kubectl run nginx-3 -n team-a --image=nginx
# Expected output: pod/nginx-3 created
kubectl describe quota team-quota -n team-a
# Expected output: pods Used changes to 3/3
# Create the 4th Pod (exceeds the Pod count quota)
kubectl run nginx-4 -n team-a --image=nginx
# Expected output: Error from server (Forbidden): pods "nginx-4" is forbidden: exceeded quota: team-quota, requested: pods=1, used: pods=3, limited: pods=3
Verification
# Confirm only 3 Pods are running
kubectl get pods -n team-a
# Expected output: nginx-1, nginx-2, nginx-3 all in Running state; nginx-4 does not exist
# View final quota usage
kubectl get quota -n team-a
# Expected output:
# NAME AGE REQUEST
# team-quota 5m pods: 3/3, requests.cpu: 750m/1, requests.memory: 384Mi/1Gi
# Clean up
kubectl delete namespace team-a
# Expected output: namespace "team-a" deleted
Exam Tips
- After setting a ResourceQuota (e.g.,
requests.cpu), Pods must set CPU requests when created, otherwise the API Server rejects them - Therefore, ResourceQuota is usually used together with LimitRange, which provides default values
- In the exam, if
kubectl create quotaerrors on--dry-run, create via YAML directly kubectl describe quotais the most commonly used command for checking quota usage, showing both Used and Hard- If Pod creation fails with
exceeded quota, it means the namespace's resources have reached their upper limit - Deleting a namespace cleans up all resources within it (Pods, ConfigMaps, Secrets, Quotas, etc.), which is very convenient during the exam