-1

Hi everybody and thanks for taking time to look at my issue/question.

I am getting different results when deploying my AWS Lambda stand-alone versus within an Application Stack.

I'm trying to connect to AWS Elasticache Redis from within my Lambda. I have .Net Core 3.1 Lambdas (using StackExchange.Redis) which can connect. But I also need to be able to connect from my Node.js Lambdas.

For the Node.js Lambdas, I'm using "node-redis" and "async-redis". I have two Lambdas which are essentially identical except that one is deployed in an Application Stack and the other is deployed as a stand-alone Lambda. Both Lambdas reference the same Lambda Layer (i.e. same "node_modules"), have the same VPC settings, the same Execution Role, and essentially the same code. So they've pushed it up to another group.

The stand-alone Lambda connects to Redis without issue. The Application Stack Lambda does not and exits processing before completing but without raising any error.

At first I thought I might just need to configure my Application Stack but I cannot find any information indicating we even can configure Application Stacks. So I'm at a loss.

The stand-alone Lambda:

 exports.handler = async (event) => {
        const asyncRedis = require("async-redis");
        const redisOptions = 
        {
            host: "XXXXXXXXX.XXXXX.XXXX.use2.cache.amazonaws.com",
            port: 6379
        }
    
        console.log('A');
        const client = asyncRedis.createClient(redisOptions);
        console.log(client);
    
        console.log('B');
        const value = await client.get("Key");
    
        console.log('C');
        console.log(value);
    
        console.log('D');
        console.log(client);
    };

The output of this function is essentially:

A
{RedisClient} --> the "client" object --> Shows connected = false
B
C
{ Correct Data From Redis }
D
{RedisClient} --> the "client" object --> Shows connected = true

The Application Stack Lambda:

async function testRedis2(event, context) {
    console.log('In TestRedis2');
    const asyncRedis = require("async-redis");
    const redisOptions = 
    {
        host: "XXXXXXXXX.XXXXX.XXXX.use2.cache.amazonaws.com",
        port: 6379
    }
        console.log('A');
        const client = asyncRedis.createClient(redisOptions);
        console.log(client);
    
        console.log('B');
        var value = await client.get("Key");

        console.log('C');
        console.log(value);
        
        console.log('D');
        console.log(client);
    }

module.exports = {
    testRedis2
};

The output of this function is essentially:

In TestRedis2
A
{RedisClient} --> the "client" object --> Shows connected = false
B

I don't understand why these don't perform identically. And I don't get why I don't see further entries in the output.

Has anyone else experienced issues connecting to VPC resources from within an Application Stack?

Thanks

Mark B
  • 183,023
  • 24
  • 297
  • 295
mmuse
  • 115
  • 9
  • 1
    I have no idea what you mean by "standalone" versus "application stack", but this is almost certainly a network configuration issue. Is the Redis server in the same VPC as the Lambda function? Does the ElastiCache cluster's security group allow inbound access from the security group assigned to the Lambda function? – Mark B Oct 09 '20 at 20:13
  • Mark, thanks for the response. On the AWS Lambda console, along the left hand side at the top it allows you to view the Dashboard, Applications, or Functions. Applications are just collections of AWS resources that you can manage as a single unit. So, if you have a number of associated functions you can put them in a stack to make managing them easier. Both functions are in the same VPC and run as the same Execution Role (so their inbound access is the same). – mmuse Oct 09 '20 at 21:30
  • The Execution Role is an IAM permission thing, it is not a network configuration setting. If there was a missing IAM permission you would be getting a permission denied error, not a hanging network connection. You need to verify the inbound rules of the security group(s) of the Redis cluster(s). – Mark B Oct 10 '20 at 00:18
  • Thanks Mark. I rechecked the VPC settings on both Lambdas and they are identical. But I agree with you that it must be a connection issue ... so I opened up a ticket with ASW. After some back and forth, the support rep confirmed that the configurations are identical. He said it didn't make sense to him so he's raised it to the next support level. I'll update if/when I hear back. – mmuse Oct 12 '20 at 14:00

1 Answers1

0

I stumbled across the answer through extensive trial and error. It may be obvious to Node/js developers but, just in case another Javascript/Node newbie has the same issue, I'll post the answer here.

The import/require and creation of the client must be at the top of the module. Not in the function itself.

So, the following does work in my application stack:

const asyncRedis = require("async-redis");

const redisOptions = {
    host: "XXXXXXXXX.XXXXX.XXXX.use2.cache.amazonaws.com",
    port: 6379
};

const client = asyncRedis.createClient(redisOptions);

async function redisGet(key: string){
  // console.log('In redisGet');
  return  await client.get(key);
}
mmuse
  • 115
  • 9