Official Go client library for Kubernetes API - typed clients, controllers, and cluster interaction tools
Clientsets provide strongly-typed interfaces for interacting with all built-in Kubernetes API groups and resources. This is the primary way to work with Pods, Deployments, Services, and other standard Kubernetes objects.
k8s.io/client-go/kubernetesk8s.io/client-go/kubernetes/typed/* (110+ packages)k8s.io/client-go/kubernetes/fake (for testing)import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
corev1 "k8s.io/api/core/v1"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
// Create configuration
config, err := rest.InClusterConfig()
// or
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
// Create clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
// Alternative: panic on error
clientset := kubernetes.NewForConfigOrDie(config)type Clientset struct {
*discovery.DiscoveryClient
// Has unexported fields
}
func NewForConfig(c *rest.Config) (*Clientset, error)
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error)
func NewForConfigOrDie(c *rest.Config) *Clientset
func New(c rest.Interface) *ClientsetThe clientset provides access to all Kubernetes API groups through typed methods:
// Core v1 (Pods, Services, ConfigMaps, etc.)
coreClient := clientset.CoreV1()
// Apps v1 (Deployments, StatefulSets, DaemonSets)
appsClient := clientset.AppsV1()
// Batch v1 (Jobs, CronJobs)
batchClient := clientset.BatchV1()
// Networking v1 (Ingresses, NetworkPolicies)
networkingClient := clientset.NetworkingV1()
// RBAC v1 (Roles, RoleBindings, ClusterRoles)
rbacClient := clientset.RbacV1()
// Storage v1 (StorageClasses, VolumeAttachments)
storageClient := clientset.StorageV1()
// Discovery client
discoveryClient := clientset.Discovery()// All API group methods on Clientset
func (c *Clientset) AdmissionregistrationV1() admissionregistrationv1.AdmissionregistrationV1Interface
func (c *Clientset) AdmissionregistrationV1alpha1() admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface
func (c *Clientset) AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface
func (c *Clientset) AppsV1() appsv1.AppsV1Interface
func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface
func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface
func (c *Clientset) AuthenticationV1() authenticationv1.AuthenticationV1Interface
func (c *Clientset) AuthenticationV1alpha1() authenticationv1alpha1.AuthenticationV1alpha1Interface
func (c *Clientset) AuthenticationV1beta1() authenticationv1beta1.AuthenticationV1beta1Interface
func (c *Clientset) AuthorizationV1() authorizationv1.AuthorizationV1Interface
func (c *Clientset) AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface
func (c *Clientset) AutoscalingV1() autoscalingv1.AutoscalingV1Interface
func (c *Clientset) AutoscalingV2() autoscalingv2.AutoscalingV2Interface
func (c *Clientset) AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface
func (c *Clientset) AutoscalingV2beta2() autoscalingv2beta2.AutoscalingV2beta2Interface
func (c *Clientset) BatchV1() batchv1.BatchV1Interface
func (c *Clientset) BatchV1beta1() batchv1beta1.BatchV1beta1Interface
func (c *Clientset) CertificatesV1() certificatesv1.CertificatesV1Interface
func (c *Clientset) CertificatesV1alpha1() certificatesv1alpha1.CertificatesV1alpha1Interface
func (c *Clientset) CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface
func (c *Clientset) CoordinationV1() coordinationv1.CoordinationV1Interface
func (c *Clientset) CoordinationV1alpha2() coordinationv1alpha2.CoordinationV1alpha2Interface
func (c *Clientset) CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta1Interface
func (c *Clientset) CoreV1() corev1.CoreV1Interface
func (c *Clientset) Discovery() discovery.DiscoveryInterface
func (c *Clientset) DiscoveryV1() discoveryv1.DiscoveryV1Interface
func (c *Clientset) DiscoveryV1beta1() discoveryv1beta1.DiscoveryV1beta1Interface
func (c *Clientset) EventsV1() eventsv1.EventsV1Interface
func (c *Clientset) EventsV1beta1() eventsv1beta1.EventsV1beta1Interface
func (c *Clientset) ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface
func (c *Clientset) FlowcontrolV1() flowcontrolv1.FlowcontrolV1Interface
func (c *Clientset) FlowcontrolV1beta1() flowcontrolv1beta1.FlowcontrolV1beta1Interface
func (c *Clientset) FlowcontrolV1beta2() flowcontrolv1beta2.FlowcontrolV1beta2Interface
func (c *Clientset) FlowcontrolV1beta3() flowcontrolv1beta3.FlowcontrolV1beta3Interface
func (c *Clientset) InternalV1alpha1() internalv1alpha1.InternalV1alpha1Interface
func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface
func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface
func (c *Clientset) NodeV1() nodev1.NodeV1Interface
func (c *Clientset) NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface
func (c *Clientset) NodeV1beta1() nodev1beta1.NodeV1beta1Interface
func (c *Clientset) PolicyV1() policyv1.PolicyV1Interface
func (c *Clientset) PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface
func (c *Clientset) RbacV1() rbacv1.RbacV1Interface
func (c *Clientset) RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface
func (c *Clientset) RbacV1beta1() rbacv1beta1.RbacV1beta1Interface
func (c *Clientset) ResourceV1() resourcev1.ResourceV1Interface
func (c *Clientset) ResourceV1alpha3() resourcev1alpha3.ResourceV1alpha3Interface
func (c *Clientset) ResourceV1beta1() resourcev1beta1.ResourceV1beta1Interface
func (c *Clientset) ResourceV1beta2() resourcev1beta2.ResourceV1beta2Interface
func (c *Clientset) SchedulingV1() schedulingv1.SchedulingV1Interface
func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface
func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface
func (c *Clientset) StorageV1() storagev1.StorageV1Interface
func (c *Clientset) StorageV1alpha1() storagev1alpha1.StorageV1alpha1Interface
func (c *Clientset) StorageV1beta1() storagev1beta1.StorageV1beta1Interface
func (c *Clientset) StoragemigrationV1beta1() storagemigrationv1beta1.StoragemigrationV1beta1InterfaceEach resource type has a standard interface with CRUD operations:
type CoreV1Interface interface {
RESTClient() rest.Interface
ComponentStatusesGetter
ConfigMapsGetter
EndpointsGetter
EventsGetter
LimitRangesGetter
NamespacesGetter
NodesGetter
PersistentVolumesGetter
PersistentVolumeClaimsGetter
PodsGetter
PodTemplatesGetter
ReplicationControllersGetter
ResourceQuotasGetter
SecretsGetter
ServicesGetter
ServiceAccountsGetter
}
// Get resource clients
pods := clientset.CoreV1().Pods("namespace")
services := clientset.CoreV1().Services("namespace")
configMaps := clientset.CoreV1().ConfigMaps("namespace")
nodes := clientset.CoreV1().Nodes() // cluster-scoped, no namespacetype PodInterface interface {
Create(ctx context.Context, pod *corev1.Pod, opts metav1.CreateOptions) (*corev1.Pod, error)
Update(ctx context.Context, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error)
UpdateStatus(ctx context.Context, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error)
Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Pod, error)
List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error)
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *corev1.Pod, err error)
Apply(ctx context.Context, pod *applyconfigurationscorev1.PodApplyConfiguration, opts metav1.ApplyOptions) (result *corev1.Pod, err error)
ApplyStatus(ctx context.Context, pod *applyconfigurationscorev1.PodApplyConfiguration, opts metav1.ApplyOptions) (result *corev1.Pod, err error)
UpdateEphemeralContainers(ctx context.Context, podName string, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error)
UpdateResize(ctx context.Context, podName string, pod *corev1.Pod, opts metav1.UpdateOptions) (*corev1.Pod, error)
// Extension methods
Bind(ctx context.Context, binding *v1.Binding, opts metav1.CreateOptions) error
Evict(ctx context.Context, eviction *policyv1beta1.Eviction) error
EvictV1(ctx context.Context, eviction *policyv1.Eviction) error
EvictV1beta1(ctx context.Context, eviction *policyv1beta1.Eviction) error
GetLogs(name string, opts *v1.PodLogOptions) *restclient.Request
ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper
}type ServiceInterface interface {
Create(ctx context.Context, service *corev1.Service, opts metav1.CreateOptions) (*corev1.Service, error)
Update(ctx context.Context, service *corev1.Service, opts metav1.UpdateOptions) (*corev1.Service, error)
UpdateStatus(ctx context.Context, service *corev1.Service, opts metav1.UpdateOptions) (*corev1.Service, error)
Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Service, error)
List(ctx context.Context, opts metav1.ListOptions) (*corev1.ServiceList, error)
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *corev1.Service, err error)
Apply(ctx context.Context, service *applyconfigurationscorev1.ServiceApplyConfiguration, opts metav1.ApplyOptions) (result *corev1.Service, err error)
ApplyStatus(ctx context.Context, service *applyconfigurationscorev1.ServiceApplyConfiguration, opts metav1.ApplyOptions) (result *corev1.Service, err error)
// Extension methods
ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper
}import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "my-pod",
Namespace: "default",
Labels: map[string]string{
"app": "myapp",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "nginx",
Image: "nginx:latest",
Ports: []corev1.ContainerPort{
{ContainerPort: 80},
},
},
},
},
}
result, err := clientset.CoreV1().Pods("default").Create(
context.TODO(),
pod,
metav1.CreateOptions{})pod, err := clientset.CoreV1().Pods("default").Get(
context.TODO(),
"my-pod",
metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
// Pod doesn't exist
} else {
// Other error
}
}// List all pods in namespace
pods, err := clientset.CoreV1().Pods("default").List(
context.TODO(),
metav1.ListOptions{})
// List with label selector
pods, err := clientset.CoreV1().Pods("default").List(
context.TODO(),
metav1.ListOptions{
LabelSelector: "app=myapp",
})
// List with field selector
pods, err := clientset.CoreV1().Pods("default").List(
context.TODO(),
metav1.ListOptions{
FieldSelector: "status.phase=Running",
})
// List with pagination
pods, err := clientset.CoreV1().Pods("default").List(
context.TODO(),
metav1.ListOptions{
Limit: 100,
Continue: continueToken,
})
for _, pod := range pods.Items {
fmt.Printf("Pod: %s\n", pod.Name)
}// Get current version
pod, err := clientset.CoreV1().Pods("default").Get(
context.TODO(), "my-pod", metav1.GetOptions{})
if err != nil {
// Handle error
}
// Modify pod
pod.Spec.Containers[0].Image = "nginx:1.21"
// Update (uses optimistic concurrency via resource version)
updatedPod, err := clientset.CoreV1().Pods("default").Update(
context.TODO(),
pod,
metav1.UpdateOptions{})// Delete single resource
err := clientset.CoreV1().Pods("default").Delete(
context.TODO(),
"my-pod",
metav1.DeleteOptions{})
// Delete with grace period
err := clientset.CoreV1().Pods("default").Delete(
context.TODO(),
"my-pod",
metav1.DeleteOptions{
GracePeriodSeconds: pointer.Int64(30),
})
// Delete collection with label selector
err := clientset.CoreV1().Pods("default").DeleteCollection(
context.TODO(),
metav1.DeleteOptions{},
metav1.ListOptions{
LabelSelector: "app=myapp",
})import "k8s.io/apimachinery/pkg/watch"
watcher, err := clientset.CoreV1().Pods("default").Watch(
context.TODO(),
metav1.ListOptions{
LabelSelector: "app=myapp",
})
if err != nil {
panic(err)
}
defer watcher.Stop()
for event := range watcher.ResultChan() {
pod := event.Object.(*corev1.Pod)
switch event.Type {
case watch.Added:
fmt.Printf("Pod added: %s\n", pod.Name)
case watch.Modified:
fmt.Printf("Pod modified: %s\n", pod.Name)
case watch.Deleted:
fmt.Printf("Pod deleted: %s\n", pod.Name)
case watch.Error:
fmt.Printf("Watch error\n")
}
}import (
"k8s.io/apimachinery/pkg/types"
"encoding/json"
)
// JSON Patch
patchData, err := json.Marshal([]map[string]interface{}{
{
"op": "replace",
"path": "/spec/containers/0/image",
"value": "nginx:1.21",
},
})
pod, err := clientset.CoreV1().Pods("default").Patch(
context.TODO(),
"my-pod",
types.JSONPatchType,
patchData,
metav1.PatchOptions{})
// Merge Patch
mergePatch := map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]string{
"version": "v2",
},
},
}
patchData, _ := json.Marshal(mergePatch)
pod, err := clientset.CoreV1().Pods("default").Patch(
context.TODO(),
"my-pod",
types.MergePatchType,
patchData,
metav1.PatchOptions{})
// Strategic Merge Patch
strategicPatch := map[string]interface{}{
"spec": map[string]interface{}{
"containers": []map[string]interface{}{
{
"name": "nginx",
"image": "nginx:1.21",
},
},
},
}
patchData, _ := json.Marshal(strategicPatch)
pod, err := clientset.CoreV1().Pods("default").Patch(
context.TODO(),
"my-pod",
types.StrategicMergePatchType,
patchData,
metav1.PatchOptions{})Many resources have a separate status subresource:
// Update status
pod, err := clientset.CoreV1().Pods("default").Get(
context.TODO(), "my-pod", metav1.GetOptions{})
pod.Status.Phase = corev1.PodRunning
pod.Status.Conditions = append(pod.Status.Conditions, corev1.PodCondition{
Type: corev1.PodReady,
Status: corev1.ConditionTrue,
})
updatedPod, err := clientset.CoreV1().Pods("default").UpdateStatus(
context.TODO(),
pod,
metav1.UpdateOptions{})import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "my-deployment",
Namespace: "default",
},
Spec: appsv1.DeploymentSpec{
Replicas: pointer.Int32(3),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "myapp",
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "myapp",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "myapp",
Image: "myapp:v1.0.0",
Ports: []corev1.ContainerPort{
{ContainerPort: 8080},
},
},
},
},
},
},
}
result, err := clientset.AppsV1().Deployments("default").Create(
context.TODO(),
deployment,
metav1.CreateOptions{})
// Get deployment
deployment, err := clientset.AppsV1().Deployments("default").Get(
context.TODO(), "my-deployment", metav1.GetOptions{})
// Scale deployment
deployment.Spec.Replicas = pointer.Int32(5)
deployment, err = clientset.AppsV1().Deployments("default").Update(
context.TODO(), deployment, metav1.UpdateOptions{})Some resources support the scale subresource:
import autoscalingv1 "k8s.io/api/autoscaling/v1"
// Get scale
scale, err := clientset.AppsV1().Deployments("default").GetScale(
context.TODO(),
"my-deployment",
metav1.GetOptions{})
// Update scale
scale.Spec.Replicas = 5
scale, err = clientset.AppsV1().Deployments("default").UpdateScale(
context.TODO(),
"my-deployment",
scale,
metav1.UpdateOptions{})
// Also available for ReplicationControllers, ReplicaSets, StatefulSets// Namespace-scoped resources require namespace parameter
pods := clientset.CoreV1().Pods("default")
configMaps := clientset.CoreV1().ConfigMaps("kube-system")
// Cluster-scoped resources don't have namespace
nodes := clientset.CoreV1().Nodes()
namespaces := clientset.CoreV1().Namespaces()
clusterRoles := clientset.RbacV1().ClusterRoles()
persistentVolumes := clientset.CoreV1().PersistentVolumes()import (
"testing"
"k8s.io/client-go/kubernetes/fake"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestMyFunction(t *testing.T) {
// Create fake clientset with initial objects
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "test-pod",
Namespace: "default",
},
}
clientset := fake.NewSimpleClientset(pod)
// Use clientset in tests
pods, err := clientset.CoreV1().Pods("default").List(
context.TODO(), metav1.ListOptions{})
if len(pods.Items) != 1 {
t.Errorf("Expected 1 pod, got %d", len(pods.Items))
}
// Create new pod
newPod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "new-pod",
Namespace: "default",
},
}
_, err = clientset.CoreV1().Pods("default").Create(
context.TODO(), newPod, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
}import apierrors "k8s.io/apimachinery/pkg/api/errors"
pod, err := clientset.CoreV1().Pods("default").Get(
context.TODO(), "my-pod", metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
// Pod doesn't exist
} else if apierrors.IsAlreadyExists(err) {
// Pod already exists (on Create)
} else if apierrors.IsConflict(err) {
// Resource version conflict (on Update)
} else if apierrors.IsForbidden(err) {
// Permission denied
} else if apierrors.IsUnauthorized(err) {
// Not authenticated
} else if apierrors.IsInvalid(err) {
// Validation error
} else if apierrors.IsServerTimeout(err) {
// Server timeout
} else if apierrors.IsTimeout(err) {
// Client timeout
} else if apierrors.IsTooManyRequests(err) {
// Rate limited
} else {
// Other error
}
}
// Get status details
if statusErr, ok := err.(*apierrors.StatusError); ok {
status := statusErr.ErrStatus
fmt.Printf("Code: %d, Reason: %s\n", status.Code, status.Reason)
}Always use context: Pass context.Context to all API calls for proper cancellation handling.
Handle resource versions: Updates use optimistic concurrency control. Get the latest version before updating.
Use label selectors: Filter lists on the server side instead of retrieving everything and filtering client-side.
Implement retry logic: Handle conflicts and transient errors with exponential backoff.
Namespace everything: Always specify namespaces explicitly rather than relying on defaults.
Use typed clients: Prefer typed clients over dynamic clients for better type safety and IDE support.
Check errors comprehensively: Use apierrors package functions to identify specific error conditions.
Respect API conventions: Follow Kubernetes API conventions for labels, annotations, and naming.
Use fake clients for testing: Test controllers and operators with fake clients instead of real clusters.
Understand subresources: Some operations like status updates and scale operations use subresources.
Install with Tessl CLI
npx tessl i tessl/golang-k8s-io--client-go@0.35.0