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.