Skip to content

kubectl top — Node Resource Usage & Shell Scripting

Reference: https://kubernetes.io/docs/reference/kubectl/cheatsheet/


The Task

Find the node consuming the most memory in the cluster. Store the result in high_memory_node.txt in the format: current_context,node_name


What kubectl top Does

kubectl top shows real-time CPU and memory usage for nodes or pods. It's the Kubernetes equivalent of top or htop on Linux — except it queries the Metrics Server (an in-cluster component) rather than reading from the OS directly.

kubectl top node

Output:

NAME           CPU(cores)   CPU(%)   MEMORY(bytes)   MEMORY(%)
controlplane   105m         10%      1292Mi          60%
node01         50m          5%       792Mi           43%

Column meanings:

Column What it shows
NAME Node name
CPU(cores) CPU usage in millicores. 105m = 105 millicores = 0.105 of a CPU core
CPU(%) CPU usage as a percentage of the node's total CPU
MEMORY(bytes) RAM in use, shown in Mi (mebibytes)
MEMORY(%) RAM as a percentage of the node's total RAM

Millicores explained: CPU is measured in millicores where 1000m = 1 core. So 105m = about 10% of one CPU core. This unit exists because containers often use fractions of a core and you need a precise way to express that.

Requires Metrics Server: kubectl top will fail with error: Metrics API not available if the Metrics Server isn't installed. In KillerCoda and CKA exam environments it's pre-installed.


What NOT to Do

kubectl get context
# error: the server doesn't have a resource type "context"

context is not a Kubernetes resource — it's a local kubeconfig concept. The API server knows nothing about it. The correct command is:

kubectl config get-contexts      # list all contexts
kubectl config current-context   # show the active context name

kubectl config subcommands operate on ~/.kube/config locally. They never hit the API server.


Manual vs One-liner Approach

What was done manually:

kubectl top node
# visually identify highest memory node
echo "kubernetes-admin@kubernetes,controleplane" > high_memory_node.txt
# then manually fix the typo in vim

Problems: manual reading is error-prone (typo: controleplane), requires two steps, doesn't scale if you have 50 nodes.

The correct one-liner:

echo "$(kubectl config current-context),$(kubectl top node --sort-by=memory --no-headers | head -1 | awk '{print $1}')" > high_memory_node.txt

Full Breakdown — Every Part

Outer Structure

echo "...,..." > high_memory_node.txt

echo prints a string. "..." is the string. > redirects output to the file. The string contains two command substitutions joined by a comma.

$(...) — Command Substitution

$(command) runs command in a subshell and substitutes its output inline. So "$(cmd1),$(cmd2)" becomes "output1,output2".

This is different from backticks `command` which do the same thing but are harder to nest and read. Always prefer $(...).

Part 1: $(kubectl config current-context)

kubectl config current-context
Part What it does
kubectl config Operate on the kubeconfig file
current-context Print the name of the currently active context

Output: kubernetes-admin@kubernetes

No flags needed. Returns a single clean string — perfect for embedding in a command substitution.

Part 2: $(kubectl top node --sort-by=memory --no-headers | head -1 | awk '{print $1}')

Breaking this pipeline stage by stage:

Stage 1:

kubectl top node --sort-by=memory --no-headers

Flag What it does
--sort-by=memory Sort the output by memory usage, highest first. Also accepts cpu
--no-headers Suppress the column header row. Without this, head -1 would grab the header, not the first data row

Output (no headers, sorted by memory descending):

controlplane   108m   10%   1292Mi   60%
node01          42m    4%    798Mi   44%

Stage 2:

| head -1

head -1 takes only the first line. Since the output is sorted by memory descending, the first line = the node with the most memory. Output: controlplane 108m 10% 1292Mi 60%

Stage 3:

| awk '{print $1}'

awk processes text column by column. $1 means the first whitespace-separated field. The first field of controlplane 108m 10% 1292Mi 60% is controlplane. Output: controlplane

awk vs cut vs grep for field extraction:

Tool Use case
awk '{print $1}' Extract by column position (whitespace-separated). Most flexible
cut -f1 -d' ' Cut by delimiter — needs exact delimiter, fragile with multiple spaces
grep Pattern matching — not for field extraction

awk is the right tool here because kubectl top output uses variable-width spaces between columns.

Final Assembly

echo "$(kubectl config current-context),$(kubectl top node --sort-by=memory --no-headers | head -1 | awk '{print $1}')" > high_memory_node.txt

Expands to:

echo "kubernetes-admin@kubernetes,controlplane" > high_memory_node.txt

Result in high_memory_node.txt:

kubernetes-admin@kubernetes,controlplane


Verify the Output

cat high_memory_node.txt

Check: correct context name, no typos, no trailing newline issues, comma-separated exactly as required.


kubectl top for Pods

The same tool works for pods:

kubectl top pod
kubectl top pod -n kube-system
kubectl top pod --sort-by=memory
kubectl top pod --sort-by=cpu
kubectl top pod -A --sort-by=memory   # across all namespaces

Find the pod consuming the most CPU across the cluster:

kubectl top pod -A --sort-by=cpu --no-headers | head -1

Find and save in one shot:

kubectl top pod -A --sort-by=cpu --no-headers | head -1 | awk '{print $1"/"$2}'
# output: namespace/podname


Shell Pipeline Reference

These tools appear constantly in CKA exam one-liners:

Tool What it does Example
head -N Take first N lines head -1 = first line only
tail -N Take last N lines tail -1 = last line only
awk '{print $N}' Print Nth whitespace-separated field awk '{print $1}' = first column
cut -dX -fN Cut by delimiter X, take field N cut -d',' -f2 = 2nd CSV field
sort -k N Sort by column N sort -k4 -n = sort by 4th field numerically
grep pattern Filter lines matching pattern grep Running
grep -v pattern Exclude lines matching pattern grep -v Completed
wc -l Count lines kubectl get pods \| wc -l
tr Translate/delete characters tr ',' '\n' = comma to newline
$(...) Command substitution Embed command output in a string