Appearance
GCP Migration
This document provides a comprehensive technical guide for migrating the IT Ticketing Service from its current on-premises VMware environment to Google Cloud Platform (GCP). This application is a demonstration for the Google Next 2026 Agentic AI Modernization workshop, showcasing how to migrate legacy workloads to GCP with minimal code changes. The migration is designed to be configuration-driven, leveraging externalized configuration and cloud-native managed services for database and deployment.
Migration Strategy
The core philosophy for this migration is to treat the target environment (GCP) as an external configuration detail rather than a driver for code refactoring. This approach, rooted in the 12-Factor App methodology, ensures the application remains portable and simplifies both the migration process and future maintenance.
Key principles of this strategy include:
- Configuration-Driven Approach: All environment-specific settings, such as database connection strings and message broker endpoints, are managed externally through Spring Boot's property management system. The migration is primarily achieved by creating a new configuration profile for the GCP environment.
- Minimizing Code Changes: The application code is written to be environment-agnostic. It relies on standard Spring abstractions like
Spring Data JPAandSpring AMQP, which can be re-pointed to different underlying services (e.g., Cloud SQL for MySQL, managed RabbitMQ) via configuration alone. - Leveraging Managed Services: We will replace on-premises dependencies (MySQL, RabbitMQ) with managed GCP equivalents (Cloud SQL, managed RabbitMQ services) to reduce operational overhead and improve scalability and reliability.
For more details on the application's configuration model, see the Configuration Guide.
Cloud SQL Integration
The application will be migrated from its on-premises MySQL database to a managed Cloud SQL for MySQL instance. This change is handled entirely through configuration updates in the application.properties file.
Current On-Premises Configuration
The current configuration points to a specific on-premises database server:
properties
# src/main/resources/application.properties
# MySQL Database Configuration
spring.datasource.url=jdbc:mysql://legacydb.next26.slalomlab.com:3306/ticketing?createDatabaseIfNotExist=true
spring.datasource.username=ticketing_user
spring.datasource.password=changeme
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver1
2
3
4
5
6
7
2
3
4
5
6
7
GCP Configuration with Cloud SQL Auth Proxy
For secure and simplified connectivity to Cloud SQL, we will use the Cloud SQL Auth Proxy. The proxy handles secure authentication with the database using IAM credentials, eliminating the need for static IP allowlists or managing SSL certificates manually.
To enable this, the following changes are required:
Add the Spring Cloud GCP SQL Starter: This dependency includes the Cloud SQL Socket Factory, which integrates the Auth Proxy with the JDBC driver.
xml<!-- pom.xml --> <dependency> <groupId>com.google.cloud</groupId> <artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId> </dependency>1
2
3
4
5Update Datasource Configuration: Create a GCP-specific profile (
application-gcp.properties) and update the datasource properties. Thespring.cloud.gcp.sql.instance-connection-nameproperty identifies the target Cloud SQL instance.properties# src/main/resources/application-gcp.properties # Cloud SQL for MySQL Configuration spring.cloud.gcp.sql.instance-connection-name=your-gcp-project:your-region:your-instance-name spring.cloud.gcp.sql.database-name=ticketing spring.datasource.username=ticketing_user # Password will be managed by Secret Manager (see below) spring.datasource.password=${sm://it-ticketing-service/db-password} # The following properties are auto-configured by the starter # spring.datasource.url=jdbc:mysql://google/ticketing?cloudSqlInstance=... # spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver1
2
3
4
5
6
7
8
9
10
11
12Note: The
spring.datasource.urlis automatically constructed by the Spring Cloud GCP starter wheninstance-connection-nameis provided.
For more information on the database setup, refer to the Database Integration documentation.
Messaging Layer Migration
The application uses RabbitMQ for publishing ticket lifecycle events. There are two primary approaches for migrating the messaging layer to GCP:
- Continue using RabbitMQ (recommended for minimal code changes)
- Migrate to Cloud Pub/Sub (requires code changes but provides deeper GCP integration)
Current RabbitMQ Configuration
The application is currently configured to connect to an on-premises RabbitMQ instance.
properties
# src/main/resources/application.properties
# RabbitMQ Configuration
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
# RabbitMQ Custom Properties
rabbitmq.exchange.name=ticket.exchange
rabbitmq.queue.name=ticket.queue
rabbitmq.routing.key=ticket.routing.key1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Option 1: Continue Using RabbitMQ (Recommended for Minimal Code Changes)
To maintain zero code changes, continue using RabbitMQ in GCP by updating only the configuration. You can use a managed RabbitMQ service (such as CloudAMQP, RabbitMQ on GCE, or a self-managed instance) and simply point to the new broker endpoint.
properties
# src/main/resources/application-gcp.properties
# RabbitMQ Configuration for GCP
spring.rabbitmq.host=your-rabbitmq-instance.gcp.example.com
spring.rabbitmq.port=5672
spring.rabbitmq.username=ticketing_user
# Password managed by Secret Manager
spring.rabbitmq.password=${sm://it-ticketing-service/rabbitmq-password}
# RabbitMQ Custom Properties (unchanged)
rabbitmq.exchange.name=ticket.exchange
rabbitmq.queue.name=ticket.queue
rabbitmq.routing.key=ticket.routing.key1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
No code changes are required - the application continues using Spring AMQP and RabbitTemplate exactly as before.
For more details on the messaging setup, see the RabbitMQ Integration documentation.
Option 2: Migrate to Cloud Pub/Sub (Alternative Approach)
For teams willing to make code changes to achieve deeper GCP integration, you can migrate from RabbitMQ to Google Cloud Pub/Sub using the Spring Cloud GCP Pub/Sub adapter. This approach provides better integration with GCP's ecosystem and eliminates the need to manage a separate message broker.
Tradeoffs:
- Advantages: Native GCP service, no broker infrastructure to manage, automatic scaling, integration with Cloud Monitoring and Cloud Logging.
- Disadvantages: Requires code changes to replace Spring AMQP with Spring Cloud GCP Pub/Sub APIs, different messaging semantics (publish/subscribe vs. AMQP exchanges and queues).
Implementation Note: This approach requires replacing RabbitTemplate and related Spring AMQP components with PubSubTemplate from the spring-cloud-gcp-starter-pubsub dependency. Message publishing and consumption logic will need to be refactored accordingly.
Container Deployment Options
The application must be containerized for deployment on GCP. A Dockerfile will be created to package the application into a portable container image. For guidance on creating the container, see the Docker Deployment guide.
Once containerized, the image will be pushed to Google Artifact Registry. From there, we have two primary deployment targets:
1. Cloud Run
Cloud Run is a fully managed, serverless platform that automatically scales containerized applications.
- Best for: Stateless web services, APIs, and event-driven workloads.
- Advantages:
- Simplicity: Deploy directly from a container image with minimal configuration.
- Scale-to-Zero: Incurs no cost when there is no traffic.
- Fully Managed: No need to manage servers or clusters.
- Deployment Command Example:bash
gcloud run deploy it-ticketing-service \ --image gcr.io/your-gcp-project/it-ticketing-service:latest \ --platform managed \ --region us-central1 \ --allow-unauthenticated \ --set-env-vars="SPRING_PROFILES_ACTIVE=gcp"1
2
3
4
5
6
2. Google Kubernetes Engine (GKE)
GKE provides a managed environment for deploying, managing, and scaling containerized applications using Google infrastructure.
- Best for: Complex, multi-service applications, workloads requiring fine-grained network control, or organizations with existing Kubernetes expertise.
- Advantages:
- Control & Flexibility: Full control over the cluster configuration, networking, and storage.
- Portability: Adheres to the open-source Kubernetes standard.
- Ecosystem: Leverages the vast Kubernetes ecosystem of tools and integrations.
- Deployment Process: Involves creating Kubernetes manifest files (
Deployment.yaml,Service.yaml, etc.) and applying them to the GKE cluster usingkubectl.
Configuration Management
Secure and flexible configuration is critical for a cloud environment. We will use a combination of Spring Profiles and Google Secret Manager.
Secret Manager Integration
Google Secret Manager provides a secure and convenient storage system for API keys, passwords, and other sensitive data. We will integrate it using the spring-cloud-gcp-starter-secretmanager dependency.
This allows us to reference secrets directly in our configuration files. The starter will resolve these references at application startup.
Example application-gcp.properties:
properties
# Reference a secret stored in Secret Manager
# The format is sm://<project-id>/<secret-name>/<version>
# If project-id is omitted, the default project is used.
# If version is omitted, the latest version is used.
spring.datasource.password=${sm://it-ticketing-service/db-password}1
2
3
4
5
6
2
3
4
5
6
Environment-Specific Properties
By activating the gcp profile when running in Google Cloud, we instruct Spring Boot to load application-gcp.properties on top of the base application.properties. This cleanly separates on-premises and cloud configurations.
Running the application with the GCP profile:
- As a JAR file:bash
java -jar -Dspring.profiles.active=gcp target/it-ticketing-service-1.0.0.jar1 - In Cloud Run/GKE: Set the
SPRING_PROFILES_ACTIVEenvironment variable togcp.
For more details, refer to the main Configuration Guide.
Migration Checklist
This checklist outlines the high-level steps for executing the migration.
| Phase | Task | Status |
|---|---|---|
| 1. Pre-Migration Prep | Provision a Cloud SQL for MySQL instance. | ☐ To Do |
| Set up RabbitMQ in GCP (managed service or self-hosted). | ☐ To Do | |
| Create secrets in Secret Manager for database and RabbitMQ passwords. | ☐ To Do | |
| Create a dedicated IAM Service Account with necessary roles (Cloud SQL Client, Secret Manager Secret Accessor). | ☐ To Do | |
Create a Dockerfile to containerize the application. | ☐ To Do | |
| 2. Configuration | Add spring-cloud-gcp dependencies for SQL and Secret Manager to pom.xml. | ☐ To Do |
Create application-gcp.properties with configurations for Cloud SQL, RabbitMQ, and Secret Manager. | ☐ To Do | |
| Build the container image and push it to Artifact Registry. | ☐ To Do | |
| 3. Testing in GCP | Deploy the container to a non-production GCP environment (e.g., Cloud Run) with the gcp profile active. | ☐ To Do |
| Execute functional and integration tests to verify database connectivity and message publishing. | ☐ To Do | |
| Perform performance and load testing to validate scaling behavior. | ☐ To Do | |
| Verify that logs and metrics are correctly ingested into Cloud Logging and Cloud Monitoring. | ☐ To Do | |
| 4. Rollback Strategy | Document the rollback procedure. | ☐ To Do |
Rollback Strategy
Due to the configuration-driven design with zero code changes, the rollback strategy is straightforward:
- Immediate Rollback: Re-deploy the application container with the default (on-premises) Spring profile active. This will point the application back to the on-premises MySQL and RabbitMQ instances. No code recompilation is needed.
- Data Consistency: A data synchronization plan may be required to handle any data written to Cloud SQL during the migration window if a rollback is initiated. This is outside the scope of the application's configuration but is a critical operational consideration.