Lab 19 - Requests, limits and quotas
Lab 19 - Requests, limits and quotas
Goal: install metrics-server, see throttling and OOM kills, and put guard rails on a namespace. Chapter: Requests, limits and quotas
Install metrics-server
# 1 -
kubectl top nodes # error: Metrics API not available
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.9.0/components.yaml
kubectl patch deploy metrics-server -n kube-system --type=json \
-p '[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
kubectl rollout status deploy/metrics-server -n kube-system
sleep 30; kubectl top nodes
--kubelet-insecure-tls: kubeadm kubelets use self-signed serving
certificates. Fine in a lab; in production sign them (serverTLSBootstrap).
# 2 - usage vs requests
kubectl top pods -A --sort-by=cpu | head
kubectl describe node worker01 | grep -A6 'Allocated resources'
QoS classes
# 3 -
cd ~
kubectl create ns res
kubectl config set-context --current --namespace=res
kubectl run besteffort --image nginx:1.27
kubectl run burstable --image nginx:1.27 --overrides='{"spec":{"containers":[{"name":"burstable","image":"nginx:1.27","resources":{"requests":{"memory":"32Mi"}}}]}}'
kubectl run guaranteed --image nginx:1.27 --overrides='{"spec":{"containers":[{"name":"guaranteed","image":"nginx:1.27","resources":{"requests":{"cpu":"100m","memory":"64Mi"},"limits":{"cpu":"100m","memory":"64Mi"}}}]}}'
kubectl get pods -o custom-columns=NAME:.metadata.name,QOS:.status.qosClass
CPU limit = throttling
# 4 - burn CPU with a 200m limit
kubectl run burner --image busybox:1.36 \
--overrides='{"spec":{"containers":[{"name":"burner","image":"busybox:1.36","command":["sh","-c","while true; do :; done"],"resources":{"limits":{"cpu":"200m","memory":"32Mi"}}}]}}'
sleep 60; kubectl top pod burner
About 200m - never more, and never killed. Just slow.
Memory limit = OOMKilled
# 5 - eat memory with a 50Mi limit
kubectl run hog --image busybox:1.36 \
--overrides='{"spec":{"containers":[{"name":"hog","image":"busybox:1.36","command":["sh","-c","tail /dev/zero"],"resources":{"limits":{"memory":"50Mi"}}}]}}'
sleep 20; kubectl get pod hog
kubectl describe pod hog | grep -A5 'Last State'
OOMKilled, exit code 137, then CrashLoopBackOff.
Guard rails: LimitRange and ResourceQuota
# 6 - defaults for everything without resources
cat > limits.yaml <<'YAML'
apiVersion: v1
kind: LimitRange
metadata:
name: defaults
spec:
limits:
- type: Container
defaultRequest: { cpu: "50m", memory: "32Mi" }
default: { cpu: "200m", memory: "128Mi" }
YAML
kubectl apply -f limits.yaml
kubectl run defaulted --image nginx:1.27
kubectl get pod defaulted -o jsonpath='{.spec.containers[0].resources}{"\n"}'
The LimitRange filled in requests and limits at admission.
# 7 - a quota for the namespace
cat > quota.yaml <<'YAML'
apiVersion: v1
kind: ResourceQuota
metadata:
name: team
spec:
hard:
pods: "8"
requests.cpu: "500m"
limits.memory: 1Gi
YAML
kubectl apply -f quota.yaml
kubectl describe quota team
# 8 - exceed it
kubectl create deploy big --image nginx:1.27 --replicas 6
kubectl get deploy big # READY stops below 6
kubectl describe rs -l app=big | grep -i -A2 'exceeded quota' | head -6
The Deployment looks fine, the Pods simply never appear. The reason is on the
ReplicaSet (FailedCreate), not on a Pod.
Discovery
InfodiscoverTask A. Which resource of the quota is exhausted, and how much is used?
Task B. Which Pod in the whole cluster uses the most memory right now?
Clean up
kubectl config set-context --current --namespace=default
kubectl delete ns res
Keep metrics-server - Lab 20 needs it.