Production-ready Serverless
on AWS
James Allardice
orangejellyfish
James Allardice
The Serverless framework
James Allardice
The Serverless framework
James Allardice
Production-ready?
James Allardice
Maintainable
James Allardice
Performant
James Allardice
Scalable
James Allardice
Secure
James Allardice
> npm i -g serverless
James Allardice
> npm i -g serverless
> serverless create --template aws-nodejs
# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
# docs.serverless.com
#
# Happy Coding!
service: aws-nodejs # NOTE: update this with your service name
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"
James Allardice
# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
# docs.serverless.com
#
# Happy Coding!
service: aws-nodejs # NOTE: update this with your service name
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
frameworkVersion: "=1.37.0"
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
# serverless.yml
provider:
name: aws
runtime: nodejs8.10
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
# serverless.yml
plugins:
- serverless-webpack
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "8.10"
}
}
]
]
}
James Allardice
const nodeExternals = require('webpack-node-externals');
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
target: 'node',
mode: 'production',
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
};
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
James Allardice
plugins:
- serverless-webpack
- serverless-iam-roles-per-function
James Allardice
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:PutItem
Resource:
- Fn::GetAtt: [ MyTable, Arn ]
- Effect: Allow
Action:
- sns:publish
Resource:
- Ref: MyTopic
James Allardice
⚙️
🚀
⚖️
🔒
James Allardice
Resources:
# A custom API Gateway account to allow us to enable request logging.
ApiGatewayAccount:
Type: AWS::ApiGateway::Account
Properties:
CloudWatchRoleArn:
Fn::GetAtt: [ RoleAPIGatewayCloudWatch, Arn ]
# A custom API Gateway stage (usually handled automatically by the Serverless
# framework) so that we can turn on CloudWatch request logging. The
# "MethodSettings" of a stage apply to all methods (effectively all endpoints)
# within that stage. The ApiGatewayRestApi resource is generated automatically
# by the Serverless framework.
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId:
Ref: ApiGatewayRestApi
MethodSettings:
- DataTraceEnabled: true
HttpMethod: "*"
LoggingLevel: INFO
ResourcePath: /*
MetricsEnabled: true
Stage
Account
Resources:
# An IAM role to allow API Gateway to log requests to CloudWatch.
RoleAPIGatewayCloudWatch:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Principal:
Service:
- apigateway.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
James Allardice
Apply to API Gateway
James Allardice
⚙️
🚀
⚖️
🔒
functions:
getTweets:
handler: tweets.get
events:
- schedule: rate(5 minutes)
environment:
TWITTER_ACCESS_TOKEN: "xxxxx"
James Allardice
:(
functions:
getTweets:
handler: tweets.get
events:
- schedule: rate(5 minutes)
environment:
TWITTER_ACCESS_TOKEN: ${ssm:TWITTER_ACCESS_TOKEN}
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
# Lambda function definitions. Each function defines itself in a separate YAML
# file that resides alongside the function implementation. Unfortunately we have
# to duplicate the function name here due to the way Serverless YAML importing
# and parsing works.
functions:
hello: ${file(src/functions/hello/index.yml):hello}
James Allardice
# src/functions/hello/handler.js
hello:
handler: src/functions/hello/handler.hello
events:
- http:
path: hello
method: get
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:PutItem
Resource:
- Fn::GetAtt: [ MyTable, Arn ]
- Effect: Allow
Action:
- sns:publish
Resource:
- Ref: MyTopic
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
# Custom AWS resource definitions. This includes anything that the Serverless
# framework doesn't handle for us, such as database setup, and overrides of
# Serverless defaults.
resources:
- ${file(src/resources/dynamodb.yml)}
- ${file(src/resources/sns.yml)}
James Allardice
Resources:
MyTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-${self:custom.stage}-my-table
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
James Allardice
Resources:
MyTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-${self:custom.stage}-my-table
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
James Allardice
James Allardice
⚙️
🚀
⚖️
🔒
⚙️
🚀
⚖️
🔒
James Allardice
GitHub!
James Allardice
What next?
Thank you!
James Allardice
orangejellyfish
Slides: https://slides.com/jamesallardice/production-ready-serverless-on-aws
Production-ready Serverless on AWS
By James Allardice
Production-ready Serverless on AWS
- 888