AWS Lambda connection timeout to Elasticache
Asked Answered
R

4

21

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:

Retarder answered 9/1, 2017 at 8:57 Comment(3)
Being in one subnet doesn't automatically allow connections. You didn't mention security group settings.Psychedelic
The default inbound tcp port for Redis is 6379: docs.aws.amazon.com/AmazonElastiCache/latest/UserGuide/…Neuropsychiatry
What 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 NATManzoni
R
0

As Tolbahady pointed out, the only solution was to create an NAT within the VPC.

Retarder answered 15/3, 2017 at 13:47 Comment(3)
Can you elaborate?, a link would it be much more appreciated.Reeding
Hello, sorry for the late reply. I no longer have the CF files, but you have to create an VPC and put Elasticache, together with the Lambdas under one subnet to communicate. You also have to have a gateway, unless you are going to communicate with the world. I believe the standard tutorial on Lambda and VPC gives enough info for a start.Retarder
A NAT gateway is not necessary for a Lambda to connect to ElasticCache, it's only needed to make calls to the internet or AWS service endpoints (unless you use a vpc gateway or endpoint for said service).Rogelioroger
L
19

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 that ssl_cert_reqs needs to be set to None for use with ElastiCache, but that didn't seem to be true in my case. I did however need to pass ssl=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.

Laodicea answered 27/6, 2019 at 17:45 Comment(3)
I've just tested - Lambda and Redis cluster can be in the same security group, you just need to specify the security group itself in its inbound/outbound rules.Fawcette
Yes, I should have been more clear in my answer. What I was trying to say was that I thought all that was needed was for them to be in the same security group, when in reality all that needs to be done is the inbound rule. Whether or not this is done through self reference or through separate security groups is irrelevant.Laodicea
Thanks, second bullet point helped. I also thought they can be same security groups, but it didn't work. When I have two different security groups for lambda and ec redis, and allowing lambda sg from ec sg worked for me.Countdown
M
2

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.

Macaroni answered 24/2, 2023 at 14:5 Comment(0)
R
0

As Tolbahady pointed out, the only solution was to create an NAT within the VPC.

Retarder answered 15/3, 2017 at 13:47 Comment(3)
Can you elaborate?, a link would it be much more appreciated.Reeding
Hello, sorry for the late reply. I no longer have the CF files, but you have to create an VPC and put Elasticache, together with the Lambdas under one subnet to communicate. You also have to have a gateway, unless you are going to communicate with the world. I believe the standard tutorial on Lambda and VPC gives enough info for a start.Retarder
A NAT gateway is not necessary for a Lambda to connect to ElasticCache, it's only needed to make calls to the internet or AWS service endpoints (unless you use a vpc gateway or endpoint for said service).Rogelioroger
U
0

@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
    });
Unknown answered 13/12, 2023 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.