How to create a kubernetes client using client-go library

A kubernetes client is a http client that can connect to a kubernetes cluster, and do resources creation, deletion etc. Before create a client, we must know the server address and port, cluster’s ca cert, and the client tls key or a service account token file. Usually, these information can be automatically obtained from KUBECONFIG file or pod service account by client-go, so next, I will introduce some common ways to create a kubernetes client:

  • InClusterConfig from k8s.io/client-go/rest
  • DirectClientConfig from k8s.io/client-go/tools/clientcmd
  • DeferredLoadingClientConfig k8s.io/client-go/tools/clientcmd

InClusterConfig

First, let’s use InClusterConfig to get a kubernetes client, this is the simplest way, but requires the process running in a cluster environment, i.e. running in a pod.

package main

import (
	"context"
	"fmt"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	clientConfig, err := rest.InClusterConfig()
	if err != nil {
		panic(err.Error())
	}

	clientSet, err := kubernetes.NewForConfig(clientConfig)
	if err != nil {
		panic(err.Error())
	}

	ns, err := clientSet.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
	fmt.Println(ns, err)
}

The InClusterConfig method depends the follow files or environments:

  • /var/run/secrets/kubernetes.io/serviceaccount/token for reading service account toekn
  • /var/run/secrets/kubernetes.io/serviceaccount/ca.crt for reading cluster root cert
  • KUBERNETES_SERVICE_HOST for getting api server host address
  • KUBERNETES_SERVICE_PORT for getting api server port

DirectClientConfig

This is call direct way, because the config constructor accept a clientcmdapi.Config parameter, this struct defines cluster address auth info, cluster info directly. Actually, there some different variations about the constructor. Some accept a clientcmdapi.Config, and context parameter, overrides info, e.g., NewNonInteractiveClientConfig. In this article we will use the NewClientConfigFromBytes method, it accepts a bytes string representing a kubeconfig file. For other constructor, you can refer to the New* series construct method from k8s.io/client-go/tools/clientcmd/client_config.go file.

package main

import (
	"context"
	"fmt"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

// Replace this content with your kubeconfig file
var configBytes = `
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: XXXXXXXXXXXXXXXXXXXX
    server: https://kubernetes:6443
  name: cluster-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
contexts:
- context:
    cluster: cluster-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
    user: admin-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
  name: context-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
current-context: context-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
kind: Config
preferences: {}
users:
- name: admin-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
  user:
    client-certificate-data: XXXXXXXXXXXXXXXXXXXXX
    client-key-data: XXXXXXXXXXXXXXXXXXXXXXXXXXX
`

func main() {
	cc, err := clientcmd.NewClientConfigFromBytes([]byte(configBytes))
	if err != nil {
		panic(err.Error())
	}

	clientConfig, err := cc.ClientConfig()
	if err != nil {
		panic(err.Error())
	}

	clientSet, err := kubernetes.NewForConfig(clientConfig)
	if err != nil {
		panic(err.Error())
	}

	ns, err := clientSet.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
	fmt.Println(ns, err)
}

DeferredLoadingClientConfig

The last is to use the DeferredLoadingClientConfig way. We can construct a client by NewNonInteractiveDeferredLoadingClientConfig method, it accepts a loading rules and an overrides parameters. NewDefaultClientConfigLoadingRules will get a file list from KUBECONFIG environment variables, if it is not set, then try to use $HOME_DIR/.kube/config file. or, we can specify a file explicitly through ClientConfigLoadingRules.ExplicitPath field, in this case, the loader will only load config file from this explicit path. The ClientConfig() method will try load config from ConfigClientLoader (the first parameter), if error occurs, or got a default config, then try to load config using in cluster config method. in cluster config will use restclient.InClusterConfig, it will find cert and token files from /var/run/secrets/kubernetes.io/serviceaccount dir, and find kubernetes api address through KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT environment.

package main

import (
	"context"
	"fmt"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)


func main() {
	clientConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}).ClientConfig()
	if err != nil {
		panic(err.Error())
	}

	clientSet, err := kubernetes.NewForConfig(clientConfig)
	if err != nil {
		panic(err.Error())
	}

	ns, err := clientSet.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
	fmt.Println(ns, err)
}

Note: client-go version is v0.29.1.

Leave a Reply

Your email address will not be published. Required fields are marked *