Workload Identity in GKE with Terraform
Introduction
Workload Identity is a powerful feature provided by Google Kubernetes Engine (GKE) that simplifies securely accessing Google Cloud resources from applications running within GKE clusters. By leveraging Google Cloud’s IAM and Kubernetes Service Accounts, Workload Identity eliminates the need for long-lived static service account keys, making your environment more secure and easier to manage.
This blog post will explore how to set up Workload Identity on GKE using Terraform.
Why Use Workload Identity?
Traditionally, applications running in GKE required service account keys to authenticate with Google Cloud APIs. This approach has several drawbacks:
- Security Risk: Service account keys can be compromised if not managed properly.
- Operational Overhead: Managing and rotating keys adds complexity to operations.
- IAM Management: Fine-grained IAM permissions are difficult to enforce with static keys.
Workload Identity addresses these issues by allowing Kubernetes workloads to authenticate as Google Cloud service accounts without requiring keys. Instead, it uses Kubernetes-native mechanisms to associate Kubernetes Service Accounts (KSAs) with Google Cloud Service Accounts (GSAs).
Prerequisites
Before we begin, ensure you have the following:
- Google Cloud SDK: Installed and authenticated to your project.
- Terraform: Installed on your local machine.
- GKE Cluster: A GKE cluster where we will deploy Workload Identity.
Setting Up Workload Identity with Terraform
Let’s dive into the steps required to set up Workload Identity on GKE using Terraform.
Step 1: Create a Google Cloud Service Account
First, we need to create a Google Cloud Service Account (GSA) that our Kubernetes workloads will use to access Google Cloud resources.
resource "google_service_account" "workload-identity-user-sa" {
account_id = "stackdriver"
display_name = "Service Account For Workload Identity"
}
Step 2: Grant IAM Roles to the GSA
Next, grant the necessary IAM roles to the GSA. For this example, we’ll grant the roles/monitoring.viewer
role, which allows the GSA to read metrics in Google Cloud Monitoring.
data "google_client_config" "current" {}
resource "google_project_iam_member" "monitoring-role" {
project = data.google_client_config.current.project
role = "roles/monitoring.viewer"
member = "serviceAccount:${google_service_account.workload-identity-user-sa.email}"
}
Step 3: Enable Workload Identity on GKE
We need to enable Workload Identity on our GKE cluster. This requires setting the workload_identity_config
on the GKE cluster.
data "google_client_config" "current" {}
resource "google_container_cluster" "default" {
name = "test-cluster"
# required to enable workload identity
workload_identity_config {
workload_pool = "${data.google_client_config.current.project}.svc.id.goog"
}
}
resource "google_container_node_pool" "default" {
name = "pool"
cluster = google_container_cluster.default.id
node_count = "2"
node_config {
image_type = "COS_CONTAINERD"
# required to enable workload identity on node pool
workload_metadata_config {
mode = "GKE_METADATA"
}
}
}
Step 4: Create a Kubernetes Service Account
Create a Kubernetes Service Account (KSA) in the GKE cluster. This KSA will be associated with the GSA.
resource "kubernetes_service_account" "ksa" {
metadata {
name = "stackdriver-ksa"
namespace = "default"
annotations = {
"iam.gke.io/gcp-service-account" = google_service_account.example_gsa.email
}
}
}
Step 5: Configure IAM Policy Binding
Bind the KSA to the GSA using the google_service_account_iam_binding
resource.
data "google_client_config" "current" {}
resource "google_project_iam_member" "workload_identity-role" {
service_account_id = google_service_account.workload-identity-user-sa.id
role = "roles/iam.workloadIdentityUser"
member = "serviceAccount:${project_id}.svc.id.goog[${namespace}/${var.service_account_name}]"
}
Step 6: Deploy an Application Using the KSA
Finally, deploy an application that uses the KSA. The application will automatically authenticate as the GSA when accessing Google Cloud resources.
apiVersion: apps/v1
kind: Deployment
metadata:
name: stackdriver-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: stackriver-app
template:
metadata:
labels:
app: stackriver-app
spec:
serviceAccountName: stackdriver-ksa
containers:
- name: stackdriver-container
image: prometheuscommunity/stackdriver-exporter:latest
args:
- --google.project-id=$project_id >> replace it with gcp project id
- --monitoring.metrics-type-prefixes=cloudsql.googleapis.com/database
Now we can see the Google Cloud Resources Metrics from the stack driver pod.
kubectl logs -f stackdriver-app-gsvce
Output:
# HELP stackdriver_cloudsql_database_cloudsql_googleapis_com_database_cpu_reserved_cores Number of cores reserved for the database.
# TYPE stackdriver_cloudsql_database_cloudsql_googleapis_com_database_cpu_reserved_cores gauge
stackdriver_cloudsql_database_cloudsql_googleapis_com_database_cpu_reserved_cores{database_id="projectid:databasename",project_id="projectid",region="us",unit="1"} 2 1717407660000
Reference: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
Conclusion
This blog post explored setting up Workload Identity on GKE using Terraform. Following these steps, you can ensure that your Kubernetes workloads securely access Google Cloud resources without needing static service account keys. Workload Identity enhances security, simplifies management, and aligns with best practices for modern cloud-native applications.
Thanks for reading this far!! We appreciate your comments and feedback.
About The Author
Suraj Solanki
Senior DevOps Engineer
LinkedIn: https://www.linkedin.com/in/suraj-solanki