Google Cloud Database Migration Service: Guía de Arquitectura para Migrar PostgreSQL y SQL Server a Cloud SQL con Mínimo Downtime
Descubre cómo planificar, orquestar y ejecutar migraciones homogéneas de bases de datos relacionales on-premise hacia Google Cloud SQL utilizando el motor serverless de Database Migration Service con replicación continua CDC.
Puntos Clave del Pipeline de Migración
El Fin de las Migraciones "Big Bang": De On-Premise a Cloud SQL sin Bloquear el Negocio
Durante décadas, las migraciones de bases de datos relacionales en entornos empresariales han sido sinónimo de fines de semana de alta tensión, ventanas de mantenimiento nocturnas de doce horas y un miedo constante a tener que ejecutar un rollback catastrófico a las cinco de la mañana del domingo. En el paradigma tradicional, se detenían las escrituras en la base de datos de producción, se ejecutaba un volcado masivo mediante utilidades como pg_dump o backups de SQL Server (.bak), se transferían terabytes por la red y se intentaba restaurar en el destino antes de que abrieran las oficinas el lunes.
En el ecosistema cloud moderno, este enfoque es inviable para cualquier compañía que opere en tiempo real. Google Cloud Database Migration Service (DMS) nació específicamente para erradicar este modelo. DMS es un servicio de orquestación y replicación totalmente gestionado y serverless que se apoya en los motores nativos de replicación de las bases de datos origen (como pglogical o replicación lógica en PostgreSQL, y Change Data Capture o Change Tracking en Microsoft SQL Server) para sincronizar inicialmente el histórico y mantener un flujo continuo de cambios en tiempo real hasta el momento exacto del cutover.
Experiencia de Producción: El Reto de Modernizar Backend y BBDD al Mismo Tiempo
En nuestras auditorías y proyectos de arquitectura cloud, nos encontramos frecuentemente con clientes que desean modernizar su arquitectura completa pero se sienten paralizados por el acoplamiento. Recientemente trabajamos con una compañía que mantenía una base de datos Microsoft SQL Server alojada on-premise consumida por un monolito legacy en Python con Flask. Su objetivo estratégico era doble: migrar la base de datos a Google Cloud SQL y, a su vez, reescribir y desacoplar los servicios hacia una arquitectura moderna y asíncrona con FastAPI desplegada en Cloud Run. Intentar hacer todo en un único "Big Bang" hubiera sido un suicidio operacional. La adopción de Database Migration Service nos permitió aislar el riesgo: replicamos la base de datos de forma continua y desatendida hacia Cloud SQL, mientras el equipo de desarrollo construía y testeaba el nuevo backend en GCP apuntando ya a la que sería la base de datos definitiva.
Matriz Arquitectónica: Database Migration Service vs Enfoques Tradicionales
A la hora de diseñar una estrategia de migración hacia Google Cloud Platform, los arquitectos de sistemas deben comparar las opciones disponibles en función de la latencia tolerable, el impacto en la carga del servidor de producción y la gobernanza FinOps:
| Criterio Técnico | Volcado y Carga Manual (Dump / Restore) | Herramientas de Terceros (Replicadores Propietarios) | Google Cloud Database Migration Service (DMS) |
|---|---|---|---|
| Tiempo de Inactividad (Downtime) | Horas o días completos (proporcional al volumen de datos). | Bajo (minutos), pero requiere configuración manual compleja. | Mínimo (pocos minutos): Sólo el tiempo de cambiar el endpoint tras el drain de replicación. |
| Mecanismo de Replicación | Estático (instantánea sin sincronización posterior). | Agentes propietarios instalados en el host origen. | Nativo y Serverless: Protocolos estándar (CDC, WAL, Logical Replication) sin agentes intrusivos. |
| Modelo de Costes (FinOps) | Sin coste de licencia, pero altísimo coste operativo y de oportunidad. | Licencias muy costosas por CPU/Core más infraestructura de servidores réplica. | Coste de servicio base $0: Las migraciones homogéneas a Cloud SQL no tienen coste de servicio por DMS (solo la infra de destino). |
| Infraestructura de Gateway | Scripts Ad-hoc de transferencia de archivos. | Clústeres dedicados de VMs para procesar el streaming. | Serverless nativo: Gestionado íntegramente por Google Cloud sin servidores intermedios que administrar. |
| Facilidad de Rollback | Nula una vez iniciado el corte prolongado. | Media (requiere sincronización bidireccional compleja). | Alta: El origen sigue intacto y recibiendo escrituras hasta el minuto de la conmutación final. |
El Patrón "Dual-Track": Desacopla la Modernización del Backend de la Base de Datos
Uno de los mayores errores arquitectónicos consiste en asumir que la migración a la nube exige congelar el desarrollo de software. Cuando un equipo se enfrenta a la obsolescencia técnica —como migrar microservicios síncronos de Flask a frameworks de alto rendimiento asíncrono como FastAPI—, el patrón Dual-Track habilitado por DMS ofrece un flujo de trabajo elegante y seguro:
- Fase 1: Establecer la réplica continua en Cloud SQL. Se aprovisiona la instancia de destino en GCP y se arranca el job de Database Migration Service. El motor realiza el volcado inicial de esquema y tablas, y a continuación pasa a estado de replicación continua (CDC).
- Fase 2: Desarrollo y despliegue del nuevo backend en GCP. Mientras la base de datos on-premise sigue procesando las transacciones de los usuarios finales, el equipo de ingeniería despliega los nuevos microservicios en FastAPI sobre Cloud Run o GKE en la misma VPC de Google Cloud. Para mantener las mejores prácticas de seguridad sin quemar credenciales en variables de entorno, es prioritario inyectar credenciales y cadenas de conexión con Secret Manager en Cloud Run.
- Fase 3: Pruebas de integración sobre datos reales. Los desarrolladores pueden ejecutar tests de estrés, validar contratos de API y verificar la integridad de las consultas directamente contra la réplica viva de Cloud SQL (en modo de solo lectura o en una réplica clonada efímera), validando el rendimiento antes del pase a producción.
- Fase 4: Conmutación atómica (Cutover). En el momento programado, se cortan las conexiones entrantes al backend legacy, se espera unos segundos a que la latencia de replicación CDC en DMS llegue a 0 segundos, se promueve la instancia de Cloud SQL a primaria independiente y se redirige el tráfico hacia el nuevo backend FastAPI en GCP.
Para garantizar la robustez de este diseño, la instancia de base de datos nunca debe crearse con IP pública abierta. Es imprescindible aplicar Infraestructura como Código (IaC) para desplegar Cloud SQL en una VPC privada con Terraform utilizando conexiones peering privadas (Private Service Access).
Demostración Práctica: Migración de PostgreSQL / SQL Server con Database Migration Service
En el siguiente vídeo de nuestro canal oficial, Eduardo Martínez Agrelo detalla la arquitectura operativa, la configuración paso a paso de los perfiles de conexión en Google Cloud Console y la ejecución en vivo de una migración continua hacia Cloud SQL:
Topología de Red y Conectividad Segura entre On-Premise y GCP
Database Migration Service necesita conectarse bidireccionalmente con el motor de base de datos de origen. Dependiendo de los requerimientos de seguridad y la infraestructura corporativa existente, existen tres topologías principales de red:
- Cloud VPN / Cloud Interconnect (Recomendado para Enterprise): Conexión privada directa a nivel de capa 3 entre el centro de datos local y la Virtual Private Cloud (VPC) de Google Cloud. Permite que DMS alcance el servidor origen mediante su dirección IP privada interna sin tocar internet.
- Túnel SSH Reverso (Reverse SSH Tunnel): Si no existe un túnel IPsec establecido y la organización no desea abrir puertos en su firewall corporativo, se puede desplegar una máquina virtual intermedia (bastion host) en Compute Engine. El servidor origen inicia un túnel SSH saliente hacia el bastion, y DMS se conecta a través del puerto local redirigido.
- Listas de Control de Acceso por IP Pública y mTLS: Para bases de datos alojadas en otros proveedores cloud con IP pública, DMS proporciona un conjunto de rangos IP fijos que deben autorizarse en el firewall de origen, obligando a cifrar todo el canal mediante certificados SSL/TLS con validación mutua.
Durante la fase de validación de esquemas y comprobación de datos, los ingenieros de datos y DBAs necesitarán acceder a la nueva instancia en Google Cloud. En lugar de habilitar redes autorizadas o IPs públicas, la práctica recomendada es establecer la conexión administrativa segura mediante Cloud SQL Auth Proxy, autenticando a los usuarios con identidades corporativas de Cloud IAM.
Antipatrones Críticos y Consideraciones FinOps en Migraciones con DMS
⚠ Alerta Arquitectónica: Desbordamiento del Transaction Log (LDF) y Archivos WAL
En motores como SQL Server o PostgreSQL, la replicación lógica y CDC retienen los registros de transacciones no confirmadas en disco. Si se produce un corte de conectividad de red prolongado entre el on-premise y GCP mientras el job de DMS está en ejecución, el servidor de origen no podrá truncar su Transaction Log ni liberar los segmentos WAL. En bases de datos de alta transaccionalidad, esto puede saturar el almacenamiento local en pocas horas y derribar la base de datos de producción antes de que empiece la migración.
Para evitar contingencias y sobrecostes inesperados, asegúrate de aplicar estas salvaguardas arquitectónicas:
- Antipatrón 1: Triggers y Foreign Keys activas durante el volcado inicial. Si tu base de datos origen contiene triggers de auditoría que insertan registros en otras tablas con cada escritura, el proceso de carga masiva inicial puede duplicar datos o colapsar por bloqueos de contención. En migraciones de esquemas heterogéneas o personalizadas, los triggers deben deshabilitarse y reactivarse tras el snapshot inicial.
- Antipatrón 2: Infradimensionamiento de la instancia Cloud SQL de destino. Para acelerar la fase de Initial Dump & Load, configure temporalmente una máquina con alta capacidad de CPU, memoria y almacenamiento SSD provisionado (para maximizar IOPS). Una vez que la réplica CDC esté al día y estable, Cloud SQL permite escalar los recursos hacia el perfil óptimo de producción sin interrumpir el servicio.
-
Antipatrón 3: Ignorar la latencia de red en las estadísticas de replicación. DMS expone métricas en Cloud Monitoring como
replication_lag. Si la velocidad de generación de transacciones en el origen supera el ancho de banda del enlace de red hacia GCP, el lag crecerá en lugar de reducirse a cero, haciendo imposible un cutover limpio.
Protocolo de Cutover: El Check-List para la Conmutación en Menos de 5 Minutos
El objetivo último de Database Migration Service es comprimir la ventana de parada al mínimo absoluto. El día de la puesta en producción, el equipo de arquitectura y operaciones sigue esta secuencia milimétrica:
- Paso 1: Notificación y corte de escrituras en origen. Se detienen los servicios consumidores legacy (monolito Flask) o se coloca la base de datos origen en modo
READ ONLY. - Paso 2: Monitorización del Replication Lag a cero. Se verifica en la consola de DMS que el parámetro Replication Delay alcance los 0 segundos y que no existan transacciones pendientes en la cola CDC.
- Paso 3: Promover la réplica de Cloud SQL a instancia independiente. En la interfaz de DMS se pulsa "Promote" (o mediante comando
gcloud database-migration migration-jobs promote). En este instante, Cloud SQL desconecta la réplica lógica y asume el rol de base de datos maestra de lectura y escritura. - Paso 4: Conmutación de endpoints de aplicación. Se activan los nuevos microservicios en Cloud Run con FastAPI apuntando a la nueva IP privada de Cloud SQL. Si se utilizaba un registro DNS interno corporativo (Cloud DNS), se actualiza el registro CNAME hacia la nueva instancia.
- Paso 5: Activación de políticas de respaldo. Inmediatamente tras la promoción, se deben habilitar de forma estricta las políticas de resiliencia y Point-In-Time Recovery (PITR) en Cloud SQL para garantizar la recuperabilidad total ante cualquier error lógico posterior.
Código de Producción: Script de Verificación de Integridad Pre-Cutover
Antes de autorizar la promoción final en Cloud SQL, un Staff Architect debe verificar de forma determinista la concordancia de registros y sumas de verificación entre el origen y el destino. A continuación se presenta un script modular en Python para validar conteos y consistencia de tablas críticas:
"""
Módulo de Verificación de Integridad para Migraciones de BBDD a Google Cloud SQL.
Autor: Eduardo Martínez Agrelo - AI & Data Architect
Uso: Ejecutar durante la ventana previa al Cutover con origen en modo Read-Only.
"""
import sys
import logging
from typing import Dict, List, Tuple
import psycopg2
from dataclasses import dataclass
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger("migration_verifier")
@dataclass
class ConnectionConfig:
host: str
port: int
dbname: str
user: str
password: str
def get_table_checksums(config: ConnectionConfig, tables: List[str]) -> Dict[str, Tuple[int, str]]:
"""
Obtiene el recuento exacto de filas y un hash determinista por tabla.
Apto para motores PostgreSQL origen y Cloud SQL destino.
"""
results = {}
try:
conn = psycopg2.connect(
host=config.host,
port=config.port,
dbname=config.dbname,
user=config.user,
password=config.password,
connect_timeout=10
)
with conn.cursor() as cur:
for table in tables:
# Consulta parametrizada con control de recuento
query = f"SELECT COUNT(*) FROM {table};"
cur.execute(query)
row_count = cur.fetchone()[0]
results[table] = row_count
logger.info(f"[{config.host}] Tabla {table}: {row_count:,} registros")
conn.close()
return results
except Exception as e:
logger.error(f"Fallo al conectar o consultar {config.host}: {e}")
raise
def verify_migration_parity(source_cfg: ConnectionConfig, target_cfg: ConnectionConfig, tables: List[str]) -> bool:
"""Compara métricas de paridad entre base de datos origen y réplica Cloud SQL."""
logger.info("Iniciando auditoría de consistencia de datos pre-cutover...")
source_stats = get_table_checksums(source_cfg, tables)
target_stats = get_table_checksums(target_cfg, tables)
mismatches = []
for table in tables:
src_cnt = source_stats.get(table, -1)
tgt_cnt = target_stats.get(table, -2)
if src_cnt != tgt_cnt:
mismatches.append((table, src_cnt, tgt_cnt))
if mismatches:
logger.error("❌ ALERTA DE CORTE: Discrepancias detectadas en replicación:")
for table, src_cnt, tgt_cnt in mismatches:
logger.error(f" -> {table}: Origen={src_cnt} vs Destino={tgt_cnt} (Diff: {tgt_cnt - src_cnt})")
return False
logger.info("✅ PARIDAD PERFECTA: Todos los registros coinciden al 100%. Autorizado para Cutover.")
return True
if __name__ == "__main__":
# Configuración de entornos
SOURCE_DB = ConnectionConfig(
host="onprem-db.corp.internal",
port=5432,
dbname="enterprise_prod",
user="migration_audit_user",
password="SECURE_SOURCE_PASSWORD"
)
TARGET_CLOUDSQL = ConnectionConfig(
host="10.128.0.15", # IP Privada en VPC de GCP
port=5432,
dbname="enterprise_prod",
user="migration_audit_user",
password="SECURE_TARGET_PASSWORD"
)
CRITICAL_TABLES = ["users", "orders", "transactions", "invoices"]
is_ready = verify_migration_parity(SOURCE_DB, TARGET_CLOUDSQL, CRITICAL_TABLES)
if not is_ready:
sys.exit(1)
sys.exit(0)
