Zero to Production: GitHub Actions CI/CD into GKE with Workload Identity
2025-03-05
Introduction
What Are We Building? 🚀
We're building a secure GitHub Actions pipeline that deploys to GKE without storing any credentials in GitHub. Instead of using service account keys, we'll use Workload Identity Federation (OIDC) so GitHub can impersonate a GCP Service Account.
No long-lived keys. No kubeconfig. Just secure, modern CI/CD.
Why This Matters
- 🔒 No secrets stored in GitHub
- 🔐 Short-lived, auditable credentials via OIDC
- 🧑💻 First-class support from Google + GitHub
- 🔁 Reusable pattern for any GCP service, not just GKE
Architecture
Flow:
- GitHub Workflow uses OIDC token
- Google validates identity and issues short-lived credentials
- Workflow impersonates a GCP Service Account
- Runs
kubectl
orgcloud
to deploy to GKE
Prerequisites
- GCP project + billing enabled
- A GKE Autopilot or Standard cluster
- GitHub repo (private or public)
- Terraform 1.3+ and
gcloud
CLI - Your app packaged into a container
Terraform Setup
New Autopilot cluster
provider "google" {
project = var.project_id
region = var.region
}
resource "google_container_cluster" "autopilot" {
name = var.cluster_name
location = var.region
enable_autopilot = true
workload_identity_config {
workload_pool = "${var.project_id}.svc.id.goog"
}
release_channel {
channel = "REGULAR"
}
ip_allocation_policy {}
networking_mode = "VPC_NATIVE"
}
Workload Identity Federation
resource "google_iam_workload_identity_pool" "github_pool" {
workload_identity_pool_id = "github"
display_name = "GitHub Actions Pool"
}
resource "google_iam_workload_identity_pool_provider" "github_provider" {
workload_identity_pool_id = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id
workload_identity_pool_provider_id = "github-provider"
display_name = "GitHub OIDC"
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.repository" = "assertion.repository"
}
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
}
resource "google_service_account" "gha_deployer" {
account_id = "gha-deployer"
display_name = "GitHub Actions deployer"
}
resource "google_service_account_iam_member" "allow_impersonation" {
service_account_id = google_service_account.gha_deployer.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_pool.name}/attribute.repository/${var.github_repo}"
}
resource "google_project_iam_member" "deploy_permissions" {
role = "roles/container.developer"
member = "serviceAccount:${google_service_account.gha_deployer.email}"
}
Variables
variable "project_id" {} variable "region" { default = "us-central1" } variable "cluster_name" { default = "gha-ci-cluster" } variable "github_repo" { description = "GitHub repo in format owner/repo" }
App deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx
ports:
- containerPort: 80
GitHub Actions Setup
name: Deploy to GKE via Workload Identity
on:
push:
branches: [ main ]
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@v1
with:
token_format: "id_token"
workload_identity_provider: "projects/<PROJECT_NUM>/locations/global/workloadIdentityPools/github/providers/github-provider"
service_account: "gha-deployer@<PROJECT_ID>.iam.gserviceaccount.com"
- name: Setup gcloud
uses: google-github-actions/setup-gcloud@v1
- name: Configure kubectl
run: |
gcloud container clusters get-credentials ${{ secrets.CLUSTER_NAME }} --region ${{ secrets.REGION }}
- name: Deploy app
run: |
kubectl apply -f k8s/
Test it
git push origin main
- GitHub will authenticate using OIDC
- GCP will issue a token
- Workflow will deploy to GKE without a service account key
Key Takeaways
🔑 Workload Identity Federation = no key rotation, no secret sprawl
🛡 GitHub OIDC → GCP IAM is the new best practice
☁️ Works for GKE, Cloud Run, Cloud Storage, etc.
✅ GitHub auth + setup-gcloud = seamless GKE integration
Conclusion
You've now built a secure, automated CI/CD pipeline using GitHub Actions + GKE + Workload Identity Federation. This is production-grade infra without touching a single JSON/token key.
Give it a try and see how it can simplify your GKE deployments!