Programa exportaciones de bases de datos de Memorystore para Redis con Cloud Scheduler

En este instructivo, se muestra cómo usar Cloud Scheduler y Cloud Functions para exportar de manera automática una base de datos de Memorystore para Redis a Cloud Storage. Tener exportaciones de bases de datos en Cloud Storage te permite crear un plan sólido y diverso de recuperación ante desastres. Por ejemplo, puedes exportar a una región diferente y, luego, importar a otras instancias de Memorystore para Redis.

Arquitectura

En este instructivo, se incluyen los siguientes componentes de Google Cloud:

Un trabajo de Cloud Scheduler publica un mensaje en un tema de Pub/Sub con información sobre el ID de instancia de Memorystore, el ID del proyecto, la región donde se encuentra y la ubicación de Cloud Storage en la que se almacenará la copia de seguridad. Este evento activa una Cloud Function que obtiene esta carga útil y comienza una exportación de base de datos en Memorystore para Redis a través de su API. La base de datos genera la exportación y la guarda en Cloud Storage. En el siguiente diagrama, se muestra este flujo de trabajo.

Flujo de trabajo de Cloud Scheduler a Pub/Sub, que activa una Cloud Function que inicia la exportación.

Objetivos

Costos

En este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud sean aptos para obtener una prueba gratuita.

Cuando finalices este instructivo, podrás borrar los recursos creados para evitar que se te siga facturando. Para obtener más información, consulta cómo hacer una limpieza.

Antes de comenzar

  1. En la página del selector de proyectos de Google Cloud Console, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyecto

  2. Comprueba que la facturación esté habilitada en tu proyecto.

    Descubre cómo puedes habilitar la facturación

  3. En Cloud Console, activa Cloud Shell.

    Activar Cloud Shell

  4. Habilita las API de Memorystore para Redis, Cloud Functions, Cloud Scheduler y App Engine.

    Habilita las API

A lo largo de este instructivo, ejecutarás todos los comandos desde Cloud Shell.

Configura tu entorno

Para comenzar, primero configura tu entorno y, luego, crea funciones personalizadas que tengan los permisos necesarios para este instructivo.

  1. En Cloud Shell, configura las siguientes variables de entorno:

    export PROJECT_ID=`gcloud config get-value project`
    export DEMO="mem-exporter"
    export BUCKET_NAME=${USER}-mem-$(date +%s)
    export MEM_INSTANCE="${DEMO}-instance"
    export GCF_NAME="${DEMO}-gcf"
    export PUBSUB_TOPIC="${DEMO}-topic"
    export SCHEDULER_JOB="${DEMO}-job"
    export MEM_ROLE="memExporter"
    export STORAGE_ROLE="simpleStorageRole"
    export REGION="us-central1"
    
  2. Crea dos funciones personalizadas que solo tengan los permisos necesarios para este instructivo:

    gcloud iam roles create ${STORAGE_ROLE} --project=${PROJECT_ID} \
        --title="Simple Storage Role" \
        --description="Grant permissions to view and create objects in Cloud Storage" \
        --permissions="storage.objects.create,storage.buckets.get"
    
    gcloud iam roles create ${MEM_ROLE} --project=${PROJECT_ID} \
        --title="Memorystore Exporter Role" \
        --description="Grant permissions to export data from a Memorystore instance to a Cloud Storage bucket" \
        --permissions="redis.instances.export"
    

    Estas funciones reducen el permiso de acceso de las cuentas de servicio de Cloud Functions y Memorystore, según el principio de privilegio mínimo.

Crea un bucket de Cloud Storage y una instancia de Memorystore

En esta sección, primero debes crear un bucket de Cloud Storage y una instancia de Memorystore para Redis. Luego, propagas los datos de muestra con Memorystore.

Crea un bucket de Cloud Storage

