I am trying to make Serverless work with Elasticache. I wrote a custom CloudFormation file based on serverless-examples/serverless-infrastructure repo. I managed to put Elasticache and Lambda in one subnet (checked with the cli). I retrieve the host and the port from the Outputs, but whenever I am trying to connect with node-redis the connection times out. Here are the relevant parts:
-
4Being in one subnet doesn't automatically allow connections. You didn't mention security group settings.Michael - sqlbot– Michael - sqlbot2017-01-09 13:25:04 +00:00Commented Jan 9, 2017 at 13:25
-
The default inbound tcp port for Redis is 6379: docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/…David Maple– David Maple2017-01-09 13:54:40 +00:00Commented Jan 9, 2017 at 13:54
-
2What does your code do besides connecting to ec? Does it use dynamodb, s3 or other aws resources? If it does that might be what's timing out, because you don't have NATTolbahady– Tolbahady2017-01-11 00:37:08 +00:00Commented Jan 11, 2017 at 0:37
4 Answers
I ran into this issue as well, but with Python. For me, there were a few problems that had to be ironed out
- The lambda needs VPC permissions.
- The ElastiCache security group needs an inbound rule from the Lambda security group that allows communication on the Redis port. I thought they could just be in the same security group.
- And the real kicker: I had turned on encryption in-transit. This meant that I needed to pass
redis.RedisClient(... ssl=True). The redis-py page mentions thatssl_cert_reqsneeds to be set toNonefor use with ElastiCache, but that didn't seem to be true in my case. I did however need to passssl=True.
It makes sense that ssl=True needed to be set but the connection was just timing out so I went round and round trying to figure out what the problem with the permissions/VPC/SG setup was.
4 Comments
In my case I had TransitEncryptionEnabled: "true" with AuthToken: xxxxx for my redis cluster.
I ensured that both my lambda and redis cluster belonged to the same "private subnet". I also ensured that my "securityGroup" allowed traffic to flow on the desired ports.
The major issue I faced was that my lambda was unable to fetch data from my redis cluster. And whenever it attempted to get the data it would throw timeout error.
I used Node.Js with "Node-Redis" client.
Setting option tls: true worked for me. This is a mandatory setting if you have encryption at transit enabled.
Here is my config:
import { createClient } from 'redis';
import config from "../config";
let options: any = {
url: `redis://${config.REDIS_HOST}:${config.REDIS_PORT}`,
password: config.REDIS_PASSWORD,
socket: { tls: true }
};
const redisClient = createClient(options);
Hope this answer is helpful to those who are using Node.Js with "Node-Redis" dependency in their lambda.
Comments
As Tolbahady pointed out, the only solution was to create an NAT within the VPC.
3 Comments
@feus4177 is right. With encryption enabled you need to set tls: true
const Redis = require('ioredis');
const AWS = require('aws-sdk');
const TIME_WINDOW = 60; // seconds
exports.handler = async (event) => {
const redis = new Redis({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
tls: true
});