Conectarse a una instancia de Redis desde un servicio de Cloud Run

Puedes conectarte a una instancia de Redis desde Cloud Run mediante la salida directa de VPC.

Configuración

Si ya has instalado la CLI de Google Cloud y has creado una instancia de Redis, puedes saltarte estos pasos.

  1. Instala gcloud CLI e inicialízala:

    gcloud init
    
  2. Sigue la guía de inicio rápido para crear una instancia de Redis. Anota la zona, la dirección IP y el puerto de la instancia de Redis.

Preparar la salida de la red VPC para la configuración

Para conectarte a tu instancia de Redis, tu servicio de Cloud Run debe tener acceso a la red VPC autorizada de la instancia de Redis.

Para encontrar el nombre de esta red, ejecuta el siguiente comando:

    gcloud redis instances describe INSTANCE_ID --region REGION --format "value(authorizedNetwork)"

Anota el nombre de la red.

Aplicación de ejemplo

Esta aplicación de servidor HTTP de ejemplo establece una conexión con una instancia de Redis desde un servicio de Cloud Run.

Clona el repositorio del lenguaje de programación que hayas elegido y ve a la carpeta que contiene el código de ejemplo:

Go

git clone https://github.com/GoogleCloudPlatform/golang-samples
cd golang-samples/memorystore/redis

Node.js

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples
cd nodejs-docs-samples/memorystore/redis

Python

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/memorystore/redis

Esta aplicación de ejemplo incrementa un contador de Redis cada vez que se accede al endpoint /.

Go

Esta aplicación usa el cliente de github.com/gomodule/redigo/redis. Para instalarlo, ejecuta el siguiente comando:

go get github.com/gomodule/redigo/redis

// Command redis is a basic app that connects to a managed Redis instance.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/gomodule/redigo/redis"
)

var redisPool *redis.Pool

func incrementHandler(w http.ResponseWriter, r *http.Request) {
	conn := redisPool.Get()
	defer conn.Close()

	counter, err := redis.Int(conn.Do("INCR", "visits"))
	if err != nil {
		http.Error(w, "Error incrementing visitor counter", http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, "Visitor number: %d", counter)
}

func main() {
	redisHost := os.Getenv("REDISHOST")
	redisPort := os.Getenv("REDISPORT")
	redisAddr := fmt.Sprintf("%s:%s", redisHost, redisPort)

	const maxConnections = 10
	redisPool = &redis.Pool{
		MaxIdle: maxConnections,
		Dial:    func() (redis.Conn, error) { return redis.Dial("tcp", redisAddr) },
	}

	http.HandleFunc("/", incrementHandler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

Node.js

Esta aplicación usa el módulo redis.

{
  "name": "memorystore-redis",
  "description": "An example of using Memorystore(Redis) with Node.js",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": ">=16.0.0"
  },
  "dependencies": {
    "redis": "^4.0.0"
  }
}

'use strict';
const http = require('http');
const redis = require('redis');

const REDISHOST = process.env.REDISHOST || 'localhost';
const REDISPORT = process.env.REDISPORT || 6379;

const client = redis.createClient(REDISPORT, REDISHOST);
client.on('error', err => console.error('ERR:REDIS:', err));

// create a server
http
  .createServer((req, res) => {
    // increment the visit counter
    client.incr('visits', (err, reply) => {
      if (err) {
        console.log(err);
        res.status(500).send(err.message);
        return;
      }
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end(`Visitor number: ${reply}\n`);
    });
  })
  .listen(8080);

Python

Esta aplicación usa Flask para el servicio web y el paquete redis-py para comunicarse con la instancia de Redis.

Flask==3.0.3
gunicorn==23.0.0
redis==6.0.0
Werkzeug==3.0.3
import logging
import os

from flask import Flask
import redis

app = Flask(__name__)

redis_host = os.environ.get("REDISHOST", "localhost")
redis_port = int(os.environ.get("REDISPORT", 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port)


@app.route("/")
def index():
    value = redis_client.incr("counter", 1)
    return f"Visitor number: {value}"


@app.errorhandler(500)
def server_error(e):
    logging.exception("An error occurred during a request.")
    return (
        """
    An internal error occurred: <pre>{}</pre>
    See logs for full stacktrace.
    """.format(
            e
        ),
        500,
    )


if __name__ == "__main__":
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine and Cloud Run.
    # See entrypoint in app.yaml or Dockerfile.
    app.run(host="127.0.0.1", port=8080, debug=True)

Desplegar la aplicación en Cloud Run

Para desplegar la aplicación, sigue estos pasos:

  1. Copia el Dockerfile en el directorio de origen:

    cp cloud_run_deployment/Dockerfile .
    
  2. Crea una imagen de contenedor con Cloud Build ejecutando el siguiente comando:

    gcloud builds submit --tag gcr.io/PROJECT_ID/visit-count
    
  3. Despliega el contenedor en Cloud Run ejecutando el siguiente comando:

        gcloud run deploy \
        --image gcr.io/PROJECT_ID/visit-count \
        --allow-unauthenticated \
        --region REGION \
        --network NETWORK \
        --subnet SUBNET \
        --set-env-vars REDISHOST=REDIS_IP,REDISPORT=REDIS_PORT
    

    donde:

    • PROJECT_ID es el ID de tu proyecto. Google Cloud
    • REGION es la región en la que se encuentra tu instancia de Redis.
    • NETWORK es el nombre de la red VPC autorizada a la que está conectada tu instancia de Redis.
    • SUBNET es el nombre de tu subred. La subred debe ser /26 o mayor. La salida de VPC directa admite los intervalos IPv4 RFC 1918, RFC 6598 y de clase E.
    • REDIS_IP y REDIS_PORT son la dirección IP y el número de puerto de tu instancia de Redis.

Una vez que se haya completado el despliegue, la línea de comandos mostrará la URL de tu servicio de Cloud Run. Visita esta URL en un navegador web (o usa una herramienta como curl) y verás cómo aumenta el recuento en tu instancia de Redis cada vez que se visite el servicio.