Skip to content

Instantly share code, notes, and snippets.

@able8
Created November 1, 2023 15:01
Show Gist options
  • Select an option

  • Save able8/bd8774bb8a297dfc27da5184f330648d to your computer and use it in GitHub Desktop.

Select an option

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

able8 commented Nov 3, 2023

Copy link
Copy Markdown
Author

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