• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Zero-Downtime Blue-Green Deployment Pipelines for Ruby Applications on Google Cloud

Zero-Downtime Blue-Green Deployment Pipelines for Ruby Applications on Google Cloud

Understanding the Blue-Green Deployment Pattern

The blue-green deployment strategy is a technique for releasing software that minimizes downtime and risk. It involves maintaining two identical production environments, referred to as “Blue” and “Green.” At any given time, one environment (e.g., Blue) is serving live production traffic, while the other (e.g., Green) is idle. To deploy a new version, we provision the idle environment (Green) with the new code, test it thoroughly, and then switch the router to direct all incoming traffic from Blue to Green. The old Blue environment is then kept as a rollback target or updated to the new version for the next cycle.

Leveraging Google Cloud Services for Blue-Green Deployments

Google Cloud Platform (GCP) offers a robust set of services that are well-suited for implementing blue-green deployments. We’ll focus on using Google Kubernetes Engine (GKE) for container orchestration, Cloud Load Balancing for traffic management, and Cloud Build for continuous integration and deployment.

Setting up GKE Clusters

For a true blue-green setup, we’ll need two distinct GKE clusters, or more practically, two distinct node pools within a single GKE cluster that can be logically separated. For simplicity and isolation, we’ll outline a two-cluster approach. Each cluster will host one version of our Ruby application.

First, create the “Blue” cluster:

gcloud container clusters create blue-cluster \
  --zone us-central1-a \
  --num-nodes 3 \
  --machine-type n1-standard-2 \
  --enable-autoscaling --min-nodes 1 --max-nodes 5 \
  --project YOUR_GCP_PROJECT_ID

Next, create the “Green” cluster. In a real-world scenario, you might use different zones or regions for disaster recovery, but for this example, we’ll keep it simple:

gcloud container clusters create green-cluster \
  --zone us-central1-b \
  --num-nodes 3 \
  --machine-type n1-standard-2 \
  --enable-autoscaling --min-nodes 1 --max-nodes 5 \
  --project YOUR_GCP_PROJECT_ID

Kubernetes Manifests for Application Deployment

We’ll define our Ruby application using Kubernetes manifests. This includes Deployments, Services, and Ingress resources. For blue-green, the key is to have separate Deployments and Services for each environment, and a single Ingress that will be reconfigured.

Here’s a sample deployment.yaml for the “Blue” environment. Note the use of labels for easy selection.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-ruby-app-blue
  labels:
    app: my-ruby-app
    version: v1.0.0
    environment: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-ruby-app
      environment: blue
  template:
    metadata:
      labels:
        app: my-ruby-app
        environment: blue
    spec:
      containers:
      - name: ruby-app
        image: gcr.io/YOUR_GCP_PROJECT_ID/my-ruby-app:v1.0.0
        ports:
        - containerPort: 3000
        env:
        - name: RAILS_ENV
          value: "production"
        # Add other necessary configurations like resource limits, health checks, etc.

And the corresponding service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-ruby-app-service-blue
spec:
  selector:
    app: my-ruby-app
    environment: blue
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: ClusterIP

For the “Green” environment, we’ll have identical manifests, but with the `environment` label and metadata names changed to reflect “green” and the new version (e.g., v1.1.0).

# deployment.yaml for green environment (e.g., v1.1.0)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-ruby-app-green
  labels:
    app: my-ruby-app
    version: v1.1.0
    environment: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-ruby-app
      environment: green
  template:
    metadata:
      labels:
        app: my-ruby-app
        environment: green
    spec:
      containers:
      - name: ruby-app
        image: gcr.io/YOUR_GCP_PROJECT_ID/my-ruby-app:v1.1.0
        ports:
        - containerPort: 3000
        env:
        - name: RAILS_ENV
          value: "production"
        # Add other necessary configurations
# service.yaml for green environment
apiVersion: v1
kind: Service
metadata:
  name: my-ruby-app-service-green
spec:
  selector:
    app: my-ruby-app
    environment: green
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: ClusterIP

Configuring Cloud Load Balancing and Ingress

The core of the blue-green switch lies in traffic management. We’ll use a single Global External HTTP(S) Load Balancer with GKE Ingress. The Ingress controller will manage the backend services. The trick is to dynamically update the Ingress to point to the desired environment’s Service.

First, ensure you have the GKE Ingress controller installed and configured on both clusters. If you’re using the default GKE setup, this is usually enabled by default.

Create an Ingress resource that initially points to the “Blue” environment. We’ll use annotations to configure the GKE Ingress controller.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ruby-app-ingress
  annotations:
    kubernetes.io/ingress.class: "gce"
    # This annotation is crucial for health checks.
    # It ensures traffic is only sent to healthy backends.
    ingress.gcp.kubernetes.io/backend-config: '{"default": "my-backend-config"}'
spec:
  rules:
  - http:
      paths:
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: my-ruby-app-service-blue # Initially points to Blue
            port:
              number: 80

You’ll also need a BackendConfig resource for health checks:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backend-config
spec:
  healthCheck:
    type: HTTP
    requestPath: /healthz # Your application should expose a /healthz endpoint
    port: 80 # The port the Service is exposing
    intervalSec: 30
    timeoutSec: 5
    healthyThreshold: 2
    unhealthyThreshold: 3

Automating the Deployment Pipeline with Cloud Build

Cloud Build is GCP’s CI/CD service. We can use it to automate the build, test, and deployment process for our blue-green strategy.

A cloudbuild.yaml file will orchestrate the steps. This example assumes you have two separate GKE contexts configured in Cloud Build, one for each cluster.

