Exploring Kubernetes: A Go Library Worth Knowing
If you write Go and work with containers, you’ll eventually encounter Kubernetes. With over 119,000 stars on GitHub, it’s one of the most popular Go projects ever built. But Kubernetes isn’t just something you deploy to. It’s also a powerful library you can program against.
In this post, we’ll explore how Kubernetes is built with Go and how you can use its client library to interact with clusters programmatically.
Why Kubernetes is Written in Go
Kubernetes is a CNCF graduated project. The Cloud Native Computing Foundation has standardized on Go for most of its projects. Why? Go compiles to a single binary. It has excellent concurrency support. It’s easy to deploy.
These traits matter for infrastructure software. Kubernetes runs containers across thousands of nodes. It needs to be fast, reliable, and easy to distribute. Go fits perfectly.
Getting Started with client-go
The client-go library is the official Go client for Kubernetes. It lets you create, read, update, and delete Kubernetes resources from your Go programs.
First, install it:
go get k8s.io/client-go@latest
Here’s how to connect to a cluster and list all pods:
package main
import (
"context"
"fmt"
"log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
// Load kubeconfig from default location
config, err := clientcmd.BuildConfigFromFlags("",
clientcmd.RecommendedHomeFile)
if err != nil {
log.Fatal(err)
}
// Create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err)
}
// List pods in all namespaces
pods, err := clientset.CoreV1().Pods("").List(
context.Background(),
metav1.ListOptions{},
)
if err != nil {
log.Fatal(err)
}
for _, pod := range pods.Items {
fmt.Printf("Pod: %s in namespace %s\n",
pod.Name, pod.Namespace)
}
}
Notice how we pass context to the List call. This is important for handling timeouts and cancellation, especially in production code.
Creating Resources Programmatically
Listing is just the start. You can create entire deployments from Go code:
package main
import (
"context"
"log"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
config, err := clientcmd.BuildConfigFromFlags("",
clientcmd.RecommendedHomeFile)
if err != nil {
log.Fatal(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err)
}
replicas := int32(3)
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "my-app",
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": "my-app"},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": "my-app"},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "app",
Image: "nginx:latest",
},
},
},
},
},
}
_, err = clientset.AppsV1().Deployments("default").Create(
context.Background(),
deployment,
metav1.CreateOptions{},
)
if err != nil {
log.Fatal(err)
}
log.Println("Deployment created!")
}
Watching for Changes
Kubernetes has a powerful watch API. You can react to changes in real-time:
func watchPods(clientset *kubernetes.Clientset) error {
watcher, err := clientset.CoreV1().Pods("default").Watch(
context.Background(),
metav1.ListOptions{},
)
if err != nil {
return err
}
defer watcher.Stop()
for event := range watcher.ResultChan() {
pod, ok := event.Object.(*corev1.Pod)
if !ok {
continue
}
fmt.Printf("Event: %s, Pod: %s\n",
event.Type, pod.Name)
}
return nil
}
This pattern is the foundation of Kubernetes operators. You watch for changes and react accordingly. It’s a good example of Go’s concurrency patterns in action.
Best Practices
When working with client-go, keep these tips in mind:
- Use contexts properly - Set timeouts on long operations
- Handle errors gracefully - Network issues happen
- Use informers for efficiency - They cache resources locally
- Test with a real cluster - Use kind or minikube locally
The Kubernetes ecosystem provides controller-runtime for building operators. It builds on client-go with higher-level abstractions.
Wrapping Up
Kubernetes is more than a deployment target. Its Go libraries let you build powerful automation. Whether you’re creating custom controllers or just scripting cluster operations, client-go is worth learning.
Start small. List some pods. Create a deployment. Then explore operators when you’re ready. The Kubernetes ecosystem runs on Go, and now you can be part of it.