Skip to content

Instantly share code, notes, and snippets.

@veyalla
Created September 13, 2024 19:58
Show Gist options
  • Select an option

  • Save veyalla/88da70c5c4fbdfbad10b5907f41aa388 to your computer and use it in GitHub Desktop.

Select an option

Save veyalla/88da70c5c4fbdfbad10b5907f41aa388 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Created by OpenAI o1!
# Default number of top pods to display
TOP_N=10
# Function to display usage information
usage() {
echo "Usage: $0 [-n top_n] [namespace1 namespace2 ...]"
echo " -n top_n Number of top pods to display (default: 10)"
echo "If no namespaces are provided, all namespaces will be included."
exit 1
}
# Parse command-line options
while getopts ":n:" opt; do
case $opt in
n)
if [[ "$OPTARG" =~ ^[0-9]+$ ]]; then
TOP_N="$OPTARG"
else
echo "Error: -n requires a numeric argument."
usage
fi
;;
\?)
echo "Invalid option: -$OPTARG"
usage
;;
:)
echo "Option -$OPTARG requires an argument."
usage
;;
esac
done
shift $((OPTIND -1))
# If no namespaces are provided, use all namespaces
if [ "$#" -eq 0 ]; then
echo "No namespaces provided. Including all namespaces."
read -r -a namespace_list <<< $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}')
else
namespace_list=("$@")
fi
# Arrays to hold pod data and namespace totals
pods_data=()
ns_list=()
ns_pod_counts=()
ns_cpu_totals=()
ns_mem_totals=()
# Loop over all namespaces and collect pod data
for namespace in "${namespace_list[@]}"; do
# Get CPU and Memory usage for all pods in this namespace
pod_usage=$(kubectl top pod -n "$namespace" --no-headers 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$pod_usage" ]; then
continue
fi
# Initialize totals for this namespace
ns_list+=("$namespace")
ns_pod_counts+=(0)
ns_cpu_totals+=(0)
ns_mem_totals+=(0)
ns_index=$((${#ns_list[@]} - 1))
while read -r name cpu mem; do
# Append the pod data with namespace to pods_data
pods_data+=("$name|$cpu|$mem|$namespace")
cpu_val=${cpu%m} # Remove 'm'
mem_val=${mem%Mi} # Remove 'Mi'
# Handle possible units like "Gi" in memory
if [[ $mem == *Gi ]]; then
mem_val_gi=${mem%Gi}
mem_val=$(echo "$mem_val_gi * 1024" | bc)
fi
# Update counts and totals
ns_pod_counts[$ns_index]=$((ns_pod_counts[$ns_index] + 1))
ns_cpu_totals[$ns_index]=$((ns_cpu_totals[$ns_index] + ${cpu_val:-0}))
ns_mem_totals[$ns_index]=$((ns_mem_totals[$ns_index] + ${mem_val:-0}))
done <<< "$pod_usage"
done
# Check if any pod data was collected
if [ ${#pods_data[@]} -eq 0 ]; then
echo "No pod data collected from the specified namespaces."
exit 1
fi
# Determine the maximum width of each column for alignment
max_name_len=8 # Minimum width for "POD NAME"
max_cpu_len=5 # Minimum width for "CPU"
max_mem_len=9 # Minimum width for "MEMORY"
max_ns_len=9 # Minimum width for "NAMESPACE"
# Calculate maximum lengths based on pod data
for entry in "${pods_data[@]}"; do
IFS='|' read -r name cpu mem ns <<< "$entry"
[ ${#name} -gt $max_name_len ] && max_name_len=${#name}
[ ${#cpu} -gt $max_cpu_len ] && max_cpu_len=${#cpu}
[ ${#mem} -gt $max_mem_len ] && max_mem_len=${#mem}
[ ${#ns} -gt $max_ns_len ] && max_ns_len=${#ns}
done
# Add padding
padding=2
max_name_len=$((max_name_len + padding))
max_cpu_len=$((max_cpu_len + padding))
max_mem_len=$((max_mem_len + padding))
max_ns_len=$((max_ns_len + padding))
# Set header names
ns_header="NAMESPACE"
pods_header="Pods"
cpu_header="CPU(m)"
mem_header="Memory(Mi)"
# Collect namespace totals into an array of strings for sorting
ns_totals=()
for i in "${!ns_list[@]}"; do
ns_totals+=("${ns_list[$i]}|${ns_pod_counts[$i]}|${ns_cpu_totals[$i]}|${ns_mem_totals[$i]}")
done
# Sort namespaces by Memory Used in descending order
sorted_ns_totals=($(printf "%s\n" "${ns_totals[@]}" | sort -t"|" -k4 -nr))
# Determine maximum lengths for the Resource Usage per Namespace section
max_ns_name_len=${#ns_header}
max_ns_pods_len=${#pods_header}
max_ns_cpu_len=${#cpu_header}
max_ns_mem_len=${#mem_header}
for entry in "${sorted_ns_totals[@]}"; do
IFS='|' read -r ns pods cpu mem <<< "$entry"
[ ${#ns} -gt $max_ns_name_len ] && max_ns_name_len=${#ns}
[ ${#pods} -gt $max_ns_pods_len ] && max_ns_pods_len=${#pods}
[ ${#cpu} -gt $max_ns_cpu_len ] && max_ns_cpu_len=${#cpu}
[ ${#mem} -gt $max_ns_mem_len ] && max_ns_mem_len=${#mem}
done
# Add padding
max_ns_name_len=$((max_ns_name_len + padding))
max_ns_pods_len=$((max_ns_pods_len + padding))
max_ns_cpu_len=$((max_ns_cpu_len + padding))
max_ns_mem_len=$((max_ns_mem_len + padding))
# Display the list of namespaces included
echo "Namespaces included:"
for ns in "${ns_list[@]}"; do
echo " - $ns"
done
echo
# Display resource usage per namespace, sorted by memory used
echo "Resource Usage per Namespace (sorted by Memory Used):"
printf "%-${max_ns_name_len}s %-${max_ns_pods_len}s %-${max_ns_cpu_len}s %-${max_ns_mem_len}s\n" "$ns_header" "$pods_header" "$cpu_header" "$mem_header"
separator_len=$((max_ns_name_len + max_ns_pods_len + max_ns_cpu_len + max_ns_mem_len + 3))
printf "%0.s-" $(seq 1 $separator_len)
echo
total_cpu=0
total_mem=0
for entry in "${sorted_ns_totals[@]}"; do
IFS='|' read -r ns pods cpu mem <<< "$entry"
printf "%-${max_ns_name_len}s %-${max_ns_pods_len}s %-${max_ns_cpu_len}s %-${max_ns_mem_len}s\n" "$ns" "$pods" "$cpu" "$mem"
total_cpu=$((total_cpu + cpu))
total_mem=$((total_mem + mem))
done
echo
# Function to sort and get top N pods by CPU usage
get_top_cpu_pods() {
printf "%s\n" "${pods_data[@]}" | sort -t"|" -k2 -hr | head -"$TOP_N"
}
# Function to sort and get top N pods by Memory usage
get_top_mem_pods() {
printf "%s\n" "${pods_data[@]}" | sort -t"|" -k3 -hr | head -"$TOP_N"
}
# Get top N CPU and Memory pods
top_cpu_pods=($(get_top_cpu_pods))
top_mem_pods=($(get_top_mem_pods))
# Prepare data for top CPU and Memory pods display
top_cpu_pods_display=("${top_cpu_pods[@]}")
top_mem_pods_display=("${top_mem_pods[@]}")
# Function to print top CPU usage pods
print_top_cpu() {
echo "Top ${TOP_N} CPU Usage Pods in Specified Namespaces:"
printf "%-${max_name_len}s %-${max_cpu_len}s %-${max_mem_len}s %-${max_ns_len}s\n" "POD NAME" "CPU" "MEMORY" "NAMESPACE"
printf "%0.s-" $(seq 1 $((max_name_len + max_cpu_len + max_mem_len + max_ns_len + 3)))
echo
printf "%s\n" "${top_cpu_pods_display[@]}" | awk -F"|" \
-v name_len="$max_name_len" -v cpu_len="$max_cpu_len" -v mem_len="$max_mem_len" -v ns_len="$max_ns_len" \
'{printf "%-*s %-*s %-*s %-*s\n", name_len, $1, cpu_len, $2, mem_len, $3, ns_len, $4}'
}
# Function to print top Memory usage pods
print_top_mem() {
echo "Top ${TOP_N} Memory Usage Pods in Specified Namespaces:"
printf "%-${max_name_len}s %-${max_cpu_len}s %-${max_mem_len}s %-${max_ns_len}s\n" "POD NAME" "CPU" "MEMORY" "NAMESPACE"
printf "%0.s-" $(seq 1 $((max_name_len + max_cpu_len + max_mem_len + max_ns_len + 3)))
echo
printf "%s\n" "${top_mem_pods_display[@]}" | awk -F"|" \
-v name_len="$max_name_len" -v cpu_len="$max_cpu_len" -v mem_len="$max_mem_len" -v ns_len="$max_ns_len" \
'{printf "%-*s %-*s %-*s %-*s\n", name_len, $1, cpu_len, $2, mem_len, $3, ns_len, $4}'
}
# Print top CPU usage pods
print_top_cpu
echo
# Display total CPU and Memory usage
printf "Total CPU Usage : %dm\n" "$total_cpu"
printf "Total Memory Usage: %dMi\n" "$total_mem"
echo
# Print top Memory usage pods
print_top_mem
echo
# Display total CPU and Memory usage again
printf "Total CPU Usage : %dm\n" "$total_cpu"
printf "Total Memory Usage: %dMi\n" "$total_mem"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment