LW IT Solutions
« Blog Overview /Cloud & AI/Tutorials / Serverless Microservices: Scaling on Google Cloud Run...

Serverless Microservices: Scaling on Google Cloud Run with GitHub Actions

Serverless Microservices: Scaling on Google Cloud Run with GitHub Actions
Contents
  1. 1. Architectural Framework: Scale-to-Zero & Keyless CI/CD
  2. 2. Step-by-Step Workload Identity Federation Setup
  3. 3. Step-by-Step GitHub Actions Workflow Configuration
  4. 4. Step-by-Step Scaling & Concurrency Engineering
  5. 5. Summary & Architectural Value
  6. Questions and answers
  7. Sources

Running microservices on static virtual machines or permanent Kubernetes clusters incurs constant baseline infrastructure costs, even during prolonged periods of zero traffic. Deploying stateless containerized web APIs to Google Cloud Run enables a fully managed, serverless architecture that scales automatically from zero instances during idle hours up to thousands of concurrent containers during traffic spikes. Integrating this deployment model with GitHub Actions and Workload Identity Federation establishes a zero-maintenance, highly secure Continuous Integration and Continuous Deployment (CI/CD) pipeline without storing long-lived service account JSON keys in external repositories.

1. Architectural Framework: Scale-to-Zero & Keyless CI/CD

An enterprise-grade serverless deployment architecture on Google Cloud relies on three decoupled components:

  • Google Cloud Run Container Execution: Stateless containers are invoked on demand via incoming HTTP requests. Concurrency settings allow a single container instance to process up to 80 simultaneous requests (the default, configurable up to 1,000) before horizontal autoscaling triggers additional instances.
  • Workload Identity Federation (WIF): Replaces static, exportable service account JSON keys with OpenID Connect (OIDC) token exchange between GitHub and Google Cloud IAM, eliminating credential leakage vulnerabilities.
  • GitHub Actions Pipeline: An automated workflow builds the application Docker image, pushes it to Google Artifact Registry, and updates the Cloud Run revision with zero downtime.
Two numbered phases: establishing trust via workload identity federation, then building and deploying to Cloud Run, with the stored JSON key crossed out
The pipeline never holds a permanent secret: GitHub proves who it is, Google hands back a token valid for minutes, and only then does anything get built or deployed.

2. Step-by-Step Workload Identity Federation Setup

To enable keyless authentication for GitHub Actions, a Workload Identity Pool and Provider must be provisioned via the Google Cloud CLI:

# 1. Create Workload Identity Pool
gcloud iam workload-identity-pools create "github-actions-pool" \
  --project="enterprise-ai-project" \
  --location="global" \
  --display-name="GitHub Actions Pool"

# 2. Create OIDC Identity Provider for GitHub
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --project="enterprise-ai-project" \
  --location="global" \
  --workload-identity-pool="github-actions-pool" \
  --display-name="GitHub Provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
  --attribute-condition="assertion.repository_owner == 'enterprise-org'" \
  --issuer-uri="https://token.actions.githubusercontent.com"

# 3. Bind Service Account to the GitHub Repository
gcloud iam service-accounts add-iam-policy-binding "ci-cd-deployer@enterprise-ai-project.iam.gserviceaccount.com" \
  --project="enterprise-ai-project" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/github-actions-pool/attribute.repository/enterprise-org/microservice-repo"

3. Step-by-Step GitHub Actions Workflow Configuration

The automated deployment pipeline requires a structured YAML configuration located in .github/workflows/deploy.yml. This workflow authenticates via OIDC, builds the container image, and deploys to Cloud Run with explicit autoscaling and concurrency parameters:

name: Deploy to Google Cloud Run

on:
  push:
    branches:
      - main

permissions:
  contents: 'read'
  id-token: 'write'

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/1234567890/locations/global/workloadIdentityPools/github-actions-pool/providers/github-provider'
          service_account: 'ci-cd-deployer@enterprise-ai-project.iam.gserviceaccount.com'

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2

      - name: Configure Docker for Artifact Registry
        run: gcloud auth configure-docker us-central1-docker.pkg.dev

      - name: Build and Push Docker Image
        run: |
          docker build -t us-central1-docker.pkg.dev/enterprise-ai-project/services/api-service:${{ github.sha }} .
          docker push us-central1-docker.pkg.dev/enterprise-ai-project/services/api-service:${{ github.sha }}

      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy api-service \
            --image us-central1-docker.pkg.dev/enterprise-ai-project/services/api-service:${{ github.sha }} \
            --region us-central1 \
            --platform managed \
            --allow-unauthenticated \
            --min-instances 0 \
            --max-instances 50 \
            --concurrency 80 \
            --memory 512Mi \
            --cpu 1

