Wednesday, December 18, 2019

Access kubernetes API from GoLang


When implementing a GoLang based kuebernetes service, you will need to access the kubernetes API.
The problem I've encountered in this, is the following:

  • When running the service as part of a kubernetes pod, you need to initialize the kunernetes client using one API: InClusterConfig()
  • When debugging the service (for example using GoLand), you need to to initialize the kunernetes client using a second API: BuildConfigFromFlags()
The solution I've made is to use flags to the application indicating which API to use.
The default flags are for running as part of a kubernetes pod, while enabling changing the default for a debug session.

The service configuration implementation is:

import (
  "encoding/json"
  "github.com/namsral/flag"
  "os"
  "os/exec"
  "path/filepath"
)

type Configuration = struct {
  InCluster                  bool
  KubeConfig                 string
}

var Config Configuration

func InitConfig() {
  defaultKubeConfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")

  flag.BoolVar(&Config.InCluster, "in-cluster", true,
   "run within a kubernetes cluster pod")
  flag.StringVar(&Config.KubeConfig, "kubeconfig", defaultKubeConfig, 
   "absolute path to the kubeconfig file")

  flag.Parse()
}


And the kubernetes client configuration is:

import (
  "k8s.io/client-go/kubernetes"
  appsV1 "k8s.io/client-go/kubernetes/typed/apps/v1"
  coreV1 "k8s.io/client-go/kubernetes/typed/core/v1"
  "k8s.io/client-go/rest"
  "k8s.io/client-go/tools/clientcmd"
)

type K8sClient struct {
  client *kubernetes.Clientset
}

func (client *K8sClient) Init() {
  var config *rest.Config
  var err error
  if Config.InCluster {
    Verbose("getting k8s config in cluster")
    config, err = rest.InClusterConfig()
  } else {
    Verbose("getting k8s config out of cluster, path %v", Config.KubeConfig)
    config, err = clientcmd.BuildConfigFromFlags("", Config.KubeConfig)
  }
  if err != nil {
    log.Fatalf("kubernetes client config failed: %v", err)
  }
  clientSet, err := kubernetes.NewForConfig(config)
  if err != nil {
    log.Fatalf("kubernetes client set failed: %v", err)
  }
  client.client = clientSet
}

That's all!

When running the service in debug mode, send the following argument:
--in-cluster=false

And you're good to go. The service will automatically use the kubernetes configuration from your home folder.

No comments:

Post a Comment