CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/golang-k8s-io--client-go

Official Go client library for Kubernetes API - typed clients, controllers, and cluster interaction tools

Overview
Eval results
Files

clientsets.mddocs/reference/

Clientsets - Typed Kubernetes Clients

Back to Index

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.

Package Information

  • Main Package: k8s.io/client-go/kubernetes
  • Typed Clients: k8s.io/client-go/kubernetes/typed/* (110+ packages)
  • Fake Clients: k8s.io/client-go/kubernetes/fake (for testing)

Core Imports

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"
)

Creating a Clientset

From rest.Config

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)

Clientset Structure

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) *Clientset

API Groups

The 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()

Available API Groups

// 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.StoragemigrationV1beta1Interface

Resource Interfaces

Each resource type has a standard interface with CRUD operations:

Core v1 Resources

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 namespace

Pod Interface

type 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
}

Service Interface

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
}

Common Operations

Create

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{})

Get

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

// 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)
}

Update

// 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

// 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",
    })

Watch

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")
    }
}

Patch

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{})

Status Subresource

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{})

Deployment Example (Apps v1)

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{})

Scale Subresource

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 vs Cluster-Scoped

// 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()

Testing with Fake Clients

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)
    }
}

Error Handling

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)
}

Best Practices

  1. Always use context: Pass context.Context to all API calls for proper cancellation handling.

  2. Handle resource versions: Updates use optimistic concurrency control. Get the latest version before updating.

  3. Use label selectors: Filter lists on the server side instead of retrieving everything and filtering client-side.

  4. Implement retry logic: Handle conflicts and transient errors with exponential backoff.

  5. Namespace everything: Always specify namespaces explicitly rather than relying on defaults.

  6. Use typed clients: Prefer typed clients over dynamic clients for better type safety and IDE support.

  7. Check errors comprehensively: Use apierrors package functions to identify specific error conditions.

  8. Respect API conventions: Follow Kubernetes API conventions for labels, annotations, and naming.

  9. Use fake clients for testing: Test controllers and operators with fake clients instead of real clusters.

  10. Understand subresources: Some operations like status updates and scale operations use subresources.

Related Documentation

Back to Index

Install with Tessl CLI

npx tessl i tessl/golang-k8s-io--client-go

docs

index.md

tile.json