Clients: kubectl & client-go
Clients are how you interact with Kubernetes. kubectl is the command-line tool most people start with, while client-go is the Go library that powers kubectl and is used by many Kubernetes tools. Understanding both helps you work with Kubernetes effectively, whether you’re running commands manually or building automation.
Think of kubectl like a remote control for Kubernetes—simple buttons (commands) that do complex things. client-go is like the internal wiring that makes the remote control work—more powerful and flexible, but requires more knowledge to use directly.
kubectl: The Kubernetes CLI
kubectl is the official command-line tool for Kubernetes. It’s the primary way most people interact with Kubernetes clusters.
What is kubectl?
kubectl is a command-line interface that translates your commands into API requests to the Kubernetes API server. It handles:
- Authentication and authorization
- Request formatting
- Response parsing and display
- Error handling
- Context and configuration management
Basic kubectl Commands
Getting Resources
# List pods
kubectl get pods
# List all resources
kubectl get all
# Get specific resource
kubectl get pod my-pod
# Get with details
kubectl get pod my-pod -o yaml
# Watch for changes
kubectl get pods --watch
Creating Resources
# Create from file
kubectl create -f pod.yaml
# Create from stdin
kubectl create -f -
# Apply configuration (create or update)
kubectl apply -f deployment.yaml
Updating Resources
# Update from file
kubectl apply -f deployment.yaml
# Edit resource
kubectl edit deployment my-deployment
# Scale deployment
kubectl scale deployment my-deployment --replicas=5
Deleting Resources
# Delete resource
kubectl delete pod my-pod
# Delete from file
kubectl delete -f deployment.yaml
# Delete all resources of type
kubectl delete pods --all
kubectl Configuration
kubectl uses a kubeconfig file (typically ~/.kube/config) that contains:
- Cluster information (API server URLs, certificates)
- User authentication (certificates, tokens)
- Contexts (which cluster and user to use)
- Namespaces (default namespace)
# View current context
kubectl config current-context
# List contexts
kubectl config get-contexts
# Switch context
kubectl config use-context my-context
# Set default namespace
kubectl config set-context --current --namespace=my-namespace
kubectl Output Formats
kubectl supports multiple output formats:
# Table (default)
kubectl get pods
# YAML
kubectl get pod my-pod -o yaml
# JSON
kubectl get pod my-pod -o json
# Wide (more columns)
kubectl get pods -o wide
# Custom columns
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase
kubectl Shortcuts
kubectl supports resource shortcuts:
# Shortcuts
kubectl get po # pods
kubectl get svc # services
kubectl get deploy # deployments
kubectl get rs # replicasets
kubectl get ns # namespaces
kubectl get no # nodes
client-go: The Go Client Library
client-go is the official Go client library for Kubernetes. It’s what kubectl uses under the hood and is the foundation for many Kubernetes tools and operators.
What is client-go?
client-go provides:
- Type-safe Go interfaces for Kubernetes APIs
- Authentication and authorization handling
- Watch and informer patterns for efficient change tracking
- Discovery client for dynamic API access
- Code generation from OpenAPI specifications
Basic client-go Usage
Setting Up a Client
package main
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
// Load kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", "~/.kube/config")
if err != nil {
panic(err)
}
// Create clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
// Use clientset...
}
Listing Pods
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// List pods
pods, err := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err)
}
for _, pod := range pods.Items {
fmt.Printf("Pod: %s\n", pod.Name)
}
Creating a Pod
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "my-pod",
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "nginx",
Image: "nginx:1.21",
},
},
},
}
result, err := clientset.CoreV1().Pods("default").Create(context.TODO(), pod, metav1.CreateOptions{})
if err != nil {
panic(err)
}
Informers and Watches
client-go provides efficient ways to watch for changes:
Watch
watch, err := clientset.CoreV1().Pods("default").Watch(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err)
}
for event := range watch.ResultChan() {
pod := event.Object.(*corev1.Pod)
fmt.Printf("Event: %s, Pod: %s\n", event.Type, pod.Name)
}
Informer (more efficient for multiple watchers)
import (
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
)
factory := informers.NewSharedInformerFactory(clientset, 0)
podInformer := factory.Core().V1().Pods()
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
pod := obj.(*corev1.Pod)
fmt.Printf("Pod added: %s\n", pod.Name)
},
UpdateFunc: func(oldObj, newObj interface{}) {
oldPod := oldObj.(*corev1.Pod)
newPod := newObj.(*corev1.Pod)
fmt.Printf("Pod updated: %s\n", newPod.Name)
},
DeleteFunc: func(obj interface{}) {
pod := obj.(*corev1.Pod)
fmt.Printf("Pod deleted: %s\n", pod.Name)
},
})
stopCh := make(chan struct{})
factory.Start(stopCh)
factory.WaitForCacheSync(stopCh)
// Keep running
<-stopCh
Authentication
Both kubectl and client-go handle authentication:
kubectl Authentication
kubectl reads authentication from kubeconfig:
# ~/.kube/config
users:
- name: my-user
user:
client-certificate: /path/to/cert.crt
client-key: /path/to/key.key
# or
token: my-token
client-go Authentication
client-go supports multiple authentication methods:
// From kubeconfig file
config, _ := clientcmd.BuildConfigFromFlags("", "~/.kube/config")
// In-cluster config (when running in pod)
config, _ := rest.InClusterConfig()
// Custom authentication
config := &rest.Config{
Host: "https://api-server",
BearerToken: "my-token",
TLSClientConfig: rest.TLSClientConfig{
CAFile: "/path/to/ca.crt",
},
}
Common Patterns
Error Handling
pod, err := clientset.CoreV1().Pods("default").Get(context.TODO(), "my-pod", metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
fmt.Println("Pod not found")
} else {
panic(err)
}
}
Label Selectors
// List pods with label selector
pods, err := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{
LabelSelector: "app=my-app",
})
Field Selectors
// List pods on specific node
pods, err := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{
FieldSelector: "spec.nodeName=node-1",
})
When to Use What
Use kubectl When:
- Manual operations and debugging
- Learning Kubernetes
- Quick one-off tasks
- Scripts and automation (bash, etc.)
- Interactive exploration
Use client-go When:
- Building Kubernetes tools or operators
- Complex automation requiring programmatic control
- Need for efficient watch/informer patterns
- Integration with Go applications
- Custom controllers or operators
Other Client Libraries
While kubectl and client-go are the most common, other languages have clients:
- Python -
kuberneteslibrary - Java -
kubernetes-client/java - JavaScript/TypeScript -
@kubernetes/client-node - Rust -
kube-rs - C# -
KubernetesClient
These follow similar patterns to client-go but are language-specific.
Best Practices
kubectl
- Use
applyinstead ofcreatefor idempotency - Use
--dry-run=clientto validate before applying - Use
-o yamlor-o jsonto see full resource definitions - Use contexts to manage multiple clusters
- Use aliases for frequently used commands
client-go
- Use informers instead of watches when possible (more efficient)
- Handle errors appropriately (check for NotFound, etc.)
- Use context for cancellation and timeouts
- Reuse clientsets (they’re thread-safe)
- Use typed clients for type safety
Key Takeaways
- kubectl is the primary CLI tool for Kubernetes
- client-go is the Go library that powers kubectl and many tools
- kubectl translates commands into API requests
- client-go provides type-safe, programmatic access
- Both handle authentication and authorization
- Use kubectl for manual operations, client-go for automation
- Other languages have their own client libraries
See Also
- APIs & Access - Overview of Kubernetes API
- API Groups & Versions - Understanding API structure
- Discovery & OpenAPI - How clients discover APIs
- Getting Started Guide - Practical kubectl usage