You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
Currently, there is a lack of a simple and concise visualization for summarizing the overall resource usage (e.g., CPU, memory, pods) in the Kubernetes cluster. While K9s provides detailed metrics and pod-specific information, it does not offer a high-level overview of the cluster’s resource health and usage in a visually intuitive way. This makes it harder to quickly assess cluster health and manage resources efficiently.
Describe the solution you'd like
A feature that provides a dashboard-like summary for key resource usage metrics:
CPU: Allocatable vs. Reserved vs. Used.
Memory: Allocatable vs. Reserved vs. Used.
Pods: Total allocatable pods vs. currently used pods.
Node List: A list of nodes that are currently in use, highlighting roles (e.g., master, worker). ( Maybe Node list not neccessary, we can remove it.)
Optionally, the user should be able to include or exclude master nodes in the calculations.
Describe alternatives you've considered
package main
import (
"context"
"flag"
"fmt"
"log"
"strings"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/metrics/pkg/client/clientset/versioned"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func main() {
// Define command-line flags
var setContext string
var includeMasters bool
flag.StringVar(&setContext, "setContext", "minikube", "Set the desired context name")
flag.BoolVar(&includeMasters, "includeMasters", false, "Set to true to include master nodes, false to exclude them")
flag.Parse()
// Load kubeconfig with the specified context
configOverrides := &clientcmd.ConfigOverrides{CurrentContext: setContext}
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
config, err := kubeConfig.ClientConfig()
if err != nil {
log.Fatal(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err)
}
metricsClientset, err := versioned.NewForConfig(config)
if err != nil {
log.Fatal(err)
}
nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.Fatal(err)
}
var totalAllocatableCPU, totalUsedCPU, totalAllocatableMemory, totalUsedMemory, totalPods, usedPods int64
var nodeNames []string // Slice to store node names
for _, node := range nodes.Items {
isMaster := false
if _, ok := node.Labels["node-role.kubernetes.io/master"]; ok {
isMaster = true
}
if includeMasters || !isMaster {
nodeNames = append(nodeNames, node.Name) // Add node name to the slice
allocatable := node.Status.Allocatable
if cpuQuantity, ok := allocatable["cpu"]; ok {
totalAllocatableCPU += cpuQuantity.MilliValue()
}
if memoryQuantity, ok := allocatable["memory"]; ok {
totalAllocatableMemory += memoryQuantity.Value()
}
if podsQuantity, ok := allocatable["pods"]; ok {
totalPods += podsQuantity.Value()
}
}
}
nodeMetrics, err := metricsClientset.MetricsV1beta1().NodeMetricses().List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.Fatal(err)
}
for _, nodeMetric := range nodeMetrics.Items {
isMaster := false
if _, ok := nodeMetric.Labels["node-role.kubernetes.io/master"]; ok {
isMaster = true
}
if includeMasters || !isMaster {
usage := nodeMetric.Usage
if cpuUsage, ok := usage["cpu"]; ok {
totalUsedCPU += cpuUsage.MilliValue()
}
if memoryUsage, ok := usage["memory"]; ok {
totalUsedMemory += memoryUsage.Value()
}
}
}
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.Fatal(err)
}
usedPods = int64(len(pods.Items))
totalReservedCPU, totalReservedMemory := calculatePodRequests(clientset)
fmt.Printf("Pods\n")
printResourceBar(float64(usedPods), float64(totalPods), "Used", "pods")
fmt.Printf("\nCPU\n")
printResourceBar(float64(totalReservedCPU)/1000, float64(totalAllocatableCPU)/1000, "Reserved", "cores")
printResourceBar(float64(totalUsedCPU)/1000, float64(totalAllocatableCPU)/1000, "Used", "cores")
fmt.Printf("\nMemory\n")
printResourceBar(float64(totalReservedMemory)/1024/1024/1024, float64(totalAllocatableMemory)/1024/1024/1024, "Reserved", "GiB")
printResourceBar(float64(totalUsedMemory)/1024/1024/1024, float64(totalAllocatableMemory)/1024/1024/1024, "Used", "GiB")
// Aesthetic node name display
fmt.Printf("\n✨ Used Nodes: %d ✨\n", len(nodeNames))
fmt.Println("⚡ Here are the nodes:")
for _, name := range nodeNames {
fmt.Printf(" 🚀 %s\n", name)
}
}
func calculatePodRequests(clientset *kubernetes.Clientset) (int64, int64) {
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.Fatal(err)
}
var totalReservedCPU, totalReservedMemory int64
for _, pod := range pods.Items {
for _, container := range pod.Spec.Containers {
resources := container.Resources
if cpuQuantity, ok := resources.Requests["cpu"]; ok {
totalReservedCPU += cpuQuantity.MilliValue()
}
if memoryQuantity, ok := resources.Requests["memory"]; ok {
totalReservedMemory += memoryQuantity.Value()
}
}
}
return totalReservedCPU, totalReservedMemory
}
func printResourceBar(used, total float64, label string, unit string) {
percentage := (used / total) * 100
barLength := 30
usedBars := int(percentage * float64(barLength) / 100)
bar := strings.Repeat("\033[33m█\033[0m", usedBars) + strings.Repeat("\033[37m░\033[0m", barLength-usedBars)
// Check if unit is memory and convert to TiB if necessary
if unit == "GiB" || unit == "TiB" {
if total > 1024 {
used = used / 1024
total = total / 1024
unit = "TiB"
} else {
unit = "GiB"
}
}
// Align numbers and percentages
if label == "Used" && unit == "pods" {
fmt.Printf("%-8s: %8d %s / %8d %s [%s] %6.2f%%\n", label, int(used), unit, int(total), unit, bar, percentage)
} else {
fmt.Printf("%-8s: %8.2f %s / %8.2f %s [%s] %6.2f%%\n", label, used, unit, total, unit, bar, percentage)
}
}
Additional context
Rancher interface has this feature, what I want is to add this feature to k9s interface. Maybe it can appear when we type :capacity or it can appear on the top right of the main screen, I don't know. This is completely open to interpretation. (example screenshot)
This is the output of the code I shared in cli. I want to integrate this into k9s but I found it very complicated and I couldn't find any contributing guide. I would appreciate it if someone who is familiar with the source code can help me integrate it.
The text was updated successfully, but these errors were encountered:
If you want to add those dashboards for pods, a good starting point is this function. That function adds all the functions you see in the top right pod view
If you think your dashboards make more sense for other resources as well (e.g the CPU & Memory can be shown also for nodes), you can have a look at the Browser struct to see how more general commands are added. An example is here where the yaml function makes sense for all resources. You can use Browser.viewCmd as an example on how to create a a live view and render your dashboards.
I couldn't find any contributing guide: there isn't one. I suggest to clone the repo, insert breakpoints into some places and run the app inside an IDE to check what happens when. This is what I did to have an understanding.
Yes I know this interface and I have tried it, but I think it only shows the currently used values.
I want to see two different interfaces as "Used & Reserved".
Currently, the interface displays the used CPU and Memory for resources, which is very helpful for real-time monitoring. However, as a user, I often find myself needing to see the requested CPU and Memory values as well.
Is your feature request related to a problem? Please describe.
Currently, there is a lack of a simple and concise visualization for summarizing the overall resource usage (e.g., CPU, memory, pods) in the Kubernetes cluster. While K9s provides detailed metrics and pod-specific information, it does not offer a high-level overview of the cluster’s resource health and usage in a visually intuitive way. This makes it harder to quickly assess cluster health and manage resources efficiently.
Describe the solution you'd like
A feature that provides a dashboard-like summary for key resource usage metrics:
CPU: Allocatable vs. Reserved vs. Used.
Memory: Allocatable vs. Reserved vs. Used.
Pods: Total allocatable pods vs. currently used pods.
Node List: A list of nodes that are currently in use, highlighting roles (e.g., master, worker). ( Maybe Node list not neccessary, we can remove it.)
Optionally, the user should be able to include or exclude master nodes in the calculations.
Describe alternatives you've considered
Additional context
Rancher interface has this feature, what I want is to add this feature to k9s interface. Maybe it can appear when we type :capacity or it can appear on the top right of the main screen, I don't know. This is completely open to interpretation. (example screenshot)
This is the output of the code I shared in cli. I want to integrate this into k9s but I found it very complicated and I couldn't find any contributing guide. I would appreciate it if someone who is familiar with the source code can help me integrate it.
The text was updated successfully, but these errors were encountered: