Monitoring Cluster and Application Resource Usage
Introduction
This tutorial guides you through monitoring resource usage in a Kubernetes cluster. You’ll learn how to use kubectl and the Metrics Server to monitor CPU and memory consumption at both the cluster and pod level. This is crucial for understanding application performance, identifying bottlenecks, and optimizing resource allocation.
Prerequisites:
- A running Kubernetes cluster (e.g., Minikube, Kind, or a cloud-based cluster).
kubectlconfigured to interact with your cluster.- Basic understanding of Kubernetes concepts like Pods, Namespaces, and Deployments.
Task 1: Deploying the Metrics Server
The Metrics Server is a cluster-wide aggregator of resource usage data. It collects metrics from Kubelets and exposes them through the Kubernetes API.
-
Download the Metrics Server manifest:
NODE_TYPE // bashwget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -
Apply the manifest:
NODE_TYPE // bashkubectl apply -f components.yamlIf you encounter RBAC errors, you might need to add--validate=falseto thekubectl applycommand to bypass validation. -
Verify the Metrics Server deployment:
NODE_TYPE // bashkubectl get deployments -n kube-system metrics-serverExpected Output:
NODE_TYPE // outputNAME READY UP-TO-DATE AVAILABLE AGE metrics-server 1/1 1 1 1m -
Check the Metrics Server logs (optional):
If the deployment isn’t ready, check the logs for errors:
NODE_TYPE // bashkubectl logs -n kube-system -l k8s-app=metrics-serverCommon issues include TLS certificate validation errors. A workaround is to add the
--kubelet-insecure-tlsflag to the Metrics Server deployment. This should ONLY be done in development/testing environments as it disables certificate validation.Edit the deployment:
NODE_TYPE // bashkubectl edit deployment metrics-server -n kube-systemAdd
--kubelet-insecure-tlsto theargssection of themetrics-servercontainer spec:NODE_TYPE // yamlspec: containers: - args: - --cert-dir=/tmp - --secure-port=4443 - --kubelet-insecure-tls # ADD THIS LINE image: k8s.gcr.io/metrics-server/metrics-server:v0.6.1 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /livez port: https scheme: HTTPS periodSeconds: 10 name: metrics-server ports: - containerPort: 4443 name: https protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /readyz port: https scheme: HTTPS periodSeconds: 10 resources: limits: cpu: 100m memory: 300Mi requests: cpu: 100m memory: 200Mi securityContext: readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 1001 volumeMounts: - mountPath: /tmp name: tmp-dirSave the changes. Kubernetes will automatically redeploy the Metrics Server.
Task 2: Monitoring Node Resource Usage
Now that Metrics Server is running, you can use kubectl top node to view resource usage for each node in your cluster.
-
Get node resource usage:
NODE_TYPE // bashkubectl top nodeExpected Output (will vary based on your cluster):
NODE_TYPE // outputNAME CPU(cores) CPU% MEMORY(bytes) MEMORY% minikube 185m 9% 874Mi 44%This command displays the CPU and memory usage for each node. The
CPU(cores)column shows the CPU usage in millicores, andCPU%shows the percentage of total CPU capacity being used. Similarly,MEMORY(bytes)shows the memory usage in bytes, andMEMORY%shows the percentage of total memory capacity.
Task 3: Monitoring Pod Resource Usage
You can also monitor resource usage for individual pods using kubectl top pod.
-
Get pod resource usage:
NODE_TYPE // bashkubectl top podExpected Output (will vary based on your deployed pods):
NODE_TYPE // outputNAME CPU(cores) MEMORY(bytes) coredns-66c46b6d5c-mzlzj 4m 22Mi etcd-minikube 24m 114Mi kube-apiserver-minikube 52m 349Mi kube-controller-manager-minikube 15m 70Mi kube-proxy-7z59z 2m 20Mi kube-scheduler-minikube 5m 24Mi metrics-server-7cd5fcb8b7-k2s2m 3m 14Mi storage-provisioner 2m 13MiThis command displays the CPU and memory usage for each pod in the current namespace. If you want to monitor pods in a specific namespace, use the
-nflag:NODE_TYPE // bashkubectl top pod -n <namespace>For example:
NODE_TYPE // bashkubectl top pod -n kube-system
Task 4: Deploying a Sample Application
To further demonstrate pod monitoring, let’s deploy a simple application.
-
Create a deployment: Create a file named
nginx-deployment.yamlwith the following content:NODE_TYPE // yamlapiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 200m memory: 256Mi -
Apply the deployment:
NODE_TYPE // bashkubectl apply -f nginx-deployment.yaml -
Verify the deployment:
NODE_TYPE // bashkubectl get deploymentsExpected Output:
NODE_TYPE // outputNAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 2/2 2 2 1m -
Monitor the Nginx pods:
NODE_TYPE // bashkubectl top podYou should now see the CPU and memory usage for the Nginx pods.
Task 5: Understanding Resource Requests and Limits
In the nginx-deployment.yaml file, you defined resources with requests and limits. Let’s clarify these concepts:
-
Requests: The minimum amount of resources (CPU and memory) that the pod is guaranteed to receive. The Kubernetes scheduler uses these values to decide which node has enough capacity to run the pod.
-
Limits: The maximum amount of resources that the pod is allowed to use. If a pod attempts to exceed its memory limit, it may be terminated by the OOM (Out Of Memory) killer. If a pod exceeds its CPU limit, it will be throttled.
It’s crucial to set appropriate resource requests and limits to ensure application stability and efficient resource utilization. Setting requests too low can lead to performance issues, while setting limits too high can waste resources.
Task 6: Using kubectl describe to view resource information.
The kubectl describe command will give you details on a pod and include its resource requests and limits.
-
Describe the Nginx pod
First you need to get the name of one of the Nginx pods.
NODE_TYPE // bashkubectl get podsExample output:
NODE_TYPE // outputNAME READY STATUS RESTARTS AGE nginx-deployment-6d6b4c6b98-gq69g 1/1 Running 0 2m nginx-deployment-6d6b4c6b98-v587x 1/1 Running 0 2mNow run the describe command on one of the Nginx pods.
NODE_TYPE // bashkubectl describe pod nginx-deployment-6d6b4c6b98-gq69gThe output contains a lot of information, but search for the “Resources:” section. It will show you the requests and limits for the containers in the pod.
NODE_TYPE // outputContainers: nginx: Container ID: docker://b81549698b6593c9e29938094b2239ac80b799ee5153060842f128474118e460 Image: nginx:latest Image ID: docker-pullable://nginx@sha256:8efd9af229fca91c495c8c009006c6263e834b57395606dca59b3b383ad41868 Port: 80/TCP Host Port: 0/TCP State: Running Started: Thu, 09 Apr 2026 14:00:02 UTC Ready: True Restart Count: 0 Limits: cpu: 200m memory: 256Mi Requests: cpu: 100m memory: 128Mi Readiness: http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rnlvz (ro)
Conclusion
You have successfully learned how to monitor cluster and application resource usage in Kubernetes using kubectl and the Metrics Server. You deployed the Metrics Server, monitored node and pod resource usage, and gained an understanding of resource requests and limits. This knowledge is crucial for managing and optimizing your Kubernetes deployments. Remember to adjust resource requests and limits based on your application’s needs to ensure stability and efficient resource utilization.