티스토리 뷰

IT/GOLANG

Kubernetes development for beginners

트래이닝맨 2021. 2. 12. 00:31
728x90
반응형

Do you have a plan to develop something related to Kubernetes?

 

Then you should read this blog!

 

Last few weeks, I spend some time developing CLI to communicate with OpenShift Cluster. During the time, I researched Kubernetes development basics and I realize that there are several important terms and repos which are very useful.

 

Memorize is limited so I will write the key points here.

  • *rest.Config
  • Typed Client
  • Clientset
  • Unstructured Client
  • Discovery Client
  • RESTMapping
  • Dynamic Client
  • k8s.io/apimachinery

*rest.Config

This is an object based on kubeconfig file that contains cluster information.

 

How to get *rest.Config?

package main

import (
	"context"
	"fmt"
	"time"

	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
}

func main(){
    // creates the in-cluster config
	config, err := rest.InClusterConfig()
	if err != nil {
		panic(err.Error())
	}
	// creates the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
    
    pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
}

 

package main

import (
	"context"
	"flag"
	"fmt"
	"path/filepath"
	"time"

	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
)

func main() {
	var kubeconfig *string
	if home := homedir.HomeDir(); home != "" {
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	flag.Parse()

	// use the current context in kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}

	// create the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	
	pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
  }
  • Outside of cluster 2
import "k8s.io/client-go/tools/clientcmd"
  ...
  kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
  config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)

 

 

Typed Client

This is using Go types defined in k8s.io/api.to represent a kind(Kubernetes object such as pod, route, and so on)

 

Typical example

    clientset, err := kubernetes.NewForConfig(config)

    deployment := &appsv1.Deployment{}
    deployment.Name = "example"
    // edit deployment spec

    client := clientset.AppsV1().Deployments(ns)
    _, err = client.Create(ctx, deployment, metav1.CreateOptions{})

 

Clientset

Clientset contains the clients for groups. Each group has exactly one version included in a Clientset.

In short, it has all clients to do create/read/update/delete for each Go struct object.

type Clientset struct {
	*discovery.DiscoveryClient
	admissionregistrationV1      *admissionregistrationv1.AdmissionregistrationV1Client
	admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client
	internalV1alpha1             *internalv1alpha1.InternalV1alpha1Client
    ...
   }

So if you get a Clientset, you can communicate with Kubernetes

 

 

Unstructured Client

This is using unstructured.Unstructured type(json/yaml) and it will be converted to Go structs. In other words, it will create objects from json/yaml file.

 

Typical example

const dsManifest = `
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: example
      namespace: default
    spec:
      selector:
        matchLabels:
          name: nginx-ds
      template:
        metadata:
          labels:
            name: nginx-ds
        spec:
          containers:
          - name: nginx
            image: nginx:latest
    `

    func main() {
        obj := &unstructured.Unstructured{}

        // decode YAML into unstructured.Unstructured
        dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
        _, gvk, err := dec.Decode([]byte(dsManifest), nil, obj)

        // Get the common metadata, and show GVK
        fmt.Println(obj.GetName(), gvk.String())

        // encode back to JSON
        enc := json.NewEncoder(os.Stdout)
        enc.SetIndent("", "    ")
        enc.Encode(obj)
    }

Discovery Client

DiscoveryClient queries API server about the resources

    dc, err := discovery.NewDiscoveryClientForConfig(cfg)

RESTMapping

This is for finding GVR (available in *meta.RESTMapping)for GVK from api server

 dc, err := discovery.NewDiscoveryClientForConfig(cfg)
    if err != nil {
        return nil, err
    }
    
 mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(dc))

return mapper.RESTMapping(gvk.GroupKind(), gvk.Version)

Dynamic Client

This client is for an unstructured data update.

  _, err = dr.Patch(ctx, obj.GetName(), types.ApplyPatchType, data, metav1.PatchOptions{
        FieldManager: "sample-controller",
    })

 

k8s.io/apimachinery

This is the baseline for all objects.

 

The hierarchy of components 

Client-go (Tool/frameworks)

  Inxexer/Cache/Informer/clientcmd ....

  -> Kuberentes Clientset

    -> RESTClient

      -> k8s.io/api-machinery

 

 

 

Reference

 

반응형

'IT > GOLANG' 카테고리의 다른 글

[Issue] Go Module can not find a package  (0) 2021.02.04
Go를 시작하는 사람들을 위한 Module 이야기  (0) 2021.02.04
댓글
250x250
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함