4. Step-by-Step Scaling & Concurrency Engineering

To ensure optimal resource utilization and prevent cold-start latency from degrading API performance, Cloud Run runtime flags must be configured precisely:

  1. Scale-to-Zero Verification (--min-instances=0): Lets Cloud Run scale the service down to zero instances without traffic; idle instances may be kept for up to 15 minutes, but under the default request-based billing they are not charged, bringing compute billing to exactly $0.00 during idle periods.
  2. Concurrency Tuning (--concurrency=80): Allows a single container CPU to handle up to 80 simultaneous requests before scaling out, reducing container churn and memory footprint compared to single-concurrency architectures.
  3. CPU Throttling Allocation: By default, CPU is throttled outside of active request processing. If background tasks or asynchronous cleanup operations are required post-response, set `–no-cpu-throttling` in combination with `–min-instances=1`.

5. Summary & Architectural Value

What this tutorial achieves: The deployment of a fully automated, keyless CI/CD deployment pipeline for containerized microservices on Google Cloud Run using GitHub Actions and Workload Identity Federation.

Resulting value: Hosting costs are minimized by dropping compute expenses to zero during inactive periods while retaining the ability to scale horizontally in seconds during sudden traffic bursts. Eliminating long-lived JSON service account keys removes credential leakage risks, and setting explicit concurrency limits maximizes container efficiency, creating a secure, maintenance-free serverless backend infrastructure.

Questions and answers

Does a service that scales to zero instances really cost nothing?

Compute time costs nothing; the rest of the chain does not come free. Every pipeline run pushes a new image tagged with the commit hash to Artifact Registry, and that storage is billed by volume whether the service is running or not. A cleanup policy in Artifact Registry that deletes old images while keeping a few recent ones, so that rolling back to an earlier revision remains possible, keeps that cost small.

Which roles does the ci-cd-deployer service account need beyond the Workload Identity binding?

The binding with roles/iam.workloadIdentityUser only allows GitHub to act as this account. What the account may do afterwards is determined by further roles, and the workflow needs three of them:

  1. Write access to the Artifact Registry repository, usually roles/artifactregistry.writer; without it, docker push fails.
  2. A Cloud Run role for deploying. roles/run.developer is enough for gcloud run deploy, but not for --allow-unauthenticated: that flag changes the service’s IAM policy, which requires roles/run.admin.
  3. roles/iam.serviceAccountUser on the service account the service runs as; without a separate setting, that is the project’s default Compute Engine service account. Without this role, the deployer cannot create a revision that runs under another identity.

Granting these roles as narrowly as possible, on the one repository and the one service rather than the whole project, is the sensible choice. A leaked key is ruled out; a faulty workflow is not, and the roles decide how far its damage reaches.

Is the binding to the repository enough, or can any branch deploy?

The binding covers the entire repository. The workflow only starts on a push to main, but any other workflow file in the same repository, including one on another branch, can request a token with id-token: write, and Google accepts it because the repository attribute matches.

The branch narrows it down, and GitHub’s OIDC token carries it in the ref claim. A condition on the provider such as assertion.ref == 'refs/heads/main' (added to --attribute-condition with &&), or an additionally mapped attribute that the service account is bound to, lets only runs from main through. The condition on assertion.repository_owner set in section 2 also ensures that the pool does not accept tokens from other organizations at all.

What does combining –no-cpu-throttling with –min-instances=1 cost?

The advantage the article starts with. A minimum instance with CPU always allocated runs around the clock and is billed even when no request arrives, so compute costs no longer drop to zero during idle periods. For work after the response, a separate queue or a Cloud Run job is therefore often the cheaper option, leaving the web service itself free to scale to zero.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Write a comment

Experience with other models or providers and questions about the implementation are welcome here.

The email address is not published. Required fields are marked with an asterisk.

ALL ARTICLES & CATEGORIES

CCTV

Follow this category by RSS

Cloud & AI

Follow this category by RSS

Data Privacy

All 14 articles in this category Follow this category by RSS

Digital Analytics

All 53 articles in this category Follow this category by RSS

Digital Marketing

All 32 articles in this category Follow this category by RSS

IT & Networks

All 18 articles in this category Follow this category by RSS

Music Production

Follow this category by RSS

Raspberry PI

Follow this category by RSS

Smart Home

All 19 articles in this category Follow this category by RSS

Web Development

Follow this category by RSS

WordPress Plugins & Tricks

Follow this category by RSS