Blog

Kubernetes GKE Workload Identity

1 1f14dqe9np6kalf53ha4kq

Often you want to configure your Kubernetes services to use a specific Google service account (much like kube2iam project).

1 9i9730xcxt2drqhbkrszcw

You can accomplish that by configuring a Kubernetes service account to act as a Google service account, which means that any Pod running the:

ServiceAccountName: <kubernetes_service_account>

will be authenticating to gcloud services using the Goole service account.

Note: this is a beta product, it might change in the future.

Overview:

Workload identity is the recommended way to access gcloud services from GKE, Once you configure the relationship between a Kubernetes service account and a Google service account, any workload running as the Kubernetes service account automatically authenticates as the Google service account when accessing Google Cloud APIs.

Cross-cluster identity:
It is important to understand that since IAM is global per project, the identity namespace will be shared across all clusters in the same project, and it's recommended to separate clusters into projects.

for example:
The following command grants the same access to any cluster in the project, that uses the default service account and Namespace, and have Workload Identity enabled on the cluster:

gcloud iam service-accounts add-iam-policy-binding \
 — role roles/iam.workloadIdentityUser \
 — member "serviceAccount:[PROJECT_ID].svc.id.goog[default/default]"
 [GOOGLE_SERVICE_ACCOUNT_NAME]@[PROJECT_ID].iam.gserviceaccount.com

Limitations:

  • Workload Identity is available for clusters running GKE version 1.12 and higher.
  • When Workload Identity is enabled, you can no longer use the Compute Engine default service account.
  • Workload Identity can’t be used with Pods running in the host network.
  • Istio namespace injection is not going to work with workload identity, as it changes the Metadata server to be GCE rather than GKE and will result in GCE compute service account.

Enable Workload Identity on a new cluster:

  1. Ensure that you have enabled the IAM Credentials API
  2. set the project id and the cluster name
export PROJECT_ID=<project_ID>
export CLUSTER_NAME=<cluster_name>
export CLUSTER_VERSION=<cluster_version>

3. You can either create a new cluster with the workload identity

gcloud beta container clusters create ${CLUSTER_NAME} \
  --cluster-version=${CLUSTER_VERSION} \

--identity-namespace=${PROJECT_ID}.svc.id.goog

or update an existing cluster:

gcloud beta container clusters update ${CLUSTER_NAME} \
  --identity-namespace=${PROJECT_ID}.svc.id.goog

Enable the Metadata Server

The Metadata Server runs on each GKE node and changes the behavior of the metadata endpoint. This also secures the metadata endpoint removing the need for metadata concealment. Let’s enable Metadata Server on our default node pool.

gcloud beta container node-pools update default-pool \
 — cluster=workload-identity-test \
 — workload-metadata-from-node=GKE_METADATA_SERVER \
 — zone=us-central1-b

4. configure kubectl for the cluster
gcloud container clusters get-credentials ${CLUSTER_NAME}

5. Like most other resources, Kubernetes service accounts live in a Namespace. Create the Namespace to use for the Kubernetes service account

kubectl create namespace <namespace>

6. set Kubernetes service account name, namespace and google service account name

export K8S_NAMESPACE=<kubernetes_service_account_namespace>
export KSA_NAME=<kubernetes_service_account>
export GSA_NAME=<google_service_account>

7. Create the Kubernetes service account

kubectl create serviceaccount \
 --namespace ${K8S_NAMESPACE} ${KSA_NAME}

8. Create the google service account

gcloud iam service-accounts create ${GSA_NAME}

9. Create the binding between the Kubernetes service account and the google service account

gcloud iam service-accounts add-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:${PROJECT_ID}.svc.id.goog[${K8S_NAMESPACE}/${KSA_NAME}]" \
  ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

10. Add the iam.gke.io/gcp-service-account=[GSA_NAME]@[PROJECT_ID] annotation to the Kubernetes service account, using the email address of the Google service account:

kubectl annotate serviceaccount \
  --namespace ${K8S_NAMESPACE} \
  ${KSA_NAME} \
  iam.gke.io/gcp-service-account=${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

11. run a test pod

kubectl run -it \
  --generator=run-pod/v1 \
  --image google/cloud-sdk \
  --serviceaccount ${KSA_NAME} \
  --namespace ${K8S_NAMESPACE} \
  workload-identity-test

12. test that the service account is the correct one

gcloud auth list

Revoking access:

keep in mind that revoking access is not an immediate operation and cached tokens may take up to 30 minutes to expire.

to revoke the access you simply need to remove the binding:

gcloud iam service-accounts remove-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:${PROJECT_ID}.svc.id.goog[${K8S_NAMESPACE}/${KSA_NAME}]" \
  ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

Applying the service account to a pod in YAML file or a Helm chart:

you should use the stanza serviceAccountName with the Kubernetes service account you have used in the binding for a run with the Google service account.

Subscribe to updates, news and more.

Related blogs