Let’s prepare for GKE cluster versions >= 1.19

Sidath Weerasinghe
3 min readAug 7, 2022

Google cloud has taken two significant changes in the GKE cluster version from 1.18 to 1.19 that we need to pay more attention to.

1. Google Kubernetes Engine doesn’t support the basic authentication for accessing the Kubernetes APIs.

2. Kubernetes controller manager image change from Debian to distroless.

Considering the above changes, here we are talking about the 1st change because that is the change most of the applications used for building the application coordination in the Kubernetes environment.

First, you have to identify your application components that use the Kubernetes APIs. Most of the applications which built early stage of the Kubernetes versions probably that application used the basic authentication for calling the Kubernetes APIs.

“Basic Authentication means that you have to enter the username and password when making the API request to get authenticated.”

Below API call can get all the endpoint details from your Kubernetes cluster using the basic authentication.

curl -u username:password https://<cluster_endpoint>/api/v1/namespaces/default/endpoints

After upgrading your cluster to the GKE version 1.19 or above, this API call wasn’t work because upgraded GKE versions do not support basic authentication. You can get the below error for the above API call,

{
"kind":"Status",
"apiVersion":"v1",
"metadata":{
},
"status":"Failure",
"message":"endpoints is forbidden: User \"system:anonymous\" cannot list resource \"endpoints\" in API group \"\" in the namespace \"default\"",
"reason":"Forbidden",
"details":{
"kind":"endpoints"
},
"code":403

The solution is to use the Token-based authentication instead of the basic authentication. You have to follow the below steps to generate the token.

Step 01

You have to create the service account for your namespace in the Kubernetes cluster.

Service account name = my-service-account

Namespace = my-namespace

kubectl create serviceaccount my-service-account -n my-namespace

You can verify by list downing the service account,

kubectl get sa -n my-namespace

Step 2

You have to create the cluster role by allowing the allowed accesses.

Create the cluster-role.yaml file using the below content.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: my-cluster-role
namespace: my-namespace
rules:
- apiGroups:
- ""
- apps
- autoscaling
- batch
- extensions
- policy
- rbac.authorization.k8s.io
resources:
- pods
- componentstatuses
- configmaps
- daemonsets
- deployments
- events
- endpoints
- horizontalpodautoscalers
- ingress
- jobs
- limitranges
- namespaces
- nodes
- pods
- persistentvolumes
- persistentvolumeclaims
- resourcequotas
- replicasets
- replicationcontrollers
- serviceaccounts
- services
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

You can apply the changes by executing the below command,

kubectl apply -f cluster-role.yaml

my-cluster-role has full access to all Kubernetes cluster resources. In your scenarios, you can choose the access level and the resource that your cluster role should access. Based on that, you can adjust the able yaml file.

Step 3

We have to map our service account and the cluster role by creating the CluserRole Binding.

Create the cluster-binding.yaml file using the below content.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-cluster-role-binding
subjects:
- namespace: my-namespace
kind: ServiceAccount
name: my-service-account
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: my-cluster-role

You can apply the changes by executing the below command,

kubectl apply -f cluster-binding.yaml

Step 4

Getting the token which is created for the service account.

kubectl get sa -n my-namespacekubectl describe sa my-service-account -n my-namespace

Get token name from the above command results.

kubectl get secrets -n my-namespace

Get the correct token similar to the token name that is returned from the description of the service account.

kubectl describe secrets <token_name> -n my-namespace

Now, let’s call the API call again with the token –

curl https://<cluster_endpoint>/api/v1/namespaces/default/endpoints -H “Authorization: Bearer <token>”

You can get the correct results, and the curl is authenticated through the bearer token.

Try to migrate your GKE version to the new GKE version. Don’t wait until GCP does the force upgrades.

--

--