Appearance
Cloud Migration Guide
This document provides a comprehensive technical guide for migrating the IT Ticketing Service from its current on-premises environment to the Google Cloud Platform (GCP). It is intended for developers and DevOps engineers responsible for the migration, deployment, and maintenance of the application in the cloud.
Migration Philosophy
The migration strategy for this application is fundamentally rooted in modern cloud-native principles, designed to ensure a smooth transition with maximum flexibility and minimal code refactoring.
Configuration-Based Migration
The core principle is to treat the application binary as an immutable artifact and manage environment-specific settings externally. The application has been intentionally designed to be environment-agnostic, with all infrastructure dependencies (database, message broker) defined through configuration. This allows us to "point" the application to different services (on-premises vs. cloud) simply by changing its configuration, without touching the compiled code.
Minimal Code Changes Approach
As outlined in the project's design goals, the primary objective is to migrate the workload to GCP with the fewest possible code modifications. The existing technology stack, particularly the use of Spring Boot, Spring Data JPA, and Spring AMQP, is highly portable. The migration will focus on reconfiguring these modules to connect to their GCP-managed equivalents.
12-Factor App Principles
This migration adheres to the 12-Factor App methodology, particularly Factor III: Config. All configuration, including resource handles, credentials, and external service endpoints, is externalized from the code. In the on-premises environment, this is managed via the application.properties file. In GCP, this will be managed through environment variables, Kubernetes ConfigMaps/Secrets, or Google Secret Manager.
Externalized Configuration Strategy
The application leverages Spring Boot's powerful externalized configuration mechanism. Properties can be supplied via command-line arguments, OS environment variables, or property files. This hierarchy allows cloud-specific configurations to override the default values packaged within the application JAR. For more details on the application's properties, see the Application Properties documentation.
From On-Premises to GCP
The migration involves mapping each component of the on-premises stack to an equivalent, and preferably managed, service within GCP.
| On-Premises Component | GCP Target Service(s) | Migration Strategy |
|---|---|---|
| Application (Spring Boot JAR) | Google Kubernetes Engine (GKE) or Cloud Run | The application will be containerized using Docker. GKE is the recommended target for stateful or complex workloads, while Cloud Run is ideal for stateless, scalable, serverless deployments. See the Docker Deployment Guide for containerization instructions. |
| MySQL Database | Cloud SQL for MySQL | The on-premises MySQL database (legacydb.next26.slalomlab.com) will be migrated to a fully managed Cloud SQL instance. This eliminates database management overhead and provides features like automated backups, high availability, and seamless scaling. |
| RabbitMQ Message Broker | CloudAMQP (on GCP Marketplace) or RabbitMQ on GKE | To align with the minimal-change philosophy, the most direct path is to use a managed RabbitMQ service like CloudAMQP or deploy a RabbitMQ cluster on GKE. This allows the application to continue using the spring-boot-starter-amqp without code changes. A more transformative (but code-intensive) option would be to refactor the messaging layer to use Google's native Cloud Pub/Sub service. |
Configuration Changes
All migration changes are isolated to the application's configuration. The following examples demonstrate how to override the default on-premises settings for a GCP environment. These properties can be set as environment variables or managed via a application-gcp.properties Spring profile.
Updating Database Connection URL
The application must be reconfigured to connect to the new Cloud SQL instance instead of the on-premises database.
Original On-Premises Configuration (application.properties):
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=changeme1
2
3
4
2
3
4
GCP Cloud SQL Configuration Example: When connecting to Cloud SQL, it is highly recommended to use the Cloud SQL Auth Proxy for secure, authorized connections. The Spring Cloud GCP starter for JPA can simplify this. Alternatively, you can configure the JDBC URL directly.
properties
# GCP Cloud SQL Configuration
# The 'cloud-sql-instance-connection-name' is in the format 'PROJECT:REGION:INSTANCE'
spring.cloud.gcp.sql.instance-connection-name=my-gcp-project:us-central1:my-sql-instance
spring.cloud.gcp.sql.database-name=ticketing
# Credentials should be sourced from Secret Manager
spring.datasource.username=ticketing_user
spring.datasource.password=${sm://projects/my-gcp-project/secrets/db-password/versions/latest}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- Note: The
spring.cloud.gcp.sql.*properties automatically configure the JDBC URL for use with the Cloud SQL Auth Proxy.
Modifying Messaging Broker Endpoints
Similarly, the RabbitMQ connection must be updated to point to the new managed service endpoint.
Original On-Premises Configuration (application.properties):
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
2
3
4
5
6
7
8
9
10
GCP Managed RabbitMQ (CloudAMQP) Example: A managed service like CloudAMQP will provide a connection URI that contains all necessary details.
properties
# GCP Managed RabbitMQ (e.g., CloudAMQP)
# The service typically provides a single URI
spring.rabbitmq.uri=amqps://user:password@broker-hostname.rmq.cloudamqp.com/vhost
# Alternatively, you can provide individual properties
# spring.rabbitmq.host=broker-hostname.rmq.cloudamqp.com
# spring.rabbitmq.port=5671
# spring.rabbitmq.username=user
# spring.rabbitmq.password=${sm://projects/my-gcp-project/secrets/rabbitmq-password/versions/latest}
# spring.rabbitmq.ssl.enabled=true
# RabbitMQ Custom Properties (unchanged from on-premises)
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
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Using Cloud Secret Manager
Hardcoding credentials in configuration files is a security risk and violates 12-Factor App principles. In GCP, all secrets (database passwords, API keys, etc.) must be stored in Google Secret Manager.
The Spring Cloud GCP project provides seamless integration, allowing you to reference secrets directly in your property files using a special syntax:
properties
# Example of sourcing a password from Secret Manager
spring.datasource.password=${sm://db-password-secret}
# With full path:
spring.rabbitmq.password=${sm://projects/my-gcp-project/secrets/rabbitmq-password/versions/latest}1
2
3
4
5
2
3
4
5
To enable this functionality, the spring-cloud-gcp-starter-secretmanager dependency must be added to the pom.xml.
Environment-Specific Profiles
To manage these different configurations cleanly, Spring Profiles are the recommended approach. You can create a application-gcp.properties file containing all the GCP-specific overrides. When running the application in GCP, you activate this profile:
bash
# Activate the 'gcp' profile when running the application
java -Dspring.profiles.active=gcp -jar target/it-ticketing-service-1.0.0.jar1
2
2
GCP Services
This section provides a brief overview of the key GCP services that are targets for this migration.
Cloud SQL for MySQL: A fully managed relational database service that automates patching, backups, replication, and other administrative tasks. It provides a secure and scalable home for the application's MySQL database.
CloudAMQP / RabbitMQ on GKE: To maintain compatibility with the existing AMQP-based code, using a managed RabbitMQ offering (like CloudAMQP from the GCP Marketplace) or deploying a self-managed RabbitMQ cluster on GKE is the path of least resistance. This avoids a rewrite of the messaging logic.
Google Kubernetes Engine (GKE): A managed Kubernetes service for deploying, scaling, and managing containerized applications. GKE is an excellent choice for this application, as it can manage the Spring Boot service, the RabbitMQ cluster (if self-hosted), and the Cloud SQL Auth Proxy sidecar container.
Cloud Run: A fully managed serverless platform that runs stateless containers. If the application can be made fully stateless, Cloud Run offers significant benefits, including scale-to-zero and a pay-per-request pricing model, which can be highly cost-effective.
Cloud Secret Manager: A secure and convenient storage system for API keys, passwords, certificates, and other sensitive data. Its integration with other GCP services and client libraries (like Spring Cloud GCP) makes it the standard for secrets management in the cloud.
Cloud Monitoring & Logging: The application's use of Spring Boot Actuator is critical for cloud operations. The
/actuator/healthendpoint will be used by GKE and Cloud Run for liveness and readiness probes, ensuring traffic is only routed to healthy instances. Metrics and logs are automatically collected by Google Cloud's operations suite, providing deep visibility into application performance. For more details, see the Monitoring Guide.