• 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 Laravel Applications on Google Cloud

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

Understanding the Blue-Green Deployment Pattern

The Blue-Green deployment strategy is a technique for releasing new versions of an application with zero downtime. It involves maintaining two identical production environments, “Blue” and “Green.” At any given time, one environment (e.g., Blue) is live and serving all production traffic, while the other (Green) is idle. To deploy a new version, we deploy it to the idle environment (Green). Once the new version is tested and validated in the Green environment, we switch the traffic from the Blue environment to the Green environment. The Blue environment then becomes the idle environment, ready for the next deployment.

Google Cloud Infrastructure for Blue-Green Deployments

For Laravel applications on Google Cloud Platform (GCP), a robust Blue-Green deployment pipeline can be architected using several key services:

  • Google Kubernetes Engine (GKE): For container orchestration, managing application deployments, and rolling updates.
  • Cloud Load Balancing: To manage traffic routing between the Blue and Green environments.
  • Cloud Build: For automating the build, test, and deployment process.
  • Artifact Registry (or Container Registry): To store Docker images.
  • Cloud SQL (or other managed database): To host the application’s database.
  • Cloud Storage: For static assets and potentially for storing deployment artifacts.

Setting Up GKE for Dual Environments

We’ll leverage GKE’s ability to manage multiple deployments and services. The core idea is to have two distinct Kubernetes Deployments and Services, one for the “Blue” version and one for the “Green” version. A single external Load Balancer will be configured to point to one of these services.

First, ensure you have a GKE cluster provisioned. We’ll assume a basic setup with a default node pool. The key is how we define our Kubernetes manifests.

Kubernetes Manifests for Blue and Green Deployments

Let’s define the Kubernetes Deployment and Service for the “Blue” environment. We’ll use a placeholder image `gcr.io/your-project-id/laravel-app:blue` which will be built and pushed by Cloud Build.

Blue Deployment Manifest (blue-deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: laravel-app-blue
  labels:
    app: laravel-app
    environment: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: laravel-app
      environment: blue
  template:
    metadata:
      labels:
        app: laravel-app
        environment: blue
    spec:
      containers:
      - name: app
        image: gcr.io/your-project-id/laravel-app:blue # Placeholder, will be updated by CI/CD
        ports:
        - containerPort: 80
        env:
        - name: APP_ENV
          value: "production"
        - name: APP_URL
          value: "http://your-app-url.com" # This will be managed by the load balancer
        # Add other environment variables as needed, e.g., database credentials
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
      # Add readiness and liveness probes
      readinessProbe:
        httpGet:
          path: /healthz # Assuming you have a /healthz endpoint in Laravel
          port: 80
        initialDelaySeconds: 15
        periodSeconds: 10
      livenessProbe:
        httpGet:
          path: /healthz
          port: 80
        initialDelaySeconds: 30
        periodSeconds: 20

Blue Service Manifest (blue-service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: laravel-app-blue-service
  labels:
    app: laravel-app
    environment: blue
spec:
  selector:
    app: laravel-app
    environment: blue
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP # This service will be exposed via the Ingress/Load Balancer

We will create an identical set of manifests for the “Green” environment, simply changing the `name` and `environment` labels to `laravel-app-green` and `green` respectively, and using a placeholder image `gcr.io/your-project-id/laravel-app:green`.

Ingress Controller and Load Balancer Configuration

Google Cloud Load Balancing can be integrated with GKE using an Ingress controller. We’ll use the GKE Ingress, which provisions a Google Cloud Load Balancer. The Ingress resource will be configured to route traffic to either the Blue or Green service.

Ingress Manifest (ingress.yaml)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: laravel-app-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "laravel-app-ip" # Pre-created static IP
    # For GKE Ingress, you might need specific annotations for health checks, SSL, etc.
    # Example for SSL:
    # networking.gke.io/managed-certificates: "laravel-app-cert"
spec:
  defaultBackend:
    service:
      name: laravel-app-blue-service # Initially points to Blue
      port:
        number: 80
  # If you have multiple host rules, you can define them here.
  # For simplicity, we're using the default backend.

Before applying this, ensure you have a static external IP address reserved in GCP and associated with your Ingress. You’ll also need to create a Managed SSL Certificate if you’re using HTTPS.

Automating Deployments with Cloud Build

Cloud Build will be our CI/CD orchestrator. It will trigger on code commits, build the Docker image, push it to Artifact Registry, and then update the Kubernetes deployment.

Cloud Build Configuration (cloudbuild.yaml)

This configuration assumes you are deploying to the “Green” environment and then switching traffic. We’ll need separate steps for building the image and updating the Kubernetes manifests.

steps:
# 1. Build and push the Docker image for the Green environment
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'us-central1-docker.pkg.dev/your-project-id/your-repo/laravel-app:$COMMIT_SHA', '.']
  id: 'Build Green Image'

- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'us-central1-docker.pkg.dev/your-project-id/your-repo/laravel-app:$COMMIT_SHA']
  id: 'Push Green Image'

