An alternative to client-go, optimized for binary size, memory consumption and speed
While building the kubetail CLI tool, we noticed that final binary sizes for tools in the K8s ecosystem (e.g. kubectl, helm) were disproportionately large compared to other unix utilities. We traced the root cause to the Kubernetes client-go library, which typically adds 20MB+ to final binaries (see our size-matters report). Separately, we have also found that client-go informers consume significant amounts of memory at runtime. This library addresses both issues with a design optimized for binary size, memory consumption, and speed.
| Client | Binary Size¹ |
|---|---|
client-go.Clientset |
25.9 MB |
client-go.DynamicClient |
10.6 MB |
kubeslim |
9.7 MB |
¹ Measured using a minimal Go executable performing a simple API call (see size-matters for methodology)
This library is experimental and is not recommended for production (yet)!
go get github.com/kubetail-org/kubeslimimport (
"context"
"fmt"
"log"
"path/filepath"
"github.com/kubetail-org/kubeslim"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
)
type namespaceList struct {
Items []struct {
Metadata struct {
Name string `json:"name"`
} `json:"metadata"`
} `json:"items"`
}
type podList struct {
Items []struct {
Metadata struct {
Name string `json:"name"`
} `json:"metadata"`
} `json:"items"`
}
func main() {
kubeconfig := filepath.Join(homedir.HomeDir(), ".kube", "config")
// Load configuration from kubeconfig file
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
log.Fatalf("failed to load kubeconfig: %v", err)
}
// Create the kubeslim client
client, err := kubeslim.NewForConfig(config)
if err != nil {
log.Fatalf("failed to create kubeslim client: %v", err)
}
// Get namespaces
namespaceGVR := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"}
namespaces, err := kubeslim.List[namespaceList](context.TODO(), client, namespaceGVR)
if err != nil {
log.Fatalf("failed to list namespaces: %v", err)
}
if len(namespaces.Items) == 0 {
fmt.Println("No namespaces found.")
return
}
for _, ns := range namespaces.Items {
fmt.Println(ns.Metadata.Name)
}
// Get pods
podGVR := schema.GroupVersionResource{Group: "core", Version: "v1", Resource: "pods"}
pods, err := kubeslim.List[podList](context.TODO(), client, podGVR)
if err != nil {
log.Fatalf("failed to list pods: %v", err)
}
if len(pods.Items) == 0 {
fmt.Println("No pods found.")
return
}
for _, pod := range pods.Items {
fmt.Println(pod.Metadata.Name)
}
}This library is very much a work in progress! If you have ideas on how to improve it or if you'd like help using it you can:
- Create a GitHub Issue
- Send us an email (hello@kubetail.com)
- Join our Discord server or Slack channel