Building the Kubernetes go-client using dep

Building the Kubernetes go-client using dep

Kubernetes is an extensible system with a powerful API. A common problem is to compile the Kubernetes go-client, without errors due to dependencies.

In this post, I will show the steps to resolve dependencies using dep, the new Golang dependency manager developed with the goal of becoming part of the Go toolchain.

http://nirmata.io/

http://nirmata.io/

Managing dependencies has been a active topic for Golang (if you are interested in the details see:The Saga of Go Dependency Management).While dep is still new and changing, as of recently it is considered ready for production use!

A major advantage of dep is that it does not clog up your local GOPATH with dependencies. You can now have a single GOPATH and manage several projects, and their dependencies, in it.  (If you prefer using godep, checkout this great post from Andy Goldstein at Heptio.)

Briefly, the way dep works is that you have manage dependencies using “Gopkg.toml” file and dep uses this file and its dependency analysis to produce a “Gopkg.lock” file. These files are version controlled – it’s optional to check-in the vendor folder. If you want more information on dep, here is an excellent presentation by Carolyn Van Slyck at Rackspace.

dep: https://github.com/golang/dep

Here are the steps to build a project that uses the client-go library:

Step 1: Write code that references client-go

To manage a dependency, dep requires you have code that references the external package. A great reference to writing custom Kubernetes controllers, or other applications that use the Kubernetes API, is this KubeCon talk by Aaron Levy from CoreOS.

Using some of the techniques Aaron covers, here is a simple main.go file that initializes a Kubernetes client and lists all Pods in the cluster:

package main

import (
	"flag"

	"github.com/golang/glog"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

// optional - local kubeconfig for testing
var kubeconfig = flag.String("kubeconfig", "", "Path to a kubeconfig file")

func main() {

	// send logs to stderr so we can use 'kubectl logs'
	flag.Set("logtostderr", "true")
	flag.Set("v", "3")
	flag.Parse()

	config, err := getConfig(*kubeconfig)
	if err != nil {
		glog.Errorf("Failed to load client config: %v", err)
		return
	}

	// build the Kubernetes client
	client, err := kubernetes.NewForConfig(config)
	if err != nil {
		glog.Errorf("Failed to create kubernetes client: %v", err)
		return
	}

	// list pods
	pods, err := client.CoreV1().Pods("").List(metav1.ListOptions{})
	if err != nil {
		glog.Errorf("Failed to retrieve pods: %v", err)
		return
	}

	for _, p := range pods.Items {
		glog.V(3).Infof("Found pods: %s/%s", p.Namespace, p.Name)
	}
}

func getConfig(kubeconfig string) (*rest.Config, error) {
	if kubeconfig != "" {
		return clientcmd.BuildConfigFromFlags("", kubeconfig)
	}

	return rest.InClusterConfig()
}

Step 2: run ‘dep init’

Once you have some code that references client-go, you can run dep to automatically analyse dependencies and generate the vendor artifacts:

dep init -v

This may take a while to complete. The “-v” flag provides details on the dependency analysis.

Step 3: update the client-go version in Gopkg.toml

When dep completes, it will generate a Gopkg.toml file. Update this to the version of client-go you want to use. Currently “v4.0.0-beta.0” is good option:

[[constraint]]
  name = "k8s.io/client-go"
  version = "v4.0.0-beta.0"

Step 4: update the API dependency in Gopkg.toml

Next, we need to make another edit to Gopkg.toml. The Kubernetes client-go depends on the API packages. So, we need to determine the correct revisions to use.

The easiest way to determine this is to check the client-go Git repo. For example, since I selected the “v4.0.0-beta.0” version I can browse to:

https://github.com/kubernetes/client-go/tree/v4.0.0-beta.0

Then select Godeps and view the Godeps.json file. In there , searching for “apimachinery” reveals the revision used to compile the “v4.0.0-beta.0” version of client-go:

{
    "ImportPath": "k8s.io/apimachinery/pkg/api/errors",
    "Rev": "abe34e4f5b4413c282a83011892cbeea5b32223b"
},

Copy this revision and add it to the Gopkg.toml file as an override. The final Gopkg.toml should look like this:

# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
#   name = "github.com/user/project"
#   version = "1.0.0"
#
# [[constraint]]
#   name = "github.com/user/project2"
#   branch = "dev"
#   source = "github.com/myfork/project2"
#
# [[override]]
#  name = "github.com/x/y"
#  version = "2.4.0"


[[constraint]]
  branch = "master"
  name = "github.com/golang/glog"

[[constraint]]
  name = "k8s.io/client-go"
  version = "v4.0.0-beta.0"
  
[[override]]
  name = "k8s.io/apimachinery"
  revision = "abe34e4f5b4413c282a83011892cbeea5b32223b"

Step 5: run ‘dep ensure’ 

Finally, run ‘dep ensure’ to re-generate the Gopkg.lock file and update the vendor folder:

dep ensure -v

One this completes, you can build your code as you normally would:

go build -v

Summary

Kubernetes is a fast moving project, and can seem daunting at first. It took me a few attempts, and lots of web searches, to figure out how to reliably compile and build applications the use the client-go package. I hope this post helps some of you avoid that pain, and get started with building Kubernetes solutions more easily.

 

Getting up to Speed With Kubernetes 1.9
Service Availability for Container-Native Applications
No Comments

Sorry, the comment form is closed at this time.