Migración de Cassandra a Bigtable con un proxy de doble escritura

1. Introducción

Bigtable es un servicio de base de datos NoSQL de alto rendimiento completamente administrado y diseñado para grandes cargas de trabajo analíticas y operativas. La migración de bases de datos existentes, como Apache Cassandra, a Bigtable a menudo requiere una planificación cuidadosa para minimizar el tiempo de inactividad y el impacto en la aplicación.

En este codelab, se muestra una estrategia de migración de Cassandra a Bigtable con una combinación de herramientas de proxy:

  1. Proxy de Cassandra-Bigtable: Permite que los clientes y las herramientas de Cassandra (como cqlsh o los controladores) interactúen con Bigtable usando el protocolo del lenguaje de consultas de Cassandra (CQL) a través de la traducción de consultas.
  2. Proxy de migración sin tiempo de inactividad (ZDM) de DataStax: Es un proxy de código abierto que se encuentra entre tu aplicación y tus servicios de bases de datos (Cassandra de origen y Bigtable de destino a través del proxy de Cassandra-Bigtable). Coordina las escrituras dobles y administra el enrutamiento del tráfico, lo que permite la migración con cambios mínimos en la aplicación y un tiempo de inactividad reducido.
  3. Cassandra Data Migrator (CDM): Es una herramienta de código abierto que se usa para migrar de forma masiva datos históricos del clúster de Cassandra de origen a la instancia de Bigtable de destino.

Qué aprenderás

  • Cómo configurar un clúster básico de Cassandra en Compute Engine
  • Cómo crear una instancia de Bigtable
  • Cómo implementar y configurar el proxy de Cassandra-Bigtable para asignar un esquema de Cassandra a Bigtable
  • Cómo implementar y configurar el proxy de ZDM de DataStax para escrituras dobles
  • Cómo usar la herramienta Cassandra Data Migrator para migrar de forma masiva los datos existentes
  • Flujo de trabajo general para una migración de Cassandra a Bigtable basada en proxy.

Requisitos

  • Un proyecto de Google Cloud con facturación habilitada. Los usuarios nuevos pueden acceder a una prueba gratuita.
  • Conocimiento básico de los conceptos de Google Cloud, como proyectos, Compute Engine, redes de VPC y reglas de firewall Tener conocimientos básicos sobre las herramientas de línea de comandos de Linux
  • Acceso a una máquina con la CLI de gcloud instalada y configurada, o bien usa Google Cloud Shell.

En este codelab, usaremos principalmente máquinas virtuales (VMs) en Compute Engine dentro de la misma red y región de VPC para simplificar las redes. Se recomienda usar direcciones IP internas.

2. Configura tu entorno

1. Selecciona o crea un proyecto de Google Cloud

Navega a Google Cloud Console y selecciona un proyecto existente o crea uno nuevo. Anota tu ID del proyecto.

2. Elige una región y una zona

Selecciona una región y una zona para tus recursos. Usaremos us-central1 y us-central1-c como ejemplos. Para mayor comodidad, define estas variables como variables de entorno:

export PROJECT_ID="<your-project-id>"
export REGION="us-central1"
export ZONE="us-central1-c"

gcloud config set project $PROJECT_ID
gcloud config set compute/region $REGION
gcloud config set compute/zone $ZONE

3. Habilita las API obligatorias

Asegúrate de que la API de Compute Engine y la API de Bigtable estén habilitadas para tu proyecto.

gcloud services enable compute.googleapis.com bigtable.googleapis.com bigtableadmin.googleapis.com

4. Configura reglas de firewall

Debemos permitir la comunicación entre nuestras VMs dentro de la red de VPC predeterminada en varios puertos:

  • Puerto CQL de Cassandra/Proxies: 9042
  • Puerto de verificación de estado del proxy de ZDM: 14001
  • SSH: 22

Crea una regla de firewall para permitir el tráfico interno en estos puertos. Usaremos una etiqueta cassandra-migration para aplicar fácilmente esta regla a las VMs pertinentes.

gcloud compute firewall-rules create allow-migration-internal \
--network=default \
--action=ALLOW \
--rules=tcp:22,tcp:9042,tcp:7000,tcp:14001 \
--source-ranges=10.0.0.0/8 \
--target-tags=cassandra-migration

3. Implementa el clúster de Cassandra (origen)

En este codelab, configuraremos un clúster de Cassandra simple de un solo nodo en Compute Engine. En una situación real, te conectarías a tu clúster existente.

1. Crea una VM de GCE para Cassandra

