Skip to content

Instantly share code, notes, and snippets.

@able8
Created November 1, 2023 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save able8/bd8774bb8a297dfc27da5184f330648d to your computer and use it in GitHub Desktop.
Save able8/bd8774bb8a297dfc27da5184f330648d to your computer and use it in GitHub Desktop.
Get Node and Pod Resource Usages using K8s metricsClient
package main
// https://cloud.tencent.com/developer/ask/sof/115441746
import (
"bytes"
"context"
"flag"
"fmt"
"log"
"path/filepath"
"time"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"k8s.io/kubectl/pkg/metricsutil"
metricsapi "k8s.io/metrics/pkg/apis/metrics"
metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1"
metrics "k8s.io/metrics/pkg/client/clientset/versioned"
)
var (
namespaceName = "infra"
podName = "thanos-xxx-7dfbffbd4b-nbvvd"
nodeName = "cn-hongkong.i-j6cjxxxx"
)
func main() {
var kubeconfig *string
if home := homedir.HomeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
// Init Kubernetes REST Client
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err.Error())
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
metricsClient, err := metrics.NewForConfig(config)
if err != nil {
panic(err)
}
for {
podOutput, err := RunTopPod(metricsClient, podName, namespaceName)
if err != nil {
log.Println(err)
}
nodeOutput, err := RunTopNode(clientset, metricsClient, nodeName)
if err != nil {
log.Println(err)
}
fmt.Println(podOutput, nodeOutput)
time.Sleep(3 * time.Second)
}
}
func RunTopPod(metricsClient metrics.Interface, podName string, namespaceName string) (string, error) {
var buf bytes.Buffer
printer := metricsutil.NewTopCmdPrinter(&buf)
m, err := metricsClient.MetricsV1beta1().PodMetricses(namespaceName).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
return "", err
}
versionedMetrics := &metricsv1beta1api.PodMetricsList{}
versionedMetrics.Items = []metricsv1beta1api.PodMetrics{*m}
metrics := &metricsapi.PodMetricsList{}
err = metricsv1beta1api.Convert_v1beta1_PodMetricsList_To_metrics_PodMetricsList(versionedMetrics, metrics, nil)
if err != nil {
return "", err
}
printer.PrintPodMetrics(metrics.Items, false, false, false, "CPU", false)
fmt.Fprintf(&buf, "Collected: %s ago, at %s\n", m.ObjectMeta.CreationTimestamp.Time.Sub(m.Timestamp.Time), m.Timestamp.Time)
return buf.String(), nil
}
func RunTopNode(clientset kubernetes.Interface, metricsClient metrics.Interface, nodeName string) (string, error) {
var buf bytes.Buffer
printer := metricsutil.NewTopCmdPrinter(&buf)
node, err := clientset.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{})
if err != nil {
return "", err
}
availableResources := make(map[string]v1.ResourceList)
availableResources[node.Name] = node.Status.Allocatable
m, err := metricsClient.MetricsV1beta1().NodeMetricses().Get(context.TODO(), nodeName, metav1.GetOptions{})
if err != nil {
return "", err
}
versionedMetrics := &metricsv1beta1api.NodeMetricsList{}
versionedMetrics.Items = []metricsv1beta1api.NodeMetrics{*m}
metrics := &metricsapi.NodeMetricsList{}
err = metricsv1beta1api.Convert_v1beta1_NodeMetricsList_To_metrics_NodeMetricsList(versionedMetrics, metrics, nil)
if err != nil {
return "", err
}
printer.PrintNodeMetrics(metrics.Items, availableResources, false, "CPU")
fmt.Fprintf(&buf, "Collected: %s ago, At %s\n", m.ObjectMeta.CreationTimestamp.Time.Sub(m.Timestamp.Time), m.Timestamp.Time)
return buf.String(), nil
}
@able8
Copy link
Author

able8 commented Nov 3, 2023

K8s Metrics API (Also used by HPA)

Source code from kubectl top node and kubectl top pod, see RunTopPod

Simple example: Get current resource usage of a pod in Kubernetes with Go client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment