Kubernetes - client-go
https://github.com/kubernetes/client-go
Built-in clients like kubectl
and kubelet
are all based on client-go
.
config + http.Client
= RESTClient
vendor/k8s.io/client-go/rest/client.go
vendor/k8s.io/client-go/rest/request.go
ListerWatcher
The ListerWatcher
interface in the client-go
SDK, used in all Go-based Kubernetes controllers, plays a critical role on how these events are generated, propagated and reliably consumed throughout the various Kubernetes components and actors.
type ListerWatcher interface {
Lister
Watcher
}
list and watch
client.Get()
client.Watch()
Cache
client-go cache:
Reflector
watches a specified resource and causes all changes to be reflected in the given store.Store
is the interface of the cache;ExpirationCache
is one of the implementation.
Package cache is a client-side caching mechanism. It is useful for reducing the number of server calls you'd otherwise need to make. Reflector watches a server and updates a Store. Two stores are provided; one that simply caches objects (for example, to allow a scheduler to list currently available nodes), and one that additionally acts as a FIFO queue (for example, to allow a scheduler to process incoming pods).
Clients
http.Client
: Go's built-in HTTP Client.rest.RESTClient
:client-go
provides arest.RESTClient
that wraps ahttp.Client
.kubernetes.Clientset
: a set of typed clients that provides pre-generated local API objects for every core resource type (Pod
s,Deployment
s,Service
s, etc.).dynamic.DynamicClient
:client-go/dynamic
package provides a dynamic client which can perform RESTful operations on arbitrary API resources. Thestruct dynamic.Interface
usesunstructured.Unstructured
to represent all object values from the API server. The dynamic package defers all data bindings until runtime.
import
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/dynamic"
dynamicClient, err := dynamic.NewForConfig(config)
Configuration
- In-Cluster configuration: used when running inside a pod and uses the service account token mounted to the pod
/var/run/secrets/kubernetes.io/serviceaccount/token
.aud
should match API server’s--api-audiences
flag.
- Out-of-Cluster configuration: used when running outside of the cluster and uses either a provided
kubeconfig
file or the current user’s defaultkubeconfig
file.
The controller-runtime
library provides a GetConfig()
that first attempts Out-of-Cluster configuration, and if it fails, attempts In-Cluster configuration.
Code Examples
RESTClientGetter
=> To RESTConfig: rest.Config ("k8s.io/client-go/rest")
=> To DiscoveryClient: discovery.CachedDiscoveryInterface
("k8s.io/client-go/discovery"
)
=> To RESTMapper: meta.RESTMapper
("k8s.io/apimachinery/pkg/api/meta"
)
Retry
import "k8s.io/client-go/util/retry"
retry.RetryOnConflict(retryBackoff, func() error {
//logic
})
Backoff
ctx := context.Background()
secret := &corev1.Secret{}
if err := retry.OnError(wait.Backoff{
Duration: 10 * time.Second,
Steps: 6,
}, func(err error) bool { return true }, func() error {
if err := c.Get(ctx, client.ObjectKey{
Namespace: "kube-system",
Name: "foo-secret",
}, secret); err != nil {
return err
}
return nil
}); err != nil {
return fmt.Errorf("failed to get secret foo-secret: %w", err)
}
Get in cluster rest config
// vendor/k8s.io/client-go/rest/config.go
// creates the in-cluster config
config, err := rest.InClusterConfig()
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
kubeconfig => clientSet
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
bytesArray := []byte(*kubeconfig)
clientConfig ,err:= clientcmd.NewClientConfigFromBytes(bytesArray)
if err!=nil {
logs.Error(err.Error())
return nil
}
config, _ := clientConfig.ClientConfig()
clientset, err := kubernetes.NewForConfig(config)
nodes, err := clientset.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{})
kubeconfig => dynamic client
Dynamic client has no knowledge about the resource you want to consume.
config, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
dynClient, err := dynamic.NewForConfig(config)
if err != nil {
return nil, err
}
secrets => kubeconfig
capiconfig "sigs.k8s.io/cluster-api/util/kubeconfig"
nn := types.NamespacedName{
Name: consts.FooName,
Namespace: consts.FooNamespace,
}
kubeconfig, err := capiconfig.FromSecret(ctx, client, nn)
// kubeconfig []byte
ClientGetter => Client
clientConfig, err := clientGetter.ToRESTConfig()
if err != nil {
return err
}
client, err := client.New(clientConfig, client.Options{})
if err != nil {
return err
}
kubeconfig => restconfig
import (
"k8s.io/client-go/tools/clientcmd"
)
restConfig, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig)
RateLimiter
rateLimiter
is passed from config to client to request.