gcloud compute instances create cassandra-origin \
--machine-type=e2-medium \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--tags=cassandra-migration \
--boot-disk-size=20GB \
--scopes=cloud-platform \
--zone="$ZONE"

Establece una conexión SSH a tu instancia de Cassandra

gcloud compute ssh --zone="$ZONE" "cassandra-origin"

2. Instala Cassandra

# Install Java (Cassandra dependency)
sudo apt-get update
sudo apt-get install -y openjdk-11-jre-headless

# Add Cassandra repository
echo "deb https://debian.cassandra.apache.org 41x main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list
curl https://downloads.apache.org/cassandra/KEYS | sudo apt-key add -

# Install Cassandra
sudo apt update
sudo apt install -y cassandra

# (Optional) Verify Cassandra is running
sudo systemctl status cassandra

3. Configura Cassandra

Debemos configurar Cassandra para que sea accesible dentro de la red privada.

Ejecuta el siguiente comando para obtener la IP privada de cassandra-origin:

hostname -I

Edita la configuración de Cassandra. No deberías tener que agregar ninguna línea de configuración nueva, solo actualizar las que ya están allí:

sudo vim /etc/cassandra/cassandra.yaml
  1. Configura seed_provider.parameters.seeds en "CASSANDRA_ORIGIN_PRIVATE_IP:7000".
  2. Configura rpc_address en CASSANDRA_ORIGIN_PRIVATE_IP.
  3. Configura listen_address en CASSANDRA_ORIGIN_PRIVATE_IP.

Guarda el archivo.

Por último, reinicia Cassandra para cargar los cambios de configuración:

sudo systemctl restart cassandra

# (Optional) Verify Cassandra is running
sudo systemctl status cassandra

4. Crea un espacio de claves y una tabla

Usaremos un ejemplo de tabla de empleados y crearemos un espacio de claves llamado "zdmbigtable".

Nota: Es posible que Cassandra tarde un minuto en comenzar a aceptar conexiones.

# Start cqlsh
cqlsh $(hostname -I)

Dentro de cqlsh, haz lo siguiente:

-- Create keyspace (adjust replication for production)
CREATE KEYSPACE zdmbigtable WITH replication = {'class':'SimpleStrategy', 'replication_factor':1};

-- Use the keyspace
USE zdmbigtable;

-- Create the employee table
CREATE TABLE employee (
    name text PRIMARY KEY,
    age bigint,
    code int,
    credited double,
    balance float,
    is_active boolean,
    birth_date timestamp
);

-- Exit cqlsh
EXIT;

Deja abierta la sesión de SSH o anota la dirección IP de esta VM (hostname -I).

4. Configura Bigtable (destino)

Duración: 0:01

Crear una instancia de Bigtable. Usaremos zdmbigtable como el ID de la instancia.

gcloud bigtable instances create zdmbigtable \
--display-name="ZDM Bigtable Target" \
--cluster="bigtable-c1" \
--cluster-zone="$ZONE" \
--cluster-num-nodes=1 # Use 1 node for dev/testing; scale as needed

El script de configuración del proxy de Cassandra-Bigtable creará la tabla de Bigtable más adelante.

5. Configura el proxy de Cassandra-Bigtable

1. Crea una VM de Compute Engine para el proxy de Cassandra-Bigtable

gcloud iam service-accounts create bigtable-proxy-sa \
    --description="Service account for Bigtable Proxy access" \
    --display-name="Bigtable Proxy Access SA"

export BIGTABLE_PROXY_SA_EMAIL=$(gcloud iam service-accounts list --filter="displayName='Bigtable Proxy Access SA'" --format="value(email)")

gcloud bigtable instances add-iam-policy-binding zdmbigtable \
  --member="serviceAccount:$BIGTABLE_PROXY_SA_EMAIL" \
  --role="roles/bigtable.admin"

gcloud compute instances create bigtable-proxy-vm \
--machine-type=e2-medium \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--tags=cassandra-migration \
--boot-disk-size=20GB \
--zone=$ZONE \
--scopes=cloud-platform \
--service-account="$BIGTABLE_PROXY_SA_EMAIL"

Establece una conexión SSH a bigtable-proxy-vm:

gcloud compute ssh --zone="$ZONE" "bigtable-proxy-vm"

En bigtable-proxy-vm, ejecuta lo siguiente:

# Install Git and Go
sudo apt-get update
sudo apt-get install -y git

wget https://go.dev/dl/go1.23.6.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.23.6.linux-amd64.tar.gz

echo 'export GOPATH=$HOME/go' >> ~/.profile
echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> ~/.profile
source ~/.profile

# Clone the proxy repository
git clone https://github.com/GoogleCloudPlatform/cloud-bigtable-ecosystem.git
cd cloud-bigtable-ecosystem/cassandra-bigtable-migration-tools/cassandra-bigtable-proxy/

2. Inicia el proxy de Cassandra-Bigtable

Inicia el servidor proxy.

# At the root of the cassandra-to-bigtable-proxy directory
go run proxy.go --project-id="$(gcloud config get-value project)" --instance-id=zdmbigtable --keyspace-id=zdmbigtable --rpc-address=$(hostname -I)

El proxy se iniciará y escuchará en el puerto 9042 las conexiones CQL entrantes. Mantén en ejecución esta sesión de la terminal. Anota la dirección IP de esta VM (hostname -I).

3. Crea una tabla a través de CQL

Conecta CQLSH a la dirección IP de la VM del proxy de Cassandra-Bigtable. Para encontrar la dirección IP, ejecuta el siguiente comando de forma local:

gcloud compute instances describe bigtable-proxy-vm --format='get(networkInterfaces[0].networkIP)'

En una ventana separada, conéctate a tu VM cassandra-origin con SSH y usa cqlsh en bigtable-proxy. Ten en cuenta que establecimos un tiempo de espera de solicitud más largo que el predeterminado para garantizar que Bigtable tenga tiempo suficiente para crear la tabla subyacente. Deberías ver el mensaje "Connected to cassandra-bigtable-proxy-v0.2.3" o uno similar, que indica que te conectaste al proxy de Bigtable y no al servidor local de Cassandra.

# Replace <your-bigtable-proxy-vm-ip> with the ip from the above command
export BIGTABLE_PROXY_IP=<your-bigtable-proxy-vm-ip>
cqlsh --request-timeout=60 $BIGTABLE_PROXY_IP
-- Create the employee table
CREATE TABLE zdmbigtable.employee (
    name text PRIMARY KEY,
    age bigint,
    code int,
    credited double,
    balance float,
    is_active boolean,
    birth_date timestamp
);

En CQLSH, verifica que se haya creado la tabla ejecutando el siguiente comando:

DESC TABLE zdmbigtable.employee;

6. Configura el proxy de ZDM

Crearemos una sola instancia del proxy de ZDM para este lab, pero te recomendamos que uses una configuración de varios nodos para una migración de producción.

1. Crea la VM del proxy de ZDM

gcloud compute instances create zdm-proxy-vm \
--machine-type=e2-medium \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--tags=cassandra-migration \
--boot-disk-size=20GB \
--scopes=cloud-platform \
--zone=$ZONE

Anota las direcciones IP de ambas VMs.

2. Prepara el proxy de ZDM

gcloud compute ssh --zone="$ZONE" zdm-proxy-vm
export ZDM_VERSION="2.3.4"
wget "https://github.com/datastax/zdm-proxy/releases/download/v$ZDM_VERSION/zdm-proxy-linux-amd64-v$ZDM_VERSION.tgz"
tar -xvzf "zdm-proxy-linux-amd64-v$ZDM_VERSION.tgz"

# replace YOUR_ZONE
gcloud config set compute/zone "YOUR_ZONE"
export ZDM_ORIGIN_CONTACT_POINTS=$(gcloud compute instances describe cassandra-origin --format='get(networkInterfaces[0].networkIP)') 
export ZDM_TARGET_CONTACT_POINTS=$(gcloud compute instances describe bigtable-proxy-vm --format='get(networkInterfaces[0].networkIP)')
export ZDM_ORIGIN_USERNAME=""
export ZDM_ORIGIN_PASSWORD=""
export ZDM_TARGET_USERNAME=""
export ZDM_TARGET_PASSWORD=""
export ZDM_PROXY_LISTEN_ADDRESS=0.0.0.0
export ZDM_PROXY_LISTEN_PORT=9042
./zdm-proxy-v${ZDM_VERSION}

7. Configura la aplicación y comienza las escrituras duales

Duración: 0:05

En esta etapa de una migración real, volverías a configurar tus aplicaciones para que apunten a la dirección IP de la VM del proxy de ZDM (p.ej., :9042) en lugar de conectarse directamente a Cassandra.

Una vez que la aplicación se conecta al proxy de ZDM, las lecturas se publican desde el origen (Cassandra) de forma predeterminada. Las escrituras se envían tanto al origen (Cassandra) como al destino (Bigtable, a través del proxy de Cassandra-Bigtable). Esto permite que tu aplicación siga funcionando con normalidad y, al mismo tiempo, garantiza que los datos nuevos se escriban en ambas bases de datos de forma simultánea. Puedes probar la conexión con cqlsh apuntando al proxy de ZDM:

cqlsh $(gcloud compute instances describe zdm-proxy-vm --format='get(networkInterfaces[0].networkIP)')

Intenta insertar algunos datos:

INSERT INTO zdmbigtable.employee (name, age, is_active) VALUES ('Alice', 30, true); 
INSERT INTO zdmbigtable.employee (name, age, is_active) VALUES ('Anna', 45, true); 
INSERT INTO zdmbigtable.employee (name, age, is_active) VALUES ('Albert', 50, false); 
SELECT * FROM zdmbigtable.employee;

Estos datos se deben escribir en Cassandra y Bigtable. Puedes confirmar esto en Bigtable. Para ello, ve a la consola de Google Cloud y abre el editor de consultas de Bigtable para tu instancia. Ejecuta una consulta "SELECT * FROM employee" y los datos insertados recientemente deberían estar visibles.

8. Migra datos históricos con Cassandra Data Migrator

Ahora que las escrituras duales están activas para los datos nuevos, usa la herramienta Cassandra Data Migrator (CDM) para copiar los datos históricos existentes de Cassandra a Bigtable.

1. Crea una VM de Compute Engine para el CDM

Esta VM necesita suficiente memoria para Spark.

gcloud compute instances create cdm-migrator-vm \
--machine-type=e2-medium \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--tags=cassandra-migration \
--boot-disk-size=40GB \
--scopes=cloud-platform \
--zone=$ZONE

2. Instala los requisitos previos (Java 11 y Spark)

Establece una conexión SSH a cdm-migrator-vm:

gcloud compute ssh cdm-migrator-vm

Dentro de la VM:

# Install Java 11 
sudo apt-get update 
sudo apt-get install -y openjdk-11-jdk
 
# Verify Java installation 
java -version 

# Download and Extract Spark (Using version 3.5.3 as requested) 
# Check the Apache Spark archives for the correct URL if needed

wget  https://archive.apache.org/dist/spark/spark-3.5.3/spark-3.5.3-bin-hadoop3-scala2.13.tgz
tar -xvzf spark-3.5.3-bin-hadoop3-scala2.13.tgz

echo 'export SPARK_HOME=$PWD/spark-3.5.3-bin-hadoop3-scala2.13' >> ~/.profile
echo 'export PATH=$PATH:$SPARK_HOME/bin' >> ~/.profile
source ~/.profile

3. Descarga Cassandra Data Migrator

En tu navegador, abre la página de paquetes de CDM y copia el vínculo .jar del panel Assets. Si la versión 5.4.0 no está disponible, elige la versión más cercana. Pega el vínculo en el siguiente comando y ejecútalo en tu instancia de cdm-migrator-vm, conservando las comillas simples alrededor de la URL.

wget 'JAR_URL_GOES_HERE' -O cassandra-data-migrator.jar

Verifica que el archivo .jar se haya descargado correctamente analizándolo con la herramienta jar. Deberías ver una larga lista de archivos ".class".

jar tf cassandra-data-migrator.jar 

4. Agrega algunos datos

Debemos agregar algunos datos para migrar escribiendo directamente en cassandra-origin (no en zdm-proxy-vm).

INSERT INTO zdmbigtable.employee (name, age, is_active) VALUES ('Alfred', 67, true); 
INSERT INTO zdmbigtable.employee (name, age, is_active) VALUES ('Bobby', 12, false); 
INSERT INTO zdmbigtable.employee (name, age, is_active) VALUES ('Carol', 29, true); 

5. Ejecuta el trabajo de migración

Ejecuta la migración con spark-submit. Este comando le indica a Spark que ejecute el archivo .jar del CDM, usando tu archivo de propiedades y especificando el espacio de claves y la tabla que se migrarán. Ajusta la configuración de memoria (–driver-memory, –executor-memory) según el tamaño de tu VM y el volumen de datos.

Asegúrate de estar en el directorio que contiene el archivo .jar y el archivo de propiedades del CDM.

Sugerencia: Puedes obtener la IP interna de tus VMs de Cassandra y proxy ejecutando estos comandos desde tu máquina local:

gcloud compute instances describe cassandra-origin --format='get(networkInterfaces[0].networkIP)'
gcloud compute instances describe bigtable-proxy-vm --format='get(networkInterfaces[0].networkIP)'
export ORIGIN_HOST="<your-cassandra-origin-ip>"
export TARGET_HOST="<your-bigtable-proxy-vm-ip>"
export KEYSPACE_TABLE="zdmbigtable.employee"
spark-submit --verbose --master "local[*]" \
--driver-memory 3G --executor-memory 3G \
--conf spark.cdm.schema.origin.keyspaceTable="$KEYSPACE_TABLE" \
--conf spark.cdm.connect.origin.host="$ORIGIN_HOST" \
--conf spark.cdm.connect.origin.port=9042 \
--conf spark.cdm.connect.target.host="$TARGET_HOST" \
--conf spark.cdm.connect.target.port=9042 \
--conf spark.cdm.feature.origin.ttl.automatic=false \
--conf spark.cdm.feature.origin.writetime.automatic=false \
--conf spark.cdm.feature.target.ttl.automatic=false \
--conf spark.cdm.feature.target.writetime.automatic=false \
--conf spark.cdm.schema.origin.column.ttl.automatic=false \
--conf spark.cdm.schema.ttlwritetime.calc.useCollections=false \
--class com.datastax.cdm.job.Migrate cassandra-data-migrator.jar

6. Verifica la migración de datos

Una vez que el trabajo del CDM se complete correctamente, verifica que los datos históricos existan en Bigtable.

cqlsh <bigtable-proxy-vm-ip>

Dentro de cqlsh, haz lo siguiente:

SELECT COUNT(*) FROM zdmbigtable.employee; -- Check row count matches origin 
SELECT * FROM zdmbigtable.employee LIMIT 10; -- Check some sample data

9. Migración de sistemas (conceptual)

Después de verificar exhaustivamente la coherencia de los datos entre Cassandra y Bigtable, puedes continuar con la migración final.

Con el proxy de ZDM, el corte implica reconfigurarlo para que lea principalmente desde el destino (Bigtable) en lugar del origen (Cassandra). Por lo general, esto se hace a través de la configuración del proxy de ZDM, lo que desplaza de manera efectiva el tráfico de lectura de tu aplicación a Bigtable.

Una vez que te asegures de que Bigtable entrega todo el tráfico correctamente, puedes hacer lo siguiente:

  • Detén las escrituras dobles reconfigurando el proxy de ZDM.
  • Retira el clúster original de Cassandra.
  • Quita el proxy de ZDM y haz que la aplicación se conecte directamente al proxy de Cassandra-Bigtable o usa el cliente de CQL nativo de Bigtable para Java.

Los detalles específicos de la reconfiguración del proxy de ZDM para la migración están fuera del alcance de este codelab básico, pero se detallan en la documentación de ZDM de DataStax.

10. Limpia

Para evitar que se generen cargos, borra los recursos que creaste durante este codelab.

1. Borra VMs de Compute Engine

gcloud compute instances delete cassandra-origin zdm-proxy-vm bigtable-proxy-vm cdm-migrator-vm --zone=$ZONE --quiet

2. Borra la instancia de Bigtable

gcloud bigtable instances delete zdmbigtable

3. Cómo borrar reglas de firewall

gcloud compute firewall-rules delete allow-migration-internal

4. Borra la base de datos de Cassandra (si está instalada de forma local o persistente)

Si instalaste Cassandra fuera de una VM de Compute Engine creada aquí, sigue los pasos correspondientes para quitar los datos o desinstalar Cassandra.

11. ¡Felicitaciones!

Completaste con éxito el proceso de configuración de una ruta de migración basada en proxy de Apache Cassandra a Bigtable.

Aprendiste todo esto:

Implementa Cassandra y Bigtable.

  • Configura el proxy de Cassandra-Bigtable para la compatibilidad con CQL.
  • Implementa el proxy de ZDM de DataStax para administrar las escrituras dobles y el tráfico.
  • Usa Cassandra Data Migrator para mover datos históricos.

Este enfoque permite realizar migraciones con un tiempo de inactividad mínimo y sin cambios en el código, ya que aprovecha la capa de proxy.

Próximos pasos

  • Explora la documentación de Bigtable
  • Consulta la documentación de Datastax ZDM Proxy para conocer las configuraciones avanzadas y los procedimientos de migración.
  • Revisa el repositorio de Cassandra-Bigtable Proxy para obtener más detalles.
  • Consulta el repositorio de Cassandra Data Migrator para conocer el uso avanzado.
  • Prueba otros codelabs de Google Cloud