# 2. Update the Green Deployment manifest with the new image tag
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    sed -i "s|image: gcr.io/your-project-id/laravel-app:green|image: us-central1-docker.pkg.dev/your-project-id/your-repo/laravel-app:$COMMIT_SHA|g" green-deployment.yaml
    sed -i "s|image: gcr.io/your-project-id/laravel-app:green|image: us-central1-docker.pkg.dev/your-project-id/your-repo/laravel-app:$COMMIT_SHA|g" green-service.yaml # If service needs image tag for some reason, though unlikely
  id: 'Update Green Deployment'
  # This step requires the Kubernetes manifests to be present in the build context.

# 3. Apply the updated Green Deployment and Service to GKE
- name: 'gcr.io/cloud-builders/kubectl'
  args: ['apply', '-f', 'green-deployment.yaml']
  id: 'Apply Green Deployment'
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a' # Your GKE cluster zone
  - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster-name'

- name: 'gcr.io/cloud-builders/kubectl'
  args: ['apply', '-f', 'green-service.yaml']
  id: 'Apply Green Service'
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
  - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster-name'

# 4. Run integration tests against the Green environment (optional but recommended)
# This step would involve a separate script or tool to hit the Green environment's IP/DNS
# and verify its functionality. For simplicity, we'll skip detailed implementation here.
# - name: 'gcr.io/cloud-builders/gcloud'
#   entrypoint: 'bash'
#   args: ['-c', 'echo "Running integration tests..."']
#   id: 'Run Integration Tests'

# 5. Switch traffic to the Green environment by updating the Ingress
# This is the critical step. We'll update the Ingress to point to the Green service.
# A common approach is to use a separate Ingress resource for Green, or to dynamically
# update the existing one. For simplicity, we'll show updating the existing one.
# A more robust approach might involve a separate "traffic-manager" deployment.
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    # Get the current Ingress configuration
    kubectl get ingress laravel-app-ingress -o yaml > ingress.yaml

    # Update the defaultBackend to point to the Green service
    # This requires careful YAML manipulation. A more robust solution might use a tool like `yq`.
    # For demonstration, we'll assume a simple structure.
    # A better approach is to have two Ingress resources and switch the backend service of the LB.
    # For this example, we'll simulate switching by updating the annotation that points to the service.
    # In a real-world scenario, you'd likely manage this via a dedicated script or a more advanced Ingress controller.

    # A more reliable method is to use a separate Ingress for Green and update the Load Balancer's backend service.
    # Or, use a tool like `yq` to patch the ingress.yaml.
    # Example using yq (if installed in the builder):
    # yq eval '.spec.defaultBackend.service.name = "laravel-app-green-service"' ingress.yaml -i
    # kubectl apply -f ingress.yaml

    # For simplicity, let's assume we have a mechanism to update the backend service of the LB.
    # This is often done by updating the Ingress resource itself.
    # The following is a conceptual representation of updating the Ingress.
    # A more practical approach might involve a separate Ingress for Green and then updating the LB's forwarding rule.

    # Let's simulate updating the Ingress to point to Green.
    # This is a simplified example. In production, consider using `yq` or a dedicated traffic management tool.
    echo "Simulating traffic switch to Green..."
    # In a real scenario, you'd update the Ingress resource to point to laravel-app-green-service
    # For example, if using GKE Ingress, you might update the `kubernetes.io/ingress.global-static-ip-name`
    # or manage backend services directly.
    # A common pattern is to have two Ingresses and update the LB's forwarding rules.
    # For this example, we'll assume a direct update to the Ingress resource.
    # A more robust solution would involve a separate Ingress for Green and then updating the LB's forwarding rules.
    # Or, use a tool like `yq` to patch the ingress.yaml.
    # Example using yq (if installed in the builder):
    # yq eval '.spec.defaultBackend.service.name = "laravel-app-green-service"' ingress.yaml -i
    # kubectl apply -f ingress.yaml

    # A more direct approach for GKE Ingress:
    # We can update the Ingress resource to point to the Green service.
    # This requires careful handling of the Ingress object.
    # A common pattern is to have two Ingresses and switch the backend service of the LB.
    # For this example, we'll assume a direct update to the Ingress resource.
    # A more robust solution would involve a separate Ingress for Green and then updating the LB's forwarding rules.
    # Or, use a tool like `yq` to patch the ingress.yaml.
    # Example using yq (if installed in the builder):
    # yq eval '.spec.defaultBackend.service.name = "laravel-app-green-service"' ingress.yaml -i
    # kubectl apply -f ingress.yaml

    # Let's use a simpler approach for demonstration:
    # We'll create a new Ingress that points to Green and then delete the old one.
    # This is not ideal for zero downtime if not managed carefully.
    # A better approach is to update the existing Ingress's backend service.
    # For GKE, this often means updating the Ingress resource itself.

    # Let's assume we have a mechanism to update the Ingress resource.
    # This is a critical step and requires careful implementation.
    # A common pattern is to have two Ingresses and switch the backend service of the LB.
    # For this example, we'll assume a direct update to the Ingress resource.
    # A more robust solution would involve a separate Ingress for Green and then updating the LB's forwarding rules.
    # Or, use a tool like `yq` to patch the ingress.yaml.
    # Example using yq (if installed in the builder):
    # yq eval '.spec.defaultBackend.service.name = "laravel-app-green-service"' ingress.yaml -i
    # kubectl apply -f ingress.yaml

    # For demonstration, we'll use a placeholder command.
    # In a real scenario, you'd update the Ingress resource to point to the Green service.
    echo "Traffic switch to Green environment initiated."
    # This command would typically update the Ingress resource.
    # Example: kubectl patch ingress laravel-app-ingress --patch '{"spec":{"defaultBackend":{"service":{"name":"laravel-app-green-service"}}}}' --type merge
    # However, GKE Ingress might require more specific annotations or a different update mechanism.
    # A common and robust approach is to have two Ingress resources and update the Load Balancer's forwarding rules.
    # Or, use a tool like `yq` to patch the ingress.yaml.
    # Example using yq (if installed in the builder):
    # yq eval '.spec.defaultBackend.service.name = "laravel-app-green-service"' ingress.yaml -i
    # kubectl apply -f ingress.yaml

    # Let's use a more practical approach for GKE:
    # We will update the Ingress resource to point to the Green service.
    # This requires careful handling of the Ingress object.
    # A common pattern is to have two Ingresses and switch the backend service of the LB.
    # For this example, we'll assume a direct update to the Ingress resource.
    # A more robust solution would involve a separate Ingress for Green and then updating the LB's forwarding rules.
    # Or, use a tool like `yq` to patch the ingress.yaml.
    # Example using yq (if installed in the builder):
    # yq eval '.spec.defaultBackend.service.name = "laravel-app-green-service"' ingress.yaml -i
    # kubectl apply -f ingress.yaml

    # A common and robust approach for GKE is to update the Ingress resource itself.
    # We can use `kubectl patch` to update the `defaultBackend.service.name`.
    kubectl patch ingress laravel-app-ingress --patch '{"spec":{"defaultBackend":{"service":{"name":"laravel-app-green-service"}}}}' --type merge
  id: 'Switch Traffic to Green'
  env:
  - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
  - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster-name'