steps:
# Step 1: Build and push the new Docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-ruby-app:$COMMIT_SHA', '.']
  id: 'Build Image'

- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/$PROJECT_ID/my-ruby-app:$COMMIT_SHA']
  id: 'Push Image'

# Step 2: Deploy to the Green environment (staging/testing)
# This step assumes you have a 'green' context configured in Cloud Build
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'apply'
  - '-f'
  - 'k8s/deployment-green.yaml' # Manifest for the Green environment
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=us-central1-b' # Zone for green-cluster
  - 'CLOUDSDK_CONTAINER_CLUSTER=green-cluster'
  id: 'Deploy to Green'

# Step 3: Run integration/smoke tests against the Green environment
# This step would involve running your test suite against the Green environment's IP/DNS
# For simplicity, we'll just add a placeholder. In reality, you'd use a tool like curl or a dedicated testing framework.
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    echo "Running smoke tests against Green environment..."
    # Replace with actual test commands
    sleep 60 # Give the green deployment time to stabilize
    # Example: curl -f http://GREEN_ENVIRONMENT_IP/healthz || exit 1
    echo "Smoke tests passed."
  id: 'Test Green Environment'

# Step 4: Update Ingress to point to Green
# This is the critical step where traffic is switched.
# We need to modify the existing Ingress resource.
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'patch'
  - 'ingress'
  - 'my-ruby-app-ingress'
  - '--patch'
  - '{"spec":{"rules":[{"http":{"paths":[{"path":"/*","backend":{"service":{"name":"my-ruby-app-service-green","port":{"number":80}}}}}]}}]}'
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a' # Zone of the Ingress controller
  - 'CLOUDSDK_CONTAINER_CLUSTER=blue-cluster' # Cluster where the Ingress is managed
  id: 'Switch Traffic to Green'

# Step 5: (Optional) Deploy to Blue environment with the new version
# This prepares Blue for the next cycle or for rollback.
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'apply'
  - '-f'
  - 'k8s/deployment-blue.yaml' # Manifest for the Blue environment, updated with new image
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a' # Zone for blue-cluster
  - 'CLOUDSDK_CONTAINER_CLUSTER=blue-cluster'
  id: 'Update Blue Environment'

# Step 6: (Optional) Run smoke tests against the Blue environment (now with new version)
# This is for verification after the switch.
- name: 'ubuntu'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    echo "Running smoke tests against Blue environment (new version)..."
    # Replace with actual test commands
    sleep 60 # Give the blue deployment time to stabilize
    # Example: curl -f http://BLUE_ENVIRONMENT_IP/healthz || exit 1
    echo "Smoke tests passed."
  id: 'Test Blue Environment'

# Step 7: Clean up old deployments (optional, can be done manually or on a schedule)
# - name: 'gcr.io/cloud-builders/kubectl'
#   args: ['delete', 'deployment', 'my-ruby-app-blue'] # If Blue was updated in step 5
#   env:
#   - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
#   - 'CLOUDSDK_CONTAINER_CLUSTER=blue-cluster'
#   id: 'Cleanup Old Blue'

images:
- 'gcr.io/$PROJECT_ID/my-ruby-app:$COMMIT_SHA'

Rollback Strategy

The beauty of blue-green is the ease of rollback. If issues are detected after switching traffic to Green, you simply reverse the Ingress update. The original “Blue” environment (which is still serving traffic or has the previous stable version) becomes active again.

To roll back, you would trigger a separate Cloud Build job or manually execute a command that patches the Ingress to point back to the “Blue” environment’s Service:

gcloud container clusters get-credentials blue-cluster --zone us-central1-a --project YOUR_GCP_PROJECT_ID
kubectl patch ingress my-ruby-app-ingress --patch '{"spec":{"rules":[{"http":{"paths":[{"path":"/*","backend":{"service":{"name":"my-ruby-app-service-blue","port":{"number":80}}}}}]}}]}'

If the “Blue” environment was updated with the new code in Step 5 of the deployment pipeline, you might need to redeploy the *previous* stable version to the “Blue” environment before switching traffic back. This requires having the previous version’s Docker image readily available and its corresponding Kubernetes manifests.

Considerations for Stateful Applications

For applications with state (e.g., databases, persistent queues), blue-green deployments become more complex. You need a strategy for data migration or synchronization between the two environments. Common approaches include:

  • Database Schema Migrations: Ensure your database migrations are backward-compatible. Deploy the new application code that can handle both the old and new schema versions. Then, run the migration, and finally, switch traffic.
  • Data Synchronization: For complex state, consider replication or dual-writing strategies, though these add significant complexity.
  • External State Management: Offload state to services like Cloud SQL, Cloud Spanner, or managed Redis, which often have their own high-availability and upgrade strategies that can simplify your application-level blue-green deployment.

Advanced Techniques and Optimizations

Canary Deployments: Instead of a full switch, gradually shift a small percentage of traffic to the new version. This can be achieved by configuring weighted backends in the Ingress or using a service mesh like Istio. This is a stepping stone from blue-green to more sophisticated deployment strategies.

Automated Health Checks and Rollbacks: Integrate more sophisticated automated testing and monitoring. If key metrics degrade after a traffic switch, automatically trigger a rollback. Tools like Prometheus and Grafana, combined with custom alerting, are essential here.

Single Cluster, Multiple Node Pools: For cost savings and simpler management, you can sometimes achieve a blue-green effect within a single GKE cluster by using distinct node pools and network policies to isolate workloads. However, this requires careful network configuration and might not offer the same level of isolation as separate clusters.

Database Blue-Green: Apply the same principles to your database infrastructure. This often involves setting up replication and performing a controlled cutover. GCP’s database services can assist with this.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala