Kubernetes Engine master|node versions

A Rube Goldberg solution

Daz Wilkin
Google Cloud - Community

--

Update 18–04–25: Some Golang and some Python added at the end.

I’m pernickety and, when I’m creating Kubernetes Engine clusters, I live on the edge and use the last|greatest master and node versions. Kubernetes Engine defaults to a ‘server-specified’ (defaultClusterVersion) version that’s usually not the latest.

However, when creating the cluster, I’ve been eyeballing the version to provide as the cluster-version value because, until recently, I was unaware how to programmatically enumerate the possibilities:

gcloud container get-server-config \
--region=$REGION \
--project=$PROJECT \
--format="json"
Fetching server config for us-west1
{
"defaultClusterVersion": "1.8.8-gke.0",
"defaultImageType": "COS",
"validImageTypes": [
"COS",
"UBUNTU"
],
"validMasterVersions": [
"1.9.6-gke.1",
"1.9.6-gke.0",
"1.9.3-gke.0",
"1.8.10-gke.0",
"1.8.8-gke.0"
],
"validNodeVersions": [
"1.9.6-gke.1",
"1.9.6-gke.0",
"1.9.3-gke.0",
"1.9.2-gke.1",
"1.8.10-gke.0",
"1.8.8-gke.0",
"1.8.7-gke.1"
]
}

NB I assume (!) the master and node version are synchronized. And, as of today, the lastest-greatest version would be “1.9.6-gke.1”

So, how would I grab that value?

One assumption is that the latest version is *always* the zero-th element of these lists:

gcloud container get-server-config \
--region=$REGION \
--project=$PROJECT \
--format="value(validMasterVersions[0])"
Fetching server config for us-west1
1.9.6-gke.1

But, where’s the fun in that ;-)

jq to the rescue…

Explanation

We’re running the same gcloud container get-server-config command as before. This time, we’re formatting the output as JSON and piping it into jq.

In an attempt to make it slightly clearer, two functions are defined to_gke_semver (lines 7+8) and from_gke_semver(lines 9+10). From the command’s output up above, you’ll see that it produces strings of the form 1.9.6-gke.1. This is like an extended semver. We want to be able to sort this type of string. So, to_gke_semver converts that string into JSON{“major”:”1", “minor”:”9", “patch”:”6", “gke”:”1"} which we’ll then use as the basis of our sort. The function from_gke_semver converts the JSON back to the string.

We use jq’s reduce function (line 11), this take an array as input, an accumulator and applies some function each array item in turn generally applying the results to the accumulator. In our case, the accumulator is initially the lowest-valued GKE semver {“major”:”0", “minor”:”0"….}(lines 14–19). And, our function compares validMasterVersion that have been converted into JSON semver objects (line 12) to the accumulator, replacing the accumulator with the item if it’s larger.

A larger value has a greater major value. For two semvers with the same major value, the greater has the larger minor value etc. etc.

Finally, we have the largest validMasterVerson as a JSON object and convert it back to a string (line 36). And this becomes the value of ${LATEST}.

Copy-and-paste the above script snippet to your shell. If like me, today, you’ll get:

echo ${LATEST}
1.9.6-gke.1

You could then:

gcloud beta container clusters create $CLUSTER \
--username="" \
--cluster-version=${LATEST} \
--machine-type=custom-1-4096 \
--image-type=COS \
--num-nodes=1 \
--enable-autorepair \
--enable-autoscaling \
--enable-autoupgrade \
--enable-cloud-logging \
--enable-cloud-monitoring \
--min-nodes=1 \
--max-nodes=2 \
--region=$REGION \
--project=$PROJECT \
--preemptible \
--scopes="https://www.googleapis.com/auth/cloud-platform"

Conclusion

Yes, it appears overly complex but is there a better way to determine this value?

Python

Thanks to Sean for thinking outside of my mental box and providing a Python alternative:

Then, as with jq:

LATEST=$(\
gcloud container get-server-config \
--region=$REGION \
--project=$PROJECT \
--format="json" \
| python3 python.py) \
&& echo ${LATEST}

Golang

Then, as with jq:

LATEST=$(\
gcloud container get-server-config \
--region=$REGION \
--project=$PROJECT \
--format="json" \
| go run main.go) \
&& echo ${LATEST}

or go build it.

--

--