Tutorial: Getting Started on N|Solid for AWS Lambda with CloudFormation and Serverless
Recently NodeSource announced N|Solid for AWS Lambda, which offers low-impact monitoring for Lambda functions built on Node.js. This is the first time NodeSource's monitoring solution for Node.js has been offered for a serverless environment. To help new users get started with ease, I've prepared the following tutorial to provide step-by-step instructions that can be followed by folks who may not already have Lambda functions running in production.
Sample Function
To start, let's write a simple GraphQL Hello World as a serverless function using Apollo and N|Solid for AWS Lambda
const { ApolloServer, gql } = require('apollo-server-lambda')
const typeDefs = gql`
type Query {
helloWorld: String
}
`
const resolvers = {
Query: {
helloWorld: () => 'Hello from N|Solid Lambda'
}
}
const server = new ApolloServer({
typeDefs,
resolvers
})
exports.handler = server.createHandler()
It's not required that you use this example—you can use any function you'd like as you proceed through the rest of the tutorial.
AWS Serverless Application Model (SAM)
Next, you'll need a template.yaml
file to organize some basic information about your function:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
helloGraphQL:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: provided
Environment:
Variables:
NSOLID_LICENSE_KEY: <license-key>
Layers:
- arn:aws:lambda:us-east-1:800406105498:layer:nsolid-node-10:5
Events:
AnyRequest:
Type: Api
Properties:
Path: /graphql
Method: ANY
template.yaml
Runtime
property must be set toprovided
Environment
must contain the variableNSOLID_LICENSE_KEY
Layers
must contain an ARN for the N|Solid runtime layer
Your NSOLID_LICENSE_KEY
and instructions for determining the appropriate ARN for your N|Solid runtime layer can both be found in your NodeSource accounts portal.
AWS requires you to create a S3 bucket to store your package, which you can do by running:
aws s3 mb s3://apollo-lambda
Now it's time to create a package and upload it to S3:
aws cloudformation package \
--template-file template.yaml \
--s3-bucket apollo-lambda \
--output-template-file output-template.yaml
After you've uploaded to S3, you can trigger the deploy using the output-template.yaml
file generated by aws cloudformation package
:
aws cloudformation deploy \
--template-file output-template.yaml \
--stack-name apollolambda \
--capabilities CAPABILITY_IAM
You should now see a message in the terminal that looks like this, which indicates that the deployment was successful:
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - staging
Believe it or not, that's it! Your function will be running using N|Solid for AWS Lambda.
There are other frameworks that simplify writing and deploying functions to AWS Lambda, let's see some other alternatives.
Updating existing AWS Lambda functions
If you already have functions running in AWS Lambda you can update their runtime to use N|Solid by running:
aws lambda update-function-configuration \
--layers arn:aws:lambda:us-east-1:800406105498:layer:nsolid-node-10:5 \
--runtime provided \
--function-name <function-name> \
--environment "Variables={NSOLID_LICENSE_KEY=<license-key>}"
Serverless Framework
Serverless is a toolkit to develop functions for different providers, including for AWS Lambda.
First, you'll need to install the serverless
toolkit:
npm install -g serverless
Next, create a serverless.yaml
file. As you can tell from the example below, this is quite similar to the template.yaml
file from earlier, but is somewhat simplified and compatible with multiple platforms.
service: apollo-lambda
provider:
name: aws
stage: dev
region: us-east-1
environment:
NSOLID_LICENSE_KEY: <license-key>
functions:
helloGraphQL:
handler: index.handler
runtime: provided
layers:
- arn:aws:lambda:us-east-1:800406105498:layer:nsolid-node-10:5
serverless.yaml
runtime
property must be set toprovided
environment
must contain the variableNSOLID_LICENSE_KEY
, which can be found in your NodeSource accounts portal, where you can find the appropriate ARNlayers
must contain a N|Solid runtime layer ARN
Using serverless
simplifies the process a bit, so if you're using this option you don't need to create a S3 bucket or a package first.
Ensure all the dependencies are in your source folder by installing them using npm install
(in our example we are using apollo-server-lambda
) and then run:
serverless deploy
When the deploy has successfully completed you'll see this output in your terminal, including the URL of the deployed function:
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (5.54 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..............................
Serverless: Stack update finished...
Service Information
service: apollo-lambda-serverless
stage: dev
region: us-east-1
stack: apollo-lambda-serverless-dev
api keys:
None
endpoints:
ANY - https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/graphql
functions:
helloGraphQL: apollo-lambda-serverless-dev-helloGraphQL
layers:
None
Additional Layers
If you want to make effective and efficient use of the new AWS Lambda Layers feature to improve sharing of code or dependencies across your layers, N|Solid makes this very easy.
The Node.js module resolution path will include the /lib/node directory of any layer you add to your function when using N|Solid on AWS Lambda. So if you publish a layer that provides your dependencies in that location, they can be both shared, and independently managed from your function’s code.
Bear in mind that the standard Node.js runtimes provided by AWS (nodejs6.10 and nodejs8.10) do not provide a layer-based solution for Node dependencies, so make sure you’re including the N|Solid runtime layer and have selected “Use custom runtime in function code or layer”
Example
Let’s say your function depends on the Redis npm package and today you include it in your function archive with the current structure:
index.js
node_modules/redis/index.js
[...]
With N|Solid, you can publish this dependency as an independent layer with the following structure:
lib/node/redis/index.js
[...]
And by adding this layer along with t he N|Solid runtime, it will transparently discover and load your dependencies as if you had included them in the function itself. As many as 5 layers can be configured for a single Lambda function, including N|Solid itself.
Monitoring your Lambda functions
Once you have your Lambda functions up and running on N|Solid, you can track their activity and performance to identify potential issues or targets for further optimization:
N|Solid will automatically generate a CPU profile for a random sample of functions. From the CPU profile view, you can zoom in on a specific time frame or view the behavior of specific components in isolation.
Visit our Getting Started Guide to find more information about implementing and using N|Solid for AWS Lambda. We’re eager to hear feedback on our latest product offering, so if you run into issues or have questions, please don’t hesitate to contact us!