Como conectarse a un cluster ElastiCache-Redis desde la CLI, Python 3.8 y a través de una Función Lambda.

Una vez tenemos nuestro cluster en funcionamiento tenemos varias formas de conectarnos y utilizarlo, a continuación vamos a ver la forma de utilizarlo desde la CLI usando Cloud9, Python usando Cloud9 y a través de una función lambda.

ElastiCache-Redis usando Python 3.8 (Cloud9)

Cloud9 es un IDE en la nube que trae todas las librerías de AWS y la CLI pre instalada, para eso desplegamos uno de esos con todas las configuraciones por defecto. Se debe tener en cuenta es que se debe autorizar desde el security group del cluster una Inbound Rule desde el security group del Cloud9 por el puerto 6379.

Ojo: Para que estas conexiones funcionen el cluster de ElastiCache debe crearse con el Encryption in transit deshabilitado. Actualmente hay problemas con las librerías de Redis y el ssl en AWS ElastiCache, es un caso conocido por AWS en el cual están trabajando: It has been reported that SSL certs received from AWS ElastiCache do not have proper hostnames and turning off hostname verification is currently required.

Crear un archivo redislab.py y cargar el siguiente código que explicaremos paso a paso:

from rediscluster import RedisClusterstartup_nodes = [{"host": "Configuration_Endpoint", "port": "6379"}]rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True, skip_full_coverage_check=True)
  • startup_nodes: Se debe especificar el endpoint y el puerto del cluster al cual vamos a conectarnos.
  • rc: Se configura la conexión al cluster de redis.

Para probar que la conexión se encuentre bien, podemos ejecutar los siguientes comandos, en la consola bash de cloud9:

czambrano:~/environment $ python3Python 3.6.10 (default, Feb 10 2020, 19:55:14) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from rediscluster import RedisCluster
>>> startup_nodes = [{"host": "Configuration_Endpoint", "port": "6379"}]
>>> rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True, skip_full_coverage_check=True)

Ingresamos línea a línea las cadenas de conexión, al final no debemos tener algún tipo de error, para finalizar vamos a ejecutar un comando (print (rc.dbsize())) que nos muestre el tamaño de las bases de datos que tenemos en el cluster y dependiendo de la cantidad de llaves que tengamos nos mostrará por cada uno de los nodos:

>>> print (rc.dbsize())
{'172.31.3.40:6379': 1, '172.31.32.148:6379': 1, '172.31.51.11:6379': 1, '172.31.53.87:6379': 0, '172.31.91.101:6379': 0, '172.31.24.239:6379': 0, '172.31.94.73:6379': 0, '172.31.30.20:6379': 0, '172.31.37.59:6379': 0}
>>>

Con este ultimo resultado podremos ver que ya nos encontramos conectados a nuestro cluster de ElastiCache.

Ojo: Con esta libreria nos conectamos a un Redis en mode cluster disabled.

import redisREDIS_URL = "Primary_Endpoint"
REDIS_STANDARD_VALIDATION = 0
REDIS_OBJECT = redis.StrictRedis(host=REDIS_URL, port=6379, db=REDIS_STANDARD_VALIDATION)
  • REDIS_URL: es el endpoint del cluster de ElastiCache. Cuando se crea en mode enabled el endpoint es el Primary_Endpoint.
  • REDIS_STANDARD_VALIDATION: Es el número de la base de datos, recuerden que por defecto en el parameter group la cantidad de base de datos es 16 (0 a 15). En este valor establecemos en este caso la primer base de datos disponible, la número 0.
  • REDIS_OBJECT: Acá se crea la conexión al cluster.

Para probar que la conexión se encuentre bien, podemos ejecutar el comando dbsize() para ver la cantidad de elementos en la BD actual (0):

>>> print (REDIS_OBJECT.dbsize())
0

Con este ultimo resultado podremos ver que ya nos encontramos conectados a nuestro cluster de ElastiCache.

ElastiCache-Redis usando CLI (Cloud9)

Para conectarnos utilizando la CLI debemos ejecutarlos siguientes comandos en una terminal bash de Cloud9 (Basada en AMI Linux):

sudo yum install gcc
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make

Una vez ejecutados los comandos mencionados, vamos a conectarnos de la siguiente forma al cluster:

czambrano:~/environment/redis-stable $ src/redis-cli -c -h Configuration_Endpoint -p 6379Configuration_Endpoint>

Para verificar la conexión vamos a agregar una llave y la consultaremos:

Agregar una llave:

Configuration_Endpoint> set 1 "mi primer llave"
-> Redirected to slot [9842] located at 172.31.94.73:6379
OK

Consultar una llave:

Configuration_Endpoint> get 1
"mi primer llave"

Con esto ya podemos validar que estemos correctamente conectados a nuestro cluster de ElastiCache-Redis.

ElastiCache-Redis usando Función Lambda (Python)

Para conectarnos desde una función lambda a un cluster de ElastiCache-Redis es necesario que la función se encuentre en una VPC y salga a internet. Desde el SG del ElastiCache se debe autorizar como origen el SG de la función lambda por el puerto 6379.

Para conectarnos al cluster de la función lambda se deben tener en cuenta las siguientes configuraciones:

  • Runtime: Python 3.8
  • Rol: La lambda debe tener un role que tenga permisos sobre cloudwatch y ElastiCache.
  • VPC: La función lambda debe estar en una VPC para poderse conectar al cluster de ElastiCache.
  • Lambda Layer: Se debe crear una lambda layer con las librerías de Redis requeridas y se adiciona a la lambda. Desde el Cloud9 ejecutamos los siguientes comandos para crear la lambda layer y cargarla a AWS.

Ojo: El rol asignado a la instancia de Cloud9 debe tener permisos suficientes para poder hacer un aws lambda publish-layer-version, con esto podrá cargar la layer sin problemas..

cd $HOME
mkdir -p temp/python
cd temp/python
pip install redis -t .
cd ..
zip -r9 ../utils_layer.zip .
aws lambda publish-layer-version --layer-name lambda_utils --description "added unsoported libs redis" --zip-file fileb://../utils_layer.zip --compatible-runtimes python3.6 python3.7 python3.8 --region us-east-1

Una vez ejecutados cada uno de los comandos dentro de nuestra función lambda en la sección de layers podremos ver algo así:

Una vez tengamos la layer lista agregamos el código de nuestra función lambda:

import json
import redis
import os
REDIS_URL = os.environ['REDIS_URL']
REDIS_STANDARD_VALIDATION = os.environ['REDIS_STANDARD_VALIDATION']
REDIS_OBJECT = redis.StrictRedis(host=REDIS_URL, port=6379, db=REDIS_STANDARD_VALIDATION)
def lambda_handler(event, context):
value = event['key1']
set_key_value("llave", value)
def set_key_value(key, value):
REDIS_OBJECT.set(key, value)

Estos campos tienen el os.environ dado que están cargando los valores de variables de entorno de las funciones lambda:

REDIS_URL = os.environ['REDIS_URL']
REDIS_STANDARD_VALIDATION = os.environ['REDIS_STANDARD_VALIDATION']

Para probar nuestra función Lambda, configuramos un test que mande un json de la siguiente forma:

{
"key1": "value1"
}

Cuando la lambda se ejecuta, esto se envía directamente al cluster de ElastiCache. Si queremos comprobar los valores guardados en el cluster podemos agregar las siguientes líneas para verificar al final de la función Lambda, las cuales resalto en negrita:

import json
import redis
import os
REDIS_URL = os.environ['REDIS_URL']
REDIS_STANDARD_VALIDATION = os.environ['REDIS_STANDARD_VALIDATION']
REDIS_OBJECT = redis.StrictRedis(host=REDIS_URL, port=6379, db=REDIS_STANDARD_VALIDATION)
def lambda_handler(event, context):
value = event['key1']
set_key_value("llave", value)
get_key_value("llave")
def set_key_value(key, value):
REDIS_OBJECT.set(key, value)
def get_key_value(key):
tc = REDIS_OBJECT.get(key)
print (tc)

Y deberíamos ver la impresión de lo que guardamos en el Redis:

Recomendaciones Finales

  • Siempre verificar los permisos del rol de la lambda y el rol de la instancia de cloud9.
  • Existen diferentes librerías de redis para conectarnos, las que vimos en el post son las más utilizadas.
  • AWS formalmente no da soporte sobre estas librerías de terceros, al indagar un poco más para que permitan la conexión a un cluster mode enabled con cifrado en tránsito obtuvimos esta respuesta del soporte de AWS: Since the module is being developed and maintained by third party, I don’t have any visibility on how exactly it works. At this point, I would encourage you to reach out to the respective developer or post your queries on the discussion forum to seek their assistance.
  • Tengan en cuenta en su arquitectura que la Lambda debe estar en una VPC, por lo tanto tendrá un SG asignado.
  • Verifiquen que el cluster de ElastiCache en su SG permita los SG de la Lambda y de la instancia de Cloud9 por el puerto 6379.

AWS x10, Tech Director en Globant con más de 7 años de experiencia en AWS.

AWS x10, Tech Director en Globant con más de 7 años de experiencia en AWS.