Usa la herramienta de línea de comandos de gsutil para crear un bucket de Cloud Storage.

  • Crea un bucket de Cloud Storage en el que desees guardar las exportaciones de datos:

    gsutil mb -l ${REGION} gs://${BUCKET_NAME}
    

Crea una instancia de Memorystore y otorga permisos a su cuenta de servicio

A continuación, debes crear una instancia de Memorystore y otorgarle a su cuenta de servicio los permisos para exportar datos a Cloud Storage.

  1. Crea una instancia de Memorystore para Redis 4 como sigue:

    gcloud redis instances create ${MEM_INSTANCE} --size=1 --region=${REGION}
    

    Esta operación tardará unos minutos en completarse.

  2. Verifica que la instancia de Memorystore sea READY:

    gcloud redis instances list --region=${REGION}
    

    El resultado es similar al siguiente:

    INSTANCE_NAME   VERSION    REGION       TIER   SIZE_GB  HOST          PORT  NETWORK  RESERVED_IP      STATUS  CREATE_TIME
    redis-instance  REDIS_4_0  us-central1  BASIC  1        10.61.20.131  6379  default  10.61.20.128/29  READY   2020-04-23T18:38:54
    
  3. Otorga a tu cuenta de servicio de Memorystore los permisos para exportar datos a Cloud Storage con la función de almacenamiento simple como sigue:

    export MEM_SA=$(gcloud redis instances describe ${MEM_INSTANCE} --region ${REGION} \
        --project ${PROJECT_ID} \
        --format "value(persistenceIamIdentity)")
    
    gsutil iam ch ${MEM_SA}:projects/${PROJECT_ID}/roles/${STORAGE_ROLE} gs://${BUCKET_NAME}
    

Crea un tema de Pub/Sub, una Cloud Function y un trabajo de Cloud Scheduler

En esta sección, debes crear una cuenta de servicio personalizada y vincularla a la función de Redis personalizada que creas. Luego, crea un tema de Pub/Sub que se usa para activar la ejecución de una función de Cloud Functions. También creas un trabajo de Cloud Scheduler para ejecutar de forma periódica la función de exportación de datos.

Crea una cuenta de servicio para la función de Cloud Functions

El primer paso es crear una cuenta de servicio personalizada y vincularla a la función de Redis personalizada que creas.

  1. Crea una cuenta de servicio de IAM para que la Cloud Function la use y guárdala en la siguiente variable:

    gcloud iam service-accounts create ${GCF_NAME} \
        --display-name="Service Account for GCF and Memorystore"
    
    export GCF_SA=$(gcloud iam service-accounts list --filter="${GCF_NAME}" --format="value(email)")
    
  2. Otorga a la cuenta de servicio de Cloud Functions acceso a la función de Redis personalizada:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${GCF_SA}" \
        --role="projects/${PROJECT_ID}/roles/${MEM_ROLE}"
    
  3. Otorga a la cuenta de servicio de Cloud Functions acceso a la función de almacenamiento personalizada como sigue:

    gsutil iam ch \
        serviceAccount:${GCF_SA}:projects/${PROJECT_ID}/roles/${STORAGE_ROLE} \
        gs://${BUCKET_NAME}
    

Crea un tema de Pub/Sub

El siguiente paso es crear un tema de Pub/Sub que se use para activar la Cloud Function que interactúa con la base de datos de Memorystore.

  • Crea el tema de Pub/Sub:

    gcloud pubsub topics create ${PUBSUB_TOPIC}
    

Crea una función de Cloud Functions

A continuación, crea la Cloud Function.

  1. Crea una carpeta para el código de la Cloud Function:

    mkdir scheduler_gcf_code && cd scheduler_gcf_code
    
  2. Para crear un archivo main.py, pega lo siguiente en Cloud Shell:

    cat <<EOF  > main.py
    
    import base64
    import logging
    import json
    
    from datetime import datetime
    from httplib2 import Http
    
    from googleapiclient import discovery
    from googleapiclient.errors import HttpError
    from oauth2client.client import GoogleCredentials
    
    def main(event, context):
        pubsub_message = json.loads(base64.b64decode(event['data']).decode('utf-8'))
        credentials = GoogleCredentials.get_application_default()
    
        service = discovery.build('redis', 'v1beta1', http=credentials.authorize(Http()), cache_discovery=False)
    
        datestamp = datetime.now().strftime("%Y%m%d%H%M") # format timestamp: YearMonthDayHourMinute
        uri = f"{pubsub_message['gs']}/backup-{datestamp}.rdb"
    
        request_body = {
            "outputConfig": {
                "gcsDestination" : {
                    "uri": uri
                }
            }
        }
    
        try:
            request = service.projects().locations().instances().export(
                name=pubsub_message['name'],
                body=request_body
            )
    
            response = request.execute()
        except HttpError as err:
            logging.error(f"Could NOT run backup. Reason: {err}")
        else:
            logging.info(f"Backup task status: {response}")
    EOF
    
  3. Para crear un archivo requirements.txt, pega lo siguiente en Cloud Shell:

    cat <<EOF > requirements.txt
    
    google-api-python-client
    Oauth2client
    EOF
    
  4. Implementa el código. Cuando se te pregunte si deseas permitir invocaciones no autenticadas de la función nueva, responde no.

    gcloud functions deploy ${GCF_NAME} \
        --trigger-topic=${PUBSUB_TOPIC} \
        --runtime=python37 \
        --entry-point=main \
        --service-account=${GCF_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
    

Crea un trabajo de Cloud Scheduler

Por último, crea un trabajo de Cloud Scheduler para ejecutar de forma periódica la función de exportación de datos.

  1. Crea una instancia de App Engine para el trabajo de Cloud Scheduler:

    gcloud app create --region=${REGION::-1}
    
  2. Guarda el nombre completo de Memorystore en una variable:

    export MEM_NAME=$(gcloud redis instances describe ${MEM_INSTANCE} --region ${REGION} --format "value(name)")
    
  3. Crea un trabajo de Cloud Scheduler para ejecutar de forma periódica la función de exportación de datos:

    gcloud scheduler jobs create pubsub ${SCHEDULER_JOB} \
        --schedule='0 23 * * *' --topic=${PUBSUB_TOPIC} \
        --message-body='{"name":'\"${MEM_NAME}\"',"gs":'\"gs://${BUCKET_NAME}\"'}' \
        --time-zone='America/Los_Angeles'
    

    Este trabajo está programado para ejecutarse a las 11:00 p.m. todos los días.

Prueba tu solución

El último paso es probar la solución. Para comenzar, ejecuta el trabajo de Cloud Scheduler.

  1. Ejecuta el trabajo de Cloud Scheduler de forma manual para activar la exportación de Memorystore de tu base de datos.

    gcloud scheduler jobs run ${SCHEDULER_JOB}
    
  2. Enumera las operaciones realizadas en la instancia de Memorystore y verifica que haya una operación del tipo EXPORT:

    gcloud redis operations list --region=${REGION} --filter="${MEM_INSTANCE}"
    

    El resultado muestra un trabajo de exportación completado, por ejemplo:

    OPERATION_NAME                                           REGION       TYPE    TARGET                 DONE  CREATE_TIME          DURATION
    operation-1592329364987-5a837122a600c-b22c2703-5077c6b7  us-central1  export  mem-exporter-instance  True  2020-06-16T17:42:45  16S
    
  3. Verifica el bucket de Cloud Storage para ver si se creó el archivo de exportación:

    gsutil ls gs://${BUCKET_NAME} | grep rdb
    

    Verás un archivo llamado backup-mem-timestamp.rdb después de que la operación STATUS del paso anterior muestre DONE.

Realice una limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo. La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

  1. En Cloud Console, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

¿Qué sigue?