Resources/limits drill down

Drill down script

This script will show full drill down resources and limits across all namespaces.

kubectl get pods --all-namespaces -o json | jq -r '
  .items[] |
  .metadata.namespace as $ns |
  (if .metadata.ownerReferences then
     (.metadata.ownerReferences[0].kind + "/" + .metadata.ownerReferences[0].name)
   else
     ("Pod/" + .metadata.name)
   end) as $wl |
  .spec.containers[]? |
  {
    ns: $ns,
    wl: $wl,
    req_cpu: (.resources.requests.cpu // "0"),
    req_mem: (.resources.requests.memory // "0"),
    lim_cpu: (.resources.limits.cpu // "0"),
    lim_mem: (.resources.limits.memory // "0")
  } |
  [ .ns, .wl, .req_cpu, .req_mem, .lim_cpu, .lim_mem ] | @tsv
' | awk '
function cpu_to_m(cpu) {
  if (cpu ~ /m$/) { return int(substr(cpu, 1, length(cpu)-1)) }
  return int(cpu * 1000)
}
function mem_to_mi(mem) {
  if (mem ~ /Ki$/) { return int(substr(mem, 1, length(mem)-2)) / 1024 }
  if (mem ~ /Mi$/) { return int(substr(mem, 1, length(mem)-2)) }
  if (mem ~ /Gi$/) { return int(substr(mem, 1, length(mem)-2)) * 1024 }
  if (mem ~ /Ti$/) { return int(substr(mem, 1, length(mem)-2)) * 1024 * 1024 }
  if (mem ~ /^[0-9]+$/) { return int(mem) / 1024 / 1024 }
  return 0
}
{
  ns=$1
  wl=$2
  rc=cpu_to_m($3)
  rm=mem_to_mi($4)
  lc=cpu_to_m($5)
  lm=mem_to_mi($6)

  # Sumy dla całego namespace
  ns_req_cpu[ns] += rc
  ns_req_mem[ns] += rm
  ns_lim_cpu[ns] += lc
  ns_lim_mem[ns] += lm

  # Sumy dla konkretnego workloadu (np. ReplicaSet, StatefulSet) wewnątrz namespace
  wl_req_cpu[ns, wl] += rc
  wl_req_mem[ns, wl] += rm
  wl_lim_cpu[ns, wl] += lc
  wl_lim_mem[ns, wl] += lm
}
END {
  fmt = "%-55s %-12s %-12s %-12s %-12s"

  # Drukowanie nagłówków ze specjalnymi prefiksami do sortowania (!00, !01)
  print sprintf("!00\t00\t" fmt, "NAMESPACE / WORKLOAD", "REQ_CPU(m)", "REQ_MEM(Mi)", "LIM_CPU(m)", "LIM_MEM(Mi)")
  print sprintf("!01\t00\t" fmt, "-------------------------------------------------------", "------------", "------------", "------------", "------------")

  for (ns in ns_req_cpu) {
     # Drukowanie sumy dla przestrzeni nazw (prefiks 00 zapewnia, że będzie na górze grupy)
     print sprintf("%s\t00\t" fmt, ns, "[+] " ns, ns_req_cpu[ns], ns_req_mem[ns], ns_lim_cpu[ns], ns_lim_mem[ns])

     # Szukanie wszystkich sub-obiektów (workloads) należących do tej przestrzeni nazw
     for (key in wl_req_cpu) {
        split(key, arr, SUBSEP)
        if (arr[1] == ns) {
           wl = arr[2]
           wl_disp = "  |- " wl
           # Skracanie nazwy, jeśli jest zbyt długa, żeby nie rozwalić tabelki
           if (length(wl_disp) > 54) { wl_disp = substr(wl_disp, 1, 51) "..." }

           # Drukowanie konkretnego workloadu z wcięciem (prefiks 01 zapewnia sortowanie pod namespace)
           print sprintf("%s\t01_%s\t" fmt, ns, wl, wl_disp, wl_req_cpu[key], wl_req_mem[key], wl_lim_cpu[key], wl_lim_mem[key])
        }
     }
  }
}' | sort -k1,1 -k2,2 | cut -f3-

Namespace-only script

This script will show resources and limits for namespaces only.

kubectl get pods --all-namespaces -o json | jq -r '
  .items[] |
  .metadata.namespace as $ns |
  .spec.containers[]? |
  {
    ns: $ns,
    req_cpu: (.resources.requests.cpu // "0"),
    req_mem: (.resources.requests.memory // "0"),
    lim_cpu: (.resources.limits.cpu // "0"),
    lim_mem: (.resources.limits.memory // "0")
  } |
  [ .ns, .req_cpu, .req_mem, .lim_cpu, .lim_mem ] | @tsv
' | awk '
function cpu_to_m(cpu) {
  if (cpu ~ /m$/) { return int(substr(cpu, 1, length(cpu)-1)) }
  return int(cpu * 1000)
}
function mem_to_mi(mem) {
  if (mem ~ /Ki$/) { return int(substr(mem, 1, length(mem)-2)) / 1024 }
  if (mem ~ /Mi$/) { return int(substr(mem, 1, length(mem)-2)) }
  if (mem ~ /Gi$/) { return int(substr(mem, 1, length(mem)-2)) * 1024 }
  if (mem ~ /Ti$/) { return int(substr(mem, 1, length(mem)-2)) * 1024 * 1024 }
  if (mem ~ /^[0-9]+$/) { return int(mem) / 1024 / 1024 }
  return 0
}
{
  ns=$1
  req_cpu[ns] += cpu_to_m($2)
  req_mem[ns] += mem_to_mi($3)
  lim_cpu[ns] += cpu_to_m($4)
  lim_mem[ns] += mem_to_mi($5)
}
END {
  fmt = "%-30s %-15s %-15s %-15s %-15s"
  print sprintf(fmt, "NAMESPACE", "REQ_CPU(m)", "REQ_MEM(Mi)", "LIM_CPU(m)", "LIM_MEM(Mi)")
  print sprintf(fmt, "------------------------------", "---------------", "---------------", "---------------", "---------------")
  for (n in req_cpu) {
    print sprintf("%-30s %-15d %-15d %-15d %-15d", n, req_cpu[n], req_mem[n], lim_cpu[n], lim_mem[n])
  }
}' | sort