I'm trying to access AWS Elasticache cluster from a Lambda function using Serverless framework (v 0.5.6) without loosing access to Dynamodb. I have tried using this Gist with no luck. Inside the Lambda function, first thing I do is to connect to the Redis instance but I keep getting timeouts, I have double checked CloudFormation outputs variables and its visibility inside the function and Lambda Roles/Policies for VPC but still nothing... I haven't found either any guide on how to create VPCs and Security Groups with CloudFormation and Serverless in order to create Public and Private subnets, NATs and Internet gateways as suggested here. Can anyone help?
You will have to place the Lambda function inside the VPC that the ElastiCache cluster resides in. Of course once you do that the Lambda function only has access to resources that exist inside the VPC, so it will no longer have access to DynamoDB. The solution to that is to add a NAT gateway to the VPC, which will allow the Lambda function to access resources outside the VPC.
I would think that setting up the VPC and NAT gateway would fall outside the Serverless framework, but I'm not an expert in that framework. I would suggest looking into configuring that manually via the AWS console or doing it through something like CloudFormation, and then simply specifying in your Serverless framework configuration the VPC that it needs to use.
While it's not properly documented, you can actually configure VPC directly in the serverless config file (see link)
Version 0.5
# s-function.json
{
"name": "hello",
"runtime": "nodejs4.3",
"handler": "handler.hello”,
"endpoints": [],
"events": [],
"vpc": {
"securityGroupIds": ["sg-123456"],
"subnetIds": [
"subnet-abc1",
"subnet-abc2",
"subnet-abc3",
]
}
}
Version 1.0
# serverless.yaml
service: aws-hello
provider: aws
runtime: nodejs4.3
vpc:
securityGroupIds:
— "sg-123456"
subnetIds:
— "subnet-abc1"
— "subnet-abc1"
— "subnet-abc1"
functions:
foo: # inherits the VPC config
handler: src/handler.foo
bar: # overwrites the VPC config
handler: src/handler.bar
vpc:
securityGroupIds:
— "sg-999999"
subnetIds:
— "subnet-zzz9"
Adding summary of how I setuped this:
create a new VPC
create 3 private subnets and 2 public subnet
multiple subnets are created for redundancy
create a security group
with inbound traffic to
elastic cache port
with outbound traffic to
all ports for internet access
create a new IGW
attach this IGW with VPC
create a new NAT
select a public lambda
public connectivity type
we need 2 route tables
1 for private subnets
this will have NAT and private subnets
another for public subnet with internet access
this will have IGW and public subnets
lambda configuration
attach IAM policies to lambda functions : AWSLambdaVPCAccessExecutionRole
attach private subnets to lambda
select security group for lambda
references:
https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/
https://docs.aws.amazon.com/lambda/latest/dg/services-elasticache-tutorial.html
Related
I'm wanting to establish connectivity to an RDS instance from some Lambda functions. Lambda functions are autodeployed with serverless framework, so ideally my config would be dynamic. I am currently managing infrastructure with CDK, and have the following resources:
1. RDS on Private Isolated subnet in VPC A, managed by CDK
2. EC2 instance on public subnet in VPC A, managed by CDK (For access to the RDS from the wider internet)
3. (Backend) 4 Lambdas without a VPC, behind an API Gateway in default VPC, managed by serverless deploy
4. Frontend hosted on S3 behind Cloudfront, managed by serverless deploy
I can deploy the lambdas to VPC A to either the private isolated or public subnets.
Additional constraints:
Lambdas require outbound connectivity, but should be protected from inbound internet requests from public internet.
I'm a bit stumped because I don't want to update my CDK script whenever the lambdas change. Help is much appreciated.
Your lambda functions need to be in the same VPC as the database, specifically in a private subnet.
You would then adjust the security group rules to allow connectivity from the functions to the DB using something like myFynction.connections.allowToDefaultPort(myDatabaseInstance);
The VPC needs to have a NAT gateway for the lambda functions to be able to access the internet. To clarify - the functions cannot be in an isolated subnet, because isolated subnets don't have Internet connectivity. Placing the functions in a public subnet will not work either - refer to this for an explanation.
Relevant documentation: https://aws.amazon.com/premiumsupport/knowledge-center/connect-lambda-to-an-rds-instance/
When I attempt to create a VPC Endpoint for the com.amazonaws.us-east-1.lambda (lambda service), the "us-east-1a" Availability Zone is not an option. However, when I choose a different service, like "com.amazonaws.us-east-1.rds", I can choose a subnet in the "us-east-1a" Availability Zone.
I am creating VPC endpoints via CloudFormation template, but also confirmed this occurs when creating via the UI.
I have been reviewing AWS documentation and also previous questions, but I cannot determine why this is occurring and how to fix this so we can select the subnets in that AZ for that VPC endpoint. Any guidance is appreciated.
Screenshot of attempting to create VPC endpoint for lambda with us-east-1a not allowed:
Screenshot of attempting to create VPC endpoint for another service:
You can run the CLI command to check for a service and the Availability Zones which are available to use for creating a VPC endpoint.
aws ec2 describe-vpc-endpoint-services --service-names SERVICE-NAME
Example for Lambda:
aws ec2 describe-vpc-endpoint-services --service-names com.amazonaws.us-east-1.lambda
{
"ServiceDetails": [
{
"ServiceName": "com.amazonaws.us-east-1.lambda",
"AvailabilityZones": [
"us-east-1a",
"us-east-1b",
"us-east-1c"
]....}
Why can’t I select an Availability Zone for my Amazon VPC interface endpoint?
https://aws.amazon.com/premiumsupport/knowledge-center/interface-endpoint-availability-zone/
I am trying to produce the correct CDK scripts (TypeScript) to create an environment with a Lambda (accessed via API Gateway) that can call an RDS (Sql Server instance).
I believe I have it mostly working, but I wanted to connect to the RDS instance from my development machine to run some queries and check on a few things.
My RDS instance is in a private subnet, and so I believe in order to connect to it I need to add an Internet Gateway and security group to allow access on the appropriate ports.
For the life of me I can figure out the last piece, how to add the internet gateway using CDK.
The latest script I have tried is as follows:
const privateSubnectConfiguration = {
cidrMask: 26,
name: 'private-subnet',
subnetType: SubnetType.PRIVATE,
};
const publicSubnectConfiguration = {
cidrMask: 26,
name: 'public-subnet',
subnetType: SubnetType.PUBLIC,
};
const vpc = new Vpc(this, props.generateId('vpc'), {
maxAzs: 2,
subnetConfiguration: [privateSubnectConfiguration, publicSubnectConfiguration],
natGateways: 1,
});
vpc.addGatewayEndpoint(props.generateId('internet-gateway'), {
service: { name: "ig-service" }
})
Which then errors with The Vpc Endpoint Service 'ig-service' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidServiceName;
I see references to the CfnInternetGateway in the docs, but just can't figure out how to attach a new one to my VPC?
Can you please help with the syntax?
First of all, you cannot directly access a database in a private subnet. You have to deploy a proxy instance in your public subnet and forward the required ports to access your database.
When using CDK VPC construct, an Internet Gateway is created by default whenever you create a public subnet. The default route is also setup for the public subnet.
So you should remove addGatewayEndpoint() from your code, which adds a Gateway VPC Endpoint that you don't need.
You may also consider using SubnetType.ISOLATED to create a private subnet without a NAT GW, which may be redundant in your case. SubnetType.PRIVATE creates a NAT Gateway by default.
I have been debugging, configuring and you name it the last couple of hours and i can't seem to figure out why this is happening.
I am trying to invoke a lambda function which is just retrieving basic information from ec2. when i test this lambda function in the aws console it seems to be working fine. However, invoking it in another lambda, using following code;
BasicAWSCredentials awsCreds = new BasicAWSCredentials("key1" , "key2");
AWSLambdaClientBuilder builder = AWSLambdaClientBuilder.standard()
.withRegion("eu-west-1")
.withCredentials(new AWSStaticCredentialsProvider(awsCreds));
AWSLambda client = builder.build();
InvokeRequest req = new InvokeRequest()
.withFunctionName("GetWhateverIneed");
InvokeResult result = client.invoke(req);
it simply times out. No response whatsoever... Both Lambdas are connected to the VPC and all subnets
I think it is my new VPC that is causing this problem. My VPC is consisting of:
1 VPC .
-2x Subnets (1x Private with ipv4 10.0.0.0/17, 1x Public with ipv4 10.0.128.0/17).
-1x IGW Connected to the Private subnet.
-1x NAT Gateway connected to the Public subnet .
-2x Endpoints (One for Ec2, One for SecretsManager)
I have also configured two route tables,
One for the "public" subnet:
"Routes" ->
Destination: 10.0.0.0/16 Target: local
Destination: 0.0.0.0/0 Target: My Internet Gateway(IGW)
One for the "private" subnet:
"Routes" ->
Destination: 10.0.0.0/16 Target: local .
Destination: 0.0.0.0/0 Target: My nat
I have made sure both of my Lambdas is running on the same VPC, they are both using the same security group:
This is my first time working with VPC so it is possible that i have missed something.
If your Lambda function is VPC attached, it needs to be able to communicate via your VPC to the AWS API. Lambdas do not talk to other Lambdas over the network, they initiate requests with the AWS API or an API Gateway, which passes the request on to the Lambda Function.
If you need a VPC attached Lambda to initiate another Lambda, it needs to be able to get to the AWS API or API Gateway via the internet. Alternatively, you can keep it all on private networks by adding a VPC Endpoint to the API Gateway Service.
A pattern I follow in similar circumstances is described in this previous post of mine: https://stackoverflow.com/a/43969112/6427978
I am trying to have an architecture with:
Route53 <-> API gateway <-> Lambda <-> RDS and DynamoDB.
I am confused about some networking aspects here!
From most of the documentation, what I understand is that Lambda is by default launched in default VPC and can access internet from there but no resources inside a "VPC". And this 2nd VPC (in quotes) refers to non-default VPCs in most discussions. But what is not clear is what if I placed the Lambda and RDS both in default VPC, lambda in a public subnet with --vpc-config info and RDS in a private subnet, will my Lambda have the internet connection?
Even when everything is in default subnet, should I put my lambda function in to a private subnet with Internet access through an Amazon VPC NAT gateway?
I know it is a theoretical question - documents are confusing me by not explicitly mentioning what cannot be done!
From most of the documentation, what I understand is that Lambda is by
default launched in default VPC and can access internet from there but
no resources inside a "VPC".
That is incorrect. By default Lambda is not launched in a VPC at all. Or if it is in a VPC it is in one that you cannot see because it doesn't exist in your AWS account.
what if I placed the Lambda and RDS both in default VPC, lambda in a
public subnet with --vpc-config info and RDS in a private subnet, will
my Lambda have the internet connection?
No, your Lambda function will not have internet access, even in a public subnet. This is because it is never assigned a public IP address. Once you place a Lambda function inside a VPC you have to have a NAT gateway in order to for the Lambda function to access anything outside the VPC.
Even when everything is in default subnet, should I put my lambda
function in to a private subnet with Internet access through an Amazon
VPC NAT gateway?
Yes, that is the correct way to provide a Lambda function with access to both a VPC and resources that exist outside the VPC.
Also note that DynamoDB (and the AWS API) does not run in your VPC. So if you place a Lambda function inside your VPC that needs to access DynamoDB, or anything else that is accessed via the AWS API, you will have to add a NAT gateway to the VPC.
Note that the "Default VPC" is the term for a the VPC that is setup for you when you first create your AWS account. You can see this VPC in your account in the VPC service console. Aside from it being created for you with default settings, you should just think of this as another VPC in your account. The Default VPC is not used by Lambda when you don't specify a VPC, and it is not used by other services like DynamoDB that exist outside your VPC network.