Deep Dive on Serverless Application Development Danilo Poccia, Technical Evangelist @danilop 2015, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Agenda What is a Serverless Application? What do we need to think about when building one? Bundling and Deploying Continuous Integration & Continuous Delivery Versioning, Stages, Variables Metrics, Monitoring, Logs, and Profiling
What are Serverless Applications?
Serverless means No servers to provision or manage Scales with usage Never pay for idle Availability and fault tolerance built in
Serverless application EVENT SOURCE FUNCTION SERVICES (ANYTHING) Changes in data state Requests to endpoints Changes in resource state Node.js Python Java C#
Example event sources that trigger AWS Lambda DATA STORES ENDPOINTS Amazon S3 Amazon DynamoDB Amazon Kinesis Amazon Cognito Amazon API Gateway AWS IoT AWS Step Functions Amazon Alexa CONFIGURATION REPOSITORIES EVENT/MESSAGE SERVICES AWS AWS CloudTrail CloudFormation AWS CodeCommit Amazon CloudWatch Amazon SES Amazon SNS Cron events and a few more with more on the way!
API Gateway AWS Mobile Apps API Gateway Cache AWS Lambda functions Websites Internet Amazon CloudFront Endpoints on Amazon EC2 Services All publicly accessible endpoints Amazon CloudWatch Monitoring Any other AWS service
Common use cases </> Web Applications Backends Data Processing Chatbots Amazon Alexa IT Automation Static websites Complex web apps Packages for Flask and Express Apps & services Mobile IoT Real time MapReduce Batch Powering chatbot logic Powering voice-enabled apps Alexa Skills Kit Policy engines Extending AWS services Infrastructure management
Bundling and Deploying Serverless Applications
Building a deployment package Node.js & Python Java C# (.NET Core).zip file consisting of your code and any dependencies Use npm/pip to install libraries All dependencies must be at root level Either.zip file with all code/dependencies, or standalone.jar Use Maven / Eclipse IDE plugins Compiled class & resource files at root level, required jars in /lib directory Either.zip file with all code/dependencies, or a standalone.dll Use NuGet / VisualStudio plugins All assemblies (.dll) at root level
AWS CloudFormation Create templates of your infrastructure CloudFormation provisions AWS resources based on dependency needs Version control/replicate/update templates like code Integrates with development, CI/CD, management tools JSON and YAML supported
CloudFormation template AWSTemplateFormatVersion: '2010-09-09' Resources: GetHtmlFunctionGetHtmlPermissionProd: Type: AWS::Lambda::Permission Properties: Action: lambda:invokefunction Principal: apigateway.amazonaws.com FunctionName: Ref: GetHtmlFunction SourceArn: Fn::Sub: arn:aws:execute-api:${aws::region}:${aws::accountid}:${serverlessrestapi}/prod/any/* ServerlessRestApiProdStage: Type: AWS::ApiGateway::Stage Properties: DeploymentId: Ref: ServerlessRestApiDeployment RestApiId: Ref: ServerlessRestApi StageName: Prod ListTable: Type: AWS::DynamoDB::Table Properties: ProvisionedThroughput: WriteCapacityUnits: 5 ReadCapacityUnits: 5 AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - KeyType: HASH AttributeName: id GetHtmlFunction: Type: AWS::Lambda::Function Properties: Handler: index.gethtml Code: S3Bucket: flourish-demo-bucket S3Key: todo_list.zip Role: Fn::GetAtt: - GetHtmlFunctionRole - Arn Runtime: nodejs4.3 GetHtmlFunctionRole: Type: AWS::IAM::Role Properties: ManagedPolicyArns: - arn:aws:iam::aws:policy/amazondynamodbreadonlyaccess - arn:aws:iam::aws:policy/service-role/awslambdabasicexecutionrole AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Action: - sts:assumerole Effect: Allow Principal: Service: - lambda.amazonaws.com ServerlessRestApiDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: Ref: ServerlessRestApi Description: 'RestApi deployment id: 127e3fb91142ab1ddc5f5446adb094442581a90d' StageName: Stage GetHtmlFunctionGetHtmlPermissionTest: Type: AWS::Lambda::Permission Properties: Action: lambda:invokefunction Principal: apigateway.amazonaws.com FunctionName: Ref: GetHtmlFunction SourceArn: Fn::Sub: arn:aws:execute-api:${aws::region}:${aws::accountid}:${serverlessrestapi}/*/any/* ServerlessRestApi: Type: AWS::ApiGateway::RestApi Properties: Body: info: version: '1.0' title: Ref: AWS::StackName paths: "/{proxy+}": x-amazon-apigateway-any-method: x-amazon-apigateway-integration: httpmethod: ANY type: aws_proxy uri: Fn::Sub: arn:aws:apigateway:${aws::region}:lambda:path/2015-03- 31/functions/${GetHtmlFunction.Arn}/invocations responses: {} swagger: '2.0'
AWS Serverless Application Model (SAM) CloudFormation extension optimized for serverless New serverless resource types: functions, APIs, and tables Supports anything CloudFormation supports Open specification (Apache 2.0)
CloudFormation template AWSTemplateFormatVersion: '2010-09-09' Resources: GetHtmlFunctionGetHtmlPermissionProd: Type: AWS::Lambda::Permission Properties: Action: lambda:invokefunction Principal: apigateway.amazonaws.com FunctionName: Ref: GetHtmlFunction SourceArn: Fn::Sub: arn:aws:execute-api:${aws::region}:${aws::accountid}:${serverlessrestapi}/prod/any/* ServerlessRestApiProdStage: Type: AWS::ApiGateway::Stage Properties: DeploymentId: Ref: ServerlessRestApiDeployment RestApiId: Ref: ServerlessRestApi StageName: Prod ListTable: Type: AWS::DynamoDB::Table Properties: ProvisionedThroughput: WriteCapacityUnits: 5 ReadCapacityUnits: 5 AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - KeyType: HASH AttributeName: id GetHtmlFunction: Type: AWS::Lambda::Function Properties: Handler: index.gethtml Code: S3Bucket: flourish-demo-bucket S3Key: todo_list.zip Role: Fn::GetAtt: - GetHtmlFunctionRole - Arn Runtime: nodejs4.3 GetHtmlFunctionRole: Type: AWS::IAM::Role Properties: ManagedPolicyArns: - arn:aws:iam::aws:policy/amazondynamodbreadonlyaccess - arn:aws:iam::aws:policy/service-role/awslambdabasicexecutionrole AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Action: - sts:assumerole Effect: Allow Principal: Service: - lambda.amazonaws.com ServerlessRestApiDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: Ref: ServerlessRestApi Description: 'RestApi deployment id: 127e3fb91142ab1ddc5f5446adb094442581a90d' StageName: Stage GetHtmlFunctionGetHtmlPermissionTest: Type: AWS::Lambda::Permission Properties: Action: lambda:invokefunction Principal: apigateway.amazonaws.com FunctionName: Ref: GetHtmlFunction SourceArn: Fn::Sub: arn:aws:execute-api:${aws::region}:${aws::accountid}:${serverlessrestapi}/*/any/* ServerlessRestApi: Type: AWS::ApiGateway::RestApi Properties: Body: info: version: '1.0' title: Ref: AWS::StackName paths: "/{proxy+}": x-amazon-apigateway-any-method: x-amazon-apigateway-integration: httpmethod: ANY type: aws_proxy uri: Fn::Sub: arn:aws:apigateway:${aws::region}:lambda:path/2015-03- 31/functions/${GetHtmlFunction.Arn}/invocations responses: {} swagger: '2.0'
SAM template AWSTemplateFormatVersion: '2010-09-09 Transform: AWS::Serverless-2016-10-31 Resources: GetHtmlFunction: Type: AWS::Serverless::Function Properties: CodeUri: s3://flourish-demo-bucket/todo_list.zip Handler: index.gethtml Runtime: nodejs4.3 Policies: AmazonDynamoDBReadOnlyAccess Events: GetHtml: Type: Api Properties: Path: /{proxy+} Method: ANY ListTable: Type: AWS::Serverless::SimpleTable
AWS commands Package & Deploy Package Creates a deployment package (.zip file) Uploads deployment package to an Amazon S3 bucket Adds a CodeUri property with S3 URI Deploy Calls CloudFormation CreateChangeSet API Calls CloudFormation ExecuteChangeSet API
Versioning, Stages, Variables
Function versioning and aliases Versions = immutable copies of code + configuration Aliases = mutable pointers to versions Development against $LATEST version Each version/alias gets its own ARN Lambda Function Version $LATEST Lambda Function Version 123 Enables rollbacks, staged promotions, locked behavior for client Lambda Function DEV Alias Lambda Function BETA Alias Lambda Function PROD Alias
API Gateway Stages Stages are named links to a deployed version of your API Recommended for managing API lifecycle dev/test/prod alpha/beta/gamma Support for parameterized values via stage variables
Lambda Environment Variables Key-value pairs that you can dynamically pass to your function Available via standard environment variable APIs such as process.env for Node.js or os.environ for Python Can optionally be encrypted via KMS Allows you to specify in IAM what roles have access to the keys to decrypt the information Useful for creating environments per stage (i.e. dev, testing, production)
API Gateway Stage Variables Stage variables act like environment variables Use stage variables to store configuration values Stage variables are available in the $context object Values are accessible from most fields in API Gateway Lambda function ARN HTTP endpoint Custom authorizer function name Parameter mappings
Stage variables and Lambda alias for stages Using Stage Variables in API Gateway together with Lambda function Aliases helps you manage a single API configuration and Lambda function for multiple stages mylambdafunction 1 2 3 = prod 4 5 6 = beta 7 8 = dev My First API Stage variable = lambdaalias Prod lambdaalias = prod Beta lambdaalias = beta Dev lambdaalias = dev
Manage Multiple Versions and Stages of your APIs Works like a source repository clone your API to create a new version: API 1 (v1) Stage (dev) Stage (prod) API 2 (v2) Stage (dev)
Continuous Integration & Continuous Delivery for Serverless Applications
AWS CodeBuild Fully managed build service that compiles source code, runs tests, and produces software packages Scales continuously and processes multiple builds concurrently You can provide custom build environments suited to your needs via Docker images Only pay by the minute for the compute resources you use Launched with CodePipeline and Jenkins integration
buildspec.yml Example version: 0.1 environment_variables: plaintext: "INPUT_FILE": "saml.yaml "S3_BUCKET": " phases: install: commands: - npm install pre_build: commands: - eslint *.js build: commands: - npm test post_build: commands: - aws cloudformation package --template $INPUT_FILE --s3- bucket $S3_BUCKET --output-template post-saml.yaml artifacts: type: zip files: - post-saml.yaml - beta.json
buildspec.yml Example version: 0.1 environment_variables: plaintext: "INPUT_FILE": "saml.yaml "S3_BUCKET": " phases: install: commands: - npm install pre_build: commands: - eslint *.js build: commands: - npm test post_build: commands: - aws cloudformation package --template $INPUT_FILE --s3- bucket $S3_BUCKET --output-template post-saml.yaml artifacts: type: zip files: - post-saml.yaml - beta.json Variables to be used by phases of build Examples for what you can do in the phases of a build: You can install packages or run commands to prepare your environment in install. Run syntax checking, commands in pre_build. Execute your build tool/command in build Test your app further or ship a container image to a repository in post_build Create and store an artifact in S3
Where to Focus Your Tests: UI Service 10% 20% Unit 70%
What service and release step corresponds with which tests? UI Service Unit Third Party Tooling AWS CodeBuild Build Test
AWS CodePipeline Continuous delivery service for fast and reliable application updates Model and visualize your software release process Builds, tests, and deploys your code every time there is a code change Integrates with third-party tools and AWS
AWS CodePipeline MyApplication Source Source GitHub Build CodeBuild AWS CodeBuild StagePipeline Action Transition Deploy JavaApp Elastic Beanstalk
AWS CodePipeline MyApplication Source Source GitHub Build CodeBuild AWS CodeBuild NotifyDevelopers Lambda Parallel actions Deploy JavaApp Elastic Beanstalk
AWS CodePipeline MyApplication Source Source GitHub Build CodeBuild AWS CodeBuild TestAPI Runscope NotifyDevelopers Lambda Sequential actions Deploy JavaApp Elastic Beanstalk
Build AWS CodePipeline MyApplication CodeBuild AWS CodeBuild Staging-Deploy JavaApp Elastic Beanstalk QATeamReview Manual Approval Review Manual Approvals Prod-Deploy JavaApp Elastic Beanstalk
Deploy via CodePipeline Pipeline flow: 1. Commit your code to a source code repository 2. Package in CodeBuild 3. Use CloudFormation actions in CodePipeline to create or update stacks via SAM templates Optional: Make use of ChangeSets 4. Make use of specific stage/environment parameter files to pass in Lambda variables 5. Test our application between stages/environments Optional: Make use of Manual Approvals
AWS CodeStar New!
Metrics, Monitoring, Logs, and Profiling Serverless Applications
Amazon CloudWatch Gain system-wide visibility into resource utilization, application performance, and operational health Collect and track metrics with CloudWatch Metrics Collect and monitor log files with CloudWatch Logs Set alarms and send messages to SNS Automatically react changes via CloudWatch Events
CloudWatch Metrics Lambda Default (free) metrics: Invocations Duration Throttles Errors Iterator Age Create custom metrics from inside your application using put-metric API call. API Gateway Default (free) metrics at Stage level: Count 4XXError 5XXError Latency IntegrationLatency CacheHitcount CacheMissCount Detailed metrics Same set of metrics at method level Can be enabled globally or only for specific methods
CloudWatch Logs Lambda Logging Logging directly from your code Basic request information included API Gateway Logging 2 Levels of logging, ERROR and INFO Optionally log method request/body content Set globally in stage, or override per method Log Pivots Build metrics based on log filters Jump to logs that generated metrics
Custom CloudWatch Dashboards
AWS X-Ray Identify performance bottlenecks and errors Pinpoint issues to specific service(s) in your application Identify impact of issues on users of the application Visualize the service call graph of your application
Service map
Trace view
Putting it all together! Bundling and Deploying Continuous Integration & Continuous Delivery Versioning, Stages, Variables Metrics, Monitoring, Logs, and Profiling
Building on Lambda Functions Padraig O Brien - Luciano Mammino
{ name : Padraig, job : engineer, twitter : @Podgeypoos79, extra : [ NodeSchool organiser, LeanCoffee organiser, Tons of secret projects! ] }
{ name : Luciano, job : engineer, twitter : @loige, Website : loige.co side-projects : [ Node.js Design Patterns, Fullstack Bulletin ] }
UK energy supplier ESB funded startup (25 people) Targets energy intensive customers Trading platform / billing / forecasting
Technology adoption by industry Source: BCG, Boston Consulting Group, 2016
Common startup goals Quick and agile High quality software
Our challenge Grow customer base Get to market fast Bringing digital disruption in the energy industry
The Standing data service Download, process & store industry data Integration layer (REST Api) Get more details!
First Design OVER-SIMPLIFIED Recurring task Software provisioning Security patches Be on call for down times AZ a AZ b AZ c
Drawbacks Many moving parts Steep learning curve Significantly long time to market
Second (and current) design Dev. Experience Write business logic Define triggers (API Gateway or Schedule) Deploy as Lambda
Some lessons learned Infrastructure as code is hard Lambda Function auto-scaling FTW! Beware of soft limits
Some lessons learned Local development was challenging Orchestration of lambda functions Managed service, less hassle
Some lessons learned Got to focus on delivering. Cost of $8 a month. Best practices for larger projects are hard to find.
What s up next (AWS Step Functions)
What s up next AWS X-Ray Improve debugging experience AWS Glue (ETL) Simplify data import and synchronization Amazon AI services & platforms Predicting electricity costs and consumption
Thank you Talk to us at our Partner s stand S28 www.planet9energy.com
Next steps See https://aws.amazon.com/serverless for reference architectures, samples, and links to more content! Explore the AWS SAM specification on GitHub Visit the Lambda console, download a blueprint, and get started building your own Serverless Applications Send us your questions, comments, and feedback on the AWS Lambda Forums.
Conclusion Lambda is a fundamental component of modern application architectures It has a place in everything from data processing to simple web apps
Thank you! @danilop