Upgrading Kubernetes client-go from v4 to v5

In a previous post, I showed how to use godep to set up a project with client-go v4. Vladimir Vivien followed up with a great post on doing the same thing usingdep.

In this post, we’ll take another quick look at setting up a project with client-go version 4 using dep, and then we’ll upgrade to client-go v5.

Let’s start from scratch and set up a new project that uses v4. The following simple main.go tries to create a new Namespace named foo-<something>:

Let’s run dep init and see what happens:

So far, so good. Now, let’s see whether our main.go runs:

Ouch! That’s a lot of errors. It turns out that deppulls in the master branch of k8s.io/apimachinery, which is incompatible with client-go v4. Fortunately, there is a branch that will work. Because client-go v4 is based on the code from Kubernetes v1.7, we’ll use the release-1.7 branch for k8s.io/apimachinery. Edit Gopkg.toml and update your constraint for k8s.io/apimachinery so it looks like this:

[[constraint]]
name = "k8s.io/apimachinery"
branch = "release-1.7"

Let’s rerun dep:

Things are looking better! Let’s try to run main.go again:

More errors! If we dig into what’s going on, it turns out that the version of github.com/ugorji/go is newer than what client-go v4 supports. To fix this, we first need to examine client-go’s Godeps.json to see what version of ugorji to use. The commit in question is ded73eae5db7e7a0ef6f55aace87a2873c5d2b74.

Let’s edit Gopkg.toml and fix it. Because our code is not directly importing any ugorji packages, we have to set an override instead of a constraint:

[[override]]
name = “github.com/ugorji/go”
revision = “ded73eae5db7e7a0ef6f55aace87a2873c5d2b74”

Let’s run dep again to get the correct ugorji revision:

And now let’s try running our program again to see if it works:

Woohoo! It worked!

Let’s do some pruning, because dep pulls in a lot of files that our project doesn’t need:

$ dep prune

There is a plan for pruning to be run automatically as part of the ensure process, but for now, we have to invoke it separately. It will also be more powerful and configurable than it is today. In the meantime, we’ll do some additional manual pruning to get rid of Bazel BUILD files, any Travis CI configuration files, and all test files:

$ find vendor \( -name BUILD -o -name .travis.yml -o -name ‘*_test.go’ \) -exec rm {} \;

Upgrading to v5

Now that we have everything working using client-go v4, let’s see what it takes to upgrade to v5.

Let’s start by editing Gopkg.toml and changing the k8s.io/client-go and k8s.io/apimachinery constraints. These are based on Kubernetes v1.8, so we’ll change the k8s.io/apimachinery branch to release-1.8.

[[constraint]]
name = "k8s.io/apimachinery"
branch = "release-1.8"
[[constraint]]
name = "k8s.io/client-go"
version = "5.0.0"

Let’s see how dep feels about this:

The key line is this one:

v5.0.0: Could not introduce k8s.io/client-go@v5.0.0, as its subpackage k8s.io/client-go/pkg/api/v1 is missing. (Package is required by (root).)

Client-go was refactored after v4 was released, and the API types that were previously at k8s.io/client-go/pkg/api/* and k8s.io/client-go/pkg/apis/* are now in k8s.io/api.

If you remember our main.go above, we directly import and use k8s.io/client-go/pkg/api/v1 so we can create a v1.Namespace. That is what is causing this problem.

Thanks to some excellent assistance from dep’s sam boyer, the solution is to tell dep to temporarily ignore the “missing” package when performing its dependency analysis. Edit your Gopkg.toml and add this:

ignored = [
 “k8s.io/client-go/pkg/api/v1”,
]

One more round with dep:

Let’s see if we can run main.go now:

Oops, we forgot to fix the import! Edit main.go and change k8s.io/client-go/pkg/api/v1 to k8s.io/api/core/v1, then run again:

Success!

Notice that dep pulled in k8s.io/api’s master branch. It’s probably a good idea to change to the release-1.8 branch in Gopkg.toml. Also, we can remove the ugorji override, because that package is no longer used by client-go. Finally, we can remove the ignored section, because we’ve successfully upgraded client-go and no longer have any references to the old packages.

You can also run the same pruning steps above to remove unused files.

And there you have it! We started a new project, pulled in client-go v4, and upgraded to v5. Depending on which client-go packages your project uses, you might have to add more packages to the ignored section, and you might have more code changes to make after you upgrade to v5. Hopefully this will help you get started!

You can also find the source code for this post at https://github.com/ncdc/client-go-4-to-5.

Client-go security update!

When I was writing this post, v5.0.0 was the latest version of client-go. v5.0.1 was recently released with a security fix. You’ll want to make sure you have this version. Fortunately, dep makes this easy:

dep ensure -update k8s.io/client-go

And if we rerun dep status, we’ll see that we’ve pulled in the update:

PROJECT          CONSTRAINT  VERSION    REVISION  LATEST   PKGS USED
...
k8s.io/client-go ^5.0.0 v5.0.1 2ae4542 2ae4542 42