As a Site Reliability Engineer with 17 years of experience, I’ve seen firsthand how crucial proper resource management is in Kubernetes environments. Today, we’re diving deep into setting resource requests and limits in Kubernetes – a fundamental skill for any SRE or DevOps engineer working with container orchestration.
Understanding Kubernetes Resource Management
Before we jump into the practical steps, let’s brush up on some key concepts:
- Pod Resource Usage: Pods consume resources from the nodes they’re scheduled on. Kubernetes needs to know how much CPU and memory a pod requires to make informed scheduling decisions.
- Requests vs. Limits:
- Requests are what the container is guaranteed to get.
- Limits are the maximum amount of resources that the container can use.
- Priority Levels:
- High Priority: Requests = Limits
- Medium Priority: Requests ≠ Limits
- Low Priority: Requests = Null | Limits = Null
Practical Implementation
Let’s walk through the process of setting up and testing resource management in Kubernetes. We’ll use a local Kind cluster for this demonstration. I’ll provide both the direct commands and their corresponding Makefile aliases for each step.
Before we begin, make sure you have the following set up on your computer:
- Docker
- Kind (Kubernetes in Docker)
If you haven’t installed these tools yet, don’t worry! Check out the links in the video description for my tutorials on installing them on Windows, Mac, and Ubuntu.
Step 1: Create a Kind Cluster
First, let’s create a Kind cluster:
# Direct command
kind create cluster --name resources --config kind/kind-config.yaml
# Makefile alias
make create-cluster
Step 2: Create and Apply a Pod with Resource Specifications
Let’s create a pod YAML file with resource specifications:
# Direct command
kubectl run nginx --image=nginx:latest --port=80 --dry-run=client -o yaml > deployment/app/pod.yaml
# Makefile alias
make create-pod-file
Now, modify the pod.yaml
File to include resource requests and limits. Here’s an example:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Apply the pod configuration:
# Direct command
kubectl apply -f deployment/app/pod-resources.yaml
# Makefile alias
make apply-pod
Step 3: Enable Metrics Server
To monitor resource usage, we need to enable the Metrics Server:
# Direct command
kubectl apply -f metrics/components.yaml
# Makefile alias
make enable-metrics
Verify that the Metrics Server is running:
# Direct command
kubectl -n kube-system get pods | grep metrics-server
# Makefile alias
make check-metrics
Step 4: Monitor Resource Usage
Now, let’s monitor our resource usage:
# Monitor node resources
# Direct command
while true; do kubectl top nodes; sleep 2; done
# Makefile alias
make show-node-resource
# Monitor pod resources
# Direct command
while true; do kubectl top pod; sleep 2; done
# Makefile alias
make show-pod-resource
Step 5: Test Resource Limits
To test our resource limits, we’ll deploy CPU and memory-intensive applications:
# Deploy CPU-intensive app
# Direct command
kubectl apply -f deployment/cpu/deployment.yaml
# Makefile alias
make create-cpu
# Deploy memory-intensive app
# Direct command
kubectl apply -f deployment/memory/deployment.yaml
# Makefile alias
make create-memory
Now, let’s generate some load:
# Create traffic generator
# Direct command
kubectl apply -f deployment/traffic/traffic-generator.yaml
# Makefile alias
make create-traffic
# Install wrk in the traffic generator
# Direct command
kubectl exec -it traffic-generator -- apk add --no-cache wrk
# Makefile alias
make add-app-traffic
# Generate load on CPU app
# Direct command
kubectl exec -it traffic-generator -- wrk -c 7 -t 7 -d 99999 -H "Connection: Close" http://cpu
# Makefile alias
make start-app-traffic-cpu
# Generate load on memory app
# Direct command
kubectl exec -it traffic-generator -- wrk -c 7 -t 7 -d 99999 -H "Connection: Close" http://memory
# Makefile alias
make start-app-traffic-memory
Monitor the resource usage as the load increases. You should see the CPU and memory usage climb but never exceed the limits we set.
Step 6: Break the Limits
Now, let’s try to exceed our limits:
# Stress test CPU
# Direct command
kubectl exec -it traffic-generator -- wrk -c 100 -t 100 -d 99999 -H "Connection: Close" http://cpu
# Makefile alias
make break-cpu
# Stress test memory
# Direct command
kubectl exec -it traffic-generator -- wrk -c 7 -t 7 -d 99999 -H "Connection: Close" http://memory
# Makefile alias
make break-memory
Watch what happens when we hit our resource limits. You might see pods being terminated or throttled.
Cleanup
After you’re done with the demonstration, you can clean up your environment:
# Delete the Kind cluster
# Direct command
kind delete cluster --name resources
# Makefile alias
make delete-all
Conclusion
Setting appropriate resource requests and limits is crucial for maintaining a stable and efficient Kubernetes cluster. It helps prevent resource contention, ensures fair resource allocation, and can even help with cost optimization in cloud environments.
Remember:
- Always set both requests and limits for critical workloads.
- Monitor your actual usage and adjust accordingly.
- Be cautious with memory limits, as hitting them can cause pod termination.
- CPU limits throttle performance but doesn’t terminate pods.
By mastering resource management, you’re taking a big step toward becoming a Kubernetes expert. Happy clustering!