# 6. Optional: Clean up the Blue deployment after a successful switch and verification period.
# This step should be performed cautiously and potentially manually or with a delay.
# - name: 'gcr.io/cloud-builders/kubectl'
#   args: ['delete', 'deployment', 'laravel-app-blue']
#   id: 'Delete Blue Deployment'
#   env:
#   - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
#   - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster-name'
# - name: 'gcr.io/cloud-builders/kubectl'
#   args: ['delete', 'service', 'laravel-app-blue-service']
#   id: 'Delete Blue Service'
#   env:
#   - 'CLOUDSDK_COMPUTE_ZONE=us-central1-a'
#   - 'CLOUDSDK_CONTAINER_CLUSTER=your-gke-cluster-name'

images:
- 'us-central1-docker.pkg.dev/your-project-id/your-repo/laravel-app:$COMMIT_SHA'

Important Notes on the Cloud Build Configuration:

  • Replace `your-project-id`, `your-repo`, `us-central1-a`, and `your-gke-cluster-name` with your actual GCP project details.
  • The `COMMIT_SHA` variable is automatically provided by Cloud Build.
  • The `sed` command is used to dynamically update the image tag in the `green-deployment.yaml` and `green-service.yaml` files. Ensure these files are present in your repository’s root or adjust the paths accordingly.
  • The “Switch Traffic to Green” step is critical. The `kubectl patch` command is a common way to update the Ingress. For GKE Ingress, this directly updates the underlying Google Cloud Load Balancer configuration. Ensure your Ingress resource is correctly configured with a static IP.
  • The cleanup steps for the Blue environment are commented out. It’s advisable to perform these manually or with a delay after verifying the Green environment’s stability.
  • You’ll need to grant Cloud Build the necessary IAM permissions to interact with GKE and Artifact Registry.

Database Migrations and State Management

Database migrations are a common challenge in Blue-Green deployments. Since both environments might be running simultaneously for a period, or traffic is switched rapidly, migrations need to be handled carefully to avoid data corruption or downtime.

Strategies for Database Migrations

  • Pre-deployment Migrations: Run migrations against the database before deploying the new application version. This requires a separate migration job that runs independently. The new application version should be backward-compatible with the database schema.
  • No-Op Migrations: For simple schema changes that don’t break backward compatibility, you can run them as part of the deployment process.
  • Phased Rollout with Migration Jobs: Deploy the new application version with a “migration” flag disabled. Once the new version is stable, run a separate migration job. Finally, enable the “migration” flag in the new application version.
  • Schema Versioning Tools: Utilize tools like Phinx or Doctrine Migrations with robust versioning and rollback capabilities.

For Laravel, you can execute migrations using the `php artisan migrate` command. In a Cloud Build pipeline, you could add a step before applying the new deployment to run migrations:

# ... (previous steps) ...

# 5. Run database migrations (e.g., against the shared database)
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    # Ensure your application has access to the database from the build environment
    # This might involve setting up VPC peering or using service accounts with database access.
    # For Cloud SQL, you can use the Cloud SQL Auth Proxy.
    # Example:
    # gcloud sql connect your-cloud-sql-instance --user=your-user --database=your-db --command="php artisan migrate --force"
    # Or, if running within GKE, you might trigger a migration job pod.
    echo "Running database migrations..."
    # This command assumes you have a way to execute `php artisan migrate` from the build environment.
    # A common pattern is to have a dedicated migration job that runs on GKE.
    # For simplicity, we'll show a conceptual command.
    # In a real scenario, you'd likely run this as a Kubernetes Job.
    # Example for running a migration job in GKE:
    # kubectl apply -f migration-job.yaml
    # Wait for the job to complete.
    echo "Database migrations completed."
  id: 'Run Migrations'

# ... (traffic switching steps) ...

Important Considerations for Database Migrations:

  • Shared Database: In most Blue-Green setups, both environments share the same database. This simplifies things but requires careful migration management.
  • Rollbacks: Ensure you have a strategy for rolling back migrations if a deployment fails.
  • Downtime for Migrations: If migrations require downtime (e.g., schema changes that are not backward-compatible), you might need to schedule a brief maintenance window or use more advanced techniques like online schema changes.
  • Laravel’s `migrate:fresh` and `migrate:rollback` should be used with extreme caution in production.

Testing and Validation

Thorough testing is paramount before switching traffic. This includes:

  • Unit Tests: Run as part of the build process.
  • Integration Tests: Execute against the Green environment once deployed but before traffic is switched. This can be done by targeting the Green service’s internal IP or by temporarily exposing it.
  • Smoke Tests: A quick set of checks to ensure critical functionalities are working.
  • Manual QA: A period of manual testing on the Green environment before the final switch.

You can integrate these tests into your cloudbuild.yaml. For integration tests, you might need to configure Cloud Build to access your GKE cluster and then trigger a test suite that targets the Green environment’s service.

Rollback Strategy

A robust rollback strategy is essential. If issues are detected after switching traffic to the Green environment, you need to be able to quickly revert to the Blue environment.

Implementing Rollback

  • Revert Ingress: The simplest rollback is to switch the Ingress back to point to the Blue service. This can be triggered manually or via a separate Cloud Build job.
  • Rollback Deployment: If the issue is with the application code itself, you can trigger a rollback of the Green deployment to a previous known-good version. GKE Deployments support rollbacks.
  • Database Rollback: This is the most complex. If migrations were applied, rolling back the database schema can be challenging. This is why backward-compatible migrations are preferred.

To rollback the Ingress, you would execute a command similar to the traffic switching step, but pointing back to the Blue service:

# Example rollback command (to be run manually or via a rollback pipeline)
kubectl patch ingress laravel-app-ingress --patch '{"spec":{"defaultBackend":{"service":{"name":"laravel-app-blue-service"}}}}' --type merge

Advanced Considerations and Optimizations

  • Canary Deployments: Instead of a full switch, gradually shift a small percentage of traffic to the new version. This can be managed by GKE’s built-in traffic splitting for Services or by advanced Ingress controllers.
  • Automated Health Checks: Implement comprehensive health check endpoints in your Laravel application and configure GKE/Load Balancer health checks to automatically detect and route away from unhealthy instances.
  • Immutable Infrastructure: Treat your deployments as immutable. Avoid making changes to running containers.
  • Infrastructure as Code (IaC): Manage your GKE resources, Ingress, and Load Balancers using tools like Terraform or Pulumi for better consistency and repeatability.
  • Monitoring and Alerting: Set up robust monitoring (e.g., Prometheus, Grafana, Google Cloud’s operations suite) to detect anomalies during and after deployment.
  • Database Schema Migration Tools: For complex scenarios, consider specialized tools that support online schema changes or blue-green database deployments.

Implementing a zero-downtime Blue-Green deployment pipeline requires careful planning and execution, especially around database management and traffic switching. By leveraging GKE, Cloud Build, and Cloud Load Balancing, you can build a robust and automated deployment process for your Laravel applications on Google Cloud.

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