SlideShare a Scribd company logo
SERVERLESS
ARCHITECTURES
~ WHOAMI
▸Full stack developer 10+ years
▸Innovation Center of Accenture Cloud Platform
YEGOR FADEEV
WHY SERVERLESS?
DON’T WORRY, THERE ARE
SERVERS
THERE ARE NO SERVERS THAT
WE MANAGE
DEVS WANT TO GO NOOPS
http://martinfowler.com/bliki/DevOpsCulture.html
DEVS WANT TO GO NODEVOPS
http://martinfowler.com/bliki/DevOpsCulture.html
STATIC WEBSITE
- Highly Available Serverless Storage
- Scaleable and Elastic
- Replicated across 2 availability zones
- Supports HTTP requestsS3
Static HTML
CSS/Media
Rich JavaScript Apps
GET
http
S3 StorageCloudFront
USER
Static HTML
CSS/Media
Rich JavaScript Apps
R53 Domain
GET
http
example.com
S3 StorageCloudFront
USER
Static HTML
CSS/Media
Rich JavaScript Apps
COST MODEL: $0.03 GiB per Month
S3 HIGHLY AVAILABLE STORAGE
- Covered by AWS S3 SLA
- Durability: 99.999999999%
- Availability: 99.99%
SLOW WRITE OPERATIONS
R53 Domain
GET
http
example.com
S3 StorageCloudFront
USER
DYNAMIC WEBSITE
GET
Static HTML
CSS/Media
Rich JavaScript Apps
S3 StorageCloudFront
GET
POST
PUT
DELETE
Dynamic Data
Data from Database
Data from External Service
dataAPI Gateway Lambda
ajax
http
event
USER
LAMBDA
- AWS Computing Service
- Designed to reflect async Actor Model
- Resilient and Scaleable
- 512 RAM
- Supports Runtimes
- Java
- Python
- NodeJS
- Go (implicitly)
- Max Timeout 5 mins
- Pricing:
- 0.20$ per million requests.
- Billable 100 milliseconds
Lambda
API Gateway
EVENT SOURCE
Kinesis Data Streams
SNS Queue or Topic data
Lambda
other data
CONSUMER OR EVENT
CRON Job
API Gateway
Lambda
+
- API Management Tool
- Authorization + Custom Authorizer
- Defines: Environment Variables for Lambda
- Can be defined with Swagger and imported
- Code Supports Versioning
- Integrated with CloudWatch
- Lambda Containers are Cached for 5 minutes
- Can be deployed with “apex.run” tool
- User can write files in /tmp
apply plugin: 'java'
version = '1.0.0'
mainClassName='Main'
jar {
archiveName = 'apex.jar'
}
repositories {
mavenCentral()
}
dependencies {
compile (
'com.amazonaws:aws-lambda-java-core:1.1.0',
'com.amazonaws:aws-lambda-java-events:1.1.0'
)
}
GRADLE
$ ./gradlew clean build
BUILD SUCCESSFUL
Total time: 9.134 secs
SHELL
public class Main implements RequestHandler<String, String> {
@Override
public String handleRequest(String input, Context context) {
context.getLogger().log("My input is: " + input);
return "Hello: " + input;
}
}
JAVA
{
"runtime": "java8",
"role": "arn:aws:iam::776022106184:role/apex_lambda_function",
"handler": "Main::handleRequest",
"memory": 512,
"timeout": 32
}
Apex.run
$ apex deploy
• function created SHELL
GET
POST
PUT
DELETE
dataAPI Gateway Lambda
ajax event
USER
DB_URL
DB_PORT
DB_USER
Variables
MAKE IT SECURE
GET
POST
PUT
DELETE
dataAPI Gateway Lambda
ajax event
USER
DB_URL
DB_PORT
DB_USER
Variables
GET
POST
PUT
DELETE
dataAPI Gateway Lambda
ajax event
USER
VPC
DB_URL
DB_PORT
DB_USER
Variables
GET
POST
PUT
DELETE
dataAPI Gateway Lambda
ajax event
USER
VPC
Authorizer
Lambda
DB_URL
DB_PORT
DB_USER
Variables
GET
POST
PUT
DELETE
dataAPI Gateway Lambda
Ajax with
access token event
USER
VPC
Authorizer
Lambda
Request
access
token
SSO Service
R53 Domain
api.example.com
GET
POST
PUT
DELETE
dataAPI Gateway Lambda
Ajax with
access token event
USER
VPC
Authorizer
Lambda
R53 Domain
api.example.comRequest
access
token
SSO Service
Elastic Beanstalk container
SAML Service Provider
Elastic Beanstalk container
Trust
SAML Identity Provider
Authenticate
Request
access token
CASE STUDY
BUILD SERVERLESS APPLICATION
• COGNITO - MAKE IT SECURE
• DYNAMODB – STORE DATA
• S3 BUCKET - KEEP WEB CONTENT
• LAMBDA - DYNAMIC CONTENT
• TERRAFORM - BUILD INFRASTRUCTURE
USER
AWS
Services
Amazon
Cognito
Client
Application
Identity
Provider
1. Using the
Application
2. Send Identity
Provider Credentials
3. Get
Authentication
Token
4. Send Identity Pool ID +
Authentication Token
5. Check Authebtication
Token with Identity Provider
6. Get Identity ID + AWS
Temp Credentials for the
Authenticated Role
7. Call AWS Services using
AWS Temp Credentials
All AWS Services
Cognito
Amazon
DynamoDB
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"dynamodb:BatchGetItem",
"dynamodb:BatchWriteItem",
"dynaeleteItem",
"dynamodb:modb:DGetItem",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:UpdateItem“
],
"Resource": ["arn:aws:dynamodb:us-east-1:1111111111:table/answers"],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${cognito-
identity.amazonaws.com:sub}"]}
}
}]
}
AWS
IAM
IAM Policy
Lambda Microservice
AWS
Lambdapublic class Main implements RequestHandler<Main.Request, Boolean> {
private AmazonDynamoDBClient client = new AmazonDynamoDBClient(new
EnvironmentVariableCredentialsProvider());
private DynamoDBMapper mapper = new DynamoDBMapper(client);
@Override
public Boolean handleRequest(Request request, Context context) {
context.getLogger().log("My input is: " + request);
Problem problem = mapper.load(Problem.class,
request.getProblemId());
String expression = problem.getCode().replaceAll("__",
request.getAnswer()) + "; problem();";
try {
return eval(expression);
} catch (ScriptException e) {
return false;
}
}
private Boolean eval(String expression) throws ScriptException {
ScriptEngine engine = new
ScriptEngineManager().getEngineByName("javascript");
return (Boolean) engine.eval(expression);
}
...
}
Invoke Lambda
AWS
Lambda
checkAnswer: function(problemId, answer) {
return cognito.identity.then(function(identity) {
var lambda = new AWS.Lambda();
var params = {
FunctionName: 'spa_checkAnswer',
Payload: JSON.stringify({ problemId: problemId, answer: answer
})
};
return cognito.sendAwsRequest(lambda.invoke(params), function(){
return checkAnswer(problemId, answer);
})
})
}
Terraform
variable "login_provider" {
default = "105303240909-
am1nkfpr1fmo9d2bce5pbkv.apps.googleusercontent.com"
}
resource "template_file" "login_provider_config" {
template = "${file("${path.module}/../conf/cognito/config.json.tpl")}"
vars {
login_provider = "${var.login_provider}"
}
provisioner "local-exec" {
command ="echo "${self.rendered}" >
${path.module}/../conf/cognito/config.json"
}
}
First Deployment
1. Deploy infrastructure
$ terraform apply
2. Deploy the content to s3 bucket
$ npm install
$ aws s3 sync app/ s3://s3-spa.demos3.com/ --acl public-read
--profile spa
3. Import DynamoDB data
$ aws dynamodb batch-write-item --request-items
file://conf/dynamodb/sampledata/Problems.json --profile spa
4. Enjoy
http://s3-spa.demos3.com.s3-website-us-east-1.amazonaws.com
ALTERNATIVES
- SERVICE FABRIC
- Runtimes:
- ASP .NET (1Core)
- NodeJS
- etc
- Deployment:
- REST API
- PowerShell
- GOOGLE CLOUD FUNCTIONS (ALPHA)
- Runtimes:
- NodeJS (only)
- Deployment:
- gcloud
TAKEAWAYS
PAY FOR ONLY WHAT YOU USE
TAKEAWAYS
READING
▸ Book: AWS Lambda in Action
▸ MEAP begin in 2016 February
▸ Publication: March 2017
▸ Author: Danilo Poccia
▸ ISBN: 9781617293719
https://www.manning.com/books/aws-lambda-in-action
TAKEAWAYS
READING
▸ Book: Serverless Single Page Apps
▸ Published: 2016-06-20
▸ Author: Ben Rady
▸ ISBN: 978-1-68050-149-0
https://www.amazon.com/Serverless-Single-Page-Apps-Available
THANK YOU!
http://www.martinfowler.com/articles/serverless.html
https://github.com/yegor86/spa-aws
Links:
Demo:

More Related Content

Serverless archtiectures

  • 2. ~ WHOAMI ▸Full stack developer 10+ years ▸Innovation Center of Accenture Cloud Platform YEGOR FADEEV
  • 4. DON’T WORRY, THERE ARE SERVERS
  • 5. THERE ARE NO SERVERS THAT WE MANAGE
  • 6. DEVS WANT TO GO NOOPS http://martinfowler.com/bliki/DevOpsCulture.html
  • 7. DEVS WANT TO GO NODEVOPS http://martinfowler.com/bliki/DevOpsCulture.html
  • 9. - Highly Available Serverless Storage - Scaleable and Elastic - Replicated across 2 availability zones - Supports HTTP requestsS3
  • 10. Static HTML CSS/Media Rich JavaScript Apps GET http S3 StorageCloudFront USER
  • 11. Static HTML CSS/Media Rich JavaScript Apps R53 Domain GET http example.com S3 StorageCloudFront USER
  • 12. Static HTML CSS/Media Rich JavaScript Apps COST MODEL: $0.03 GiB per Month S3 HIGHLY AVAILABLE STORAGE - Covered by AWS S3 SLA - Durability: 99.999999999% - Availability: 99.99% SLOW WRITE OPERATIONS R53 Domain GET http example.com S3 StorageCloudFront USER
  • 14. GET Static HTML CSS/Media Rich JavaScript Apps S3 StorageCloudFront GET POST PUT DELETE Dynamic Data Data from Database Data from External Service dataAPI Gateway Lambda ajax http event USER
  • 15. LAMBDA - AWS Computing Service - Designed to reflect async Actor Model - Resilient and Scaleable - 512 RAM - Supports Runtimes - Java - Python - NodeJS - Go (implicitly) - Max Timeout 5 mins - Pricing: - 0.20$ per million requests. - Billable 100 milliseconds
  • 16. Lambda API Gateway EVENT SOURCE Kinesis Data Streams SNS Queue or Topic data Lambda other data CONSUMER OR EVENT CRON Job
  • 17. API Gateway Lambda + - API Management Tool - Authorization + Custom Authorizer - Defines: Environment Variables for Lambda - Can be defined with Swagger and imported - Code Supports Versioning - Integrated with CloudWatch - Lambda Containers are Cached for 5 minutes - Can be deployed with “apex.run” tool - User can write files in /tmp
  • 18. apply plugin: 'java' version = '1.0.0' mainClassName='Main' jar { archiveName = 'apex.jar' } repositories { mavenCentral() } dependencies { compile ( 'com.amazonaws:aws-lambda-java-core:1.1.0', 'com.amazonaws:aws-lambda-java-events:1.1.0' ) } GRADLE $ ./gradlew clean build BUILD SUCCESSFUL Total time: 9.134 secs SHELL
  • 19. public class Main implements RequestHandler<String, String> { @Override public String handleRequest(String input, Context context) { context.getLogger().log("My input is: " + input); return "Hello: " + input; } } JAVA { "runtime": "java8", "role": "arn:aws:iam::776022106184:role/apex_lambda_function", "handler": "Main::handleRequest", "memory": 512, "timeout": 32 } Apex.run $ apex deploy • function created SHELL
  • 20. GET POST PUT DELETE dataAPI Gateway Lambda ajax event USER DB_URL DB_PORT DB_USER Variables
  • 22. GET POST PUT DELETE dataAPI Gateway Lambda ajax event USER DB_URL DB_PORT DB_USER Variables
  • 23. GET POST PUT DELETE dataAPI Gateway Lambda ajax event USER VPC DB_URL DB_PORT DB_USER Variables
  • 24. GET POST PUT DELETE dataAPI Gateway Lambda ajax event USER VPC Authorizer Lambda DB_URL DB_PORT DB_USER Variables
  • 25. GET POST PUT DELETE dataAPI Gateway Lambda Ajax with access token event USER VPC Authorizer Lambda Request access token SSO Service R53 Domain api.example.com
  • 26. GET POST PUT DELETE dataAPI Gateway Lambda Ajax with access token event USER VPC Authorizer Lambda R53 Domain api.example.comRequest access token SSO Service Elastic Beanstalk container
  • 27. SAML Service Provider Elastic Beanstalk container Trust SAML Identity Provider Authenticate Request access token
  • 29. BUILD SERVERLESS APPLICATION • COGNITO - MAKE IT SECURE • DYNAMODB – STORE DATA • S3 BUCKET - KEEP WEB CONTENT • LAMBDA - DYNAMIC CONTENT • TERRAFORM - BUILD INFRASTRUCTURE
  • 30. USER AWS Services Amazon Cognito Client Application Identity Provider 1. Using the Application 2. Send Identity Provider Credentials 3. Get Authentication Token 4. Send Identity Pool ID + Authentication Token 5. Check Authebtication Token with Identity Provider 6. Get Identity ID + AWS Temp Credentials for the Authenticated Role 7. Call AWS Services using AWS Temp Credentials All AWS Services Cognito
  • 32. { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem", "dynaeleteItem", "dynamodb:modb:DGetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:UpdateItem“ ], "Resource": ["arn:aws:dynamodb:us-east-1:1111111111:table/answers"], "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": ["${cognito- identity.amazonaws.com:sub}"]} } }] } AWS IAM IAM Policy
  • 33. Lambda Microservice AWS Lambdapublic class Main implements RequestHandler<Main.Request, Boolean> { private AmazonDynamoDBClient client = new AmazonDynamoDBClient(new EnvironmentVariableCredentialsProvider()); private DynamoDBMapper mapper = new DynamoDBMapper(client); @Override public Boolean handleRequest(Request request, Context context) { context.getLogger().log("My input is: " + request); Problem problem = mapper.load(Problem.class, request.getProblemId()); String expression = problem.getCode().replaceAll("__", request.getAnswer()) + "; problem();"; try { return eval(expression); } catch (ScriptException e) { return false; } } private Boolean eval(String expression) throws ScriptException { ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); return (Boolean) engine.eval(expression); } ... }
  • 34. Invoke Lambda AWS Lambda checkAnswer: function(problemId, answer) { return cognito.identity.then(function(identity) { var lambda = new AWS.Lambda(); var params = { FunctionName: 'spa_checkAnswer', Payload: JSON.stringify({ problemId: problemId, answer: answer }) }; return cognito.sendAwsRequest(lambda.invoke(params), function(){ return checkAnswer(problemId, answer); }) }) }
  • 35. Terraform variable "login_provider" { default = "105303240909- am1nkfpr1fmo9d2bce5pbkv.apps.googleusercontent.com" } resource "template_file" "login_provider_config" { template = "${file("${path.module}/../conf/cognito/config.json.tpl")}" vars { login_provider = "${var.login_provider}" } provisioner "local-exec" { command ="echo "${self.rendered}" > ${path.module}/../conf/cognito/config.json" } }
  • 36. First Deployment 1. Deploy infrastructure $ terraform apply 2. Deploy the content to s3 bucket $ npm install $ aws s3 sync app/ s3://s3-spa.demos3.com/ --acl public-read --profile spa 3. Import DynamoDB data $ aws dynamodb batch-write-item --request-items file://conf/dynamodb/sampledata/Problems.json --profile spa 4. Enjoy http://s3-spa.demos3.com.s3-website-us-east-1.amazonaws.com
  • 38. - SERVICE FABRIC - Runtimes: - ASP .NET (1Core) - NodeJS - etc - Deployment: - REST API - PowerShell - GOOGLE CLOUD FUNCTIONS (ALPHA) - Runtimes: - NodeJS (only) - Deployment: - gcloud
  • 40. PAY FOR ONLY WHAT YOU USE
  • 41. TAKEAWAYS READING ▸ Book: AWS Lambda in Action ▸ MEAP begin in 2016 February ▸ Publication: March 2017 ▸ Author: Danilo Poccia ▸ ISBN: 9781617293719 https://www.manning.com/books/aws-lambda-in-action
  • 42. TAKEAWAYS READING ▸ Book: Serverless Single Page Apps ▸ Published: 2016-06-20 ▸ Author: Ben Rady ▸ ISBN: 978-1-68050-149-0 https://www.amazon.com/Serverless-Single-Page-Apps-Available

Editor's Notes

  1. Serverless is a hot topic in the software architecture world. We’re already seeing books, open source frameworks, plenty of vendor products, and even a conference dedicated to the subject. But what is Serverless and why is (or isn’t) it worth considering? Through this session I will try to enlighten you a little on these questions. Like many trends in software there’s no clear view of what ‘Serverless’ is: 1. Serverless was first used to describe applications that significantly or fully depend on 3rd party applications / services (‘in the cloud’) to manage server-side logic and state. These are typically ‘rich client’ applications (think single page web apps, or mobile apps) that use the vast ecosystem of cloud: databases, authentication services etc. 2. Serverless can also mean applications where some amount of server-side logic is still written by the application developer but unlike traditional architectures it runs in stateless compute containers that are event-triggered, ephemeral (may only last for one invocation), and fully managed by a 3rd party. (Thanks to ThoughtWorks for their definition in their most recent Tech Radar.) One way to think of this is ‘Functions as a service / FaaS’ . 3. AWS Lambda is one of the most popular implementations of FaaS at present, but there are others
  2. The term ‘Serverless’ is confusing since with such applications there are both server hardware and server processes running somewhere, but the difference to normal approaches is that the organization building and supporting a ‘Serverless’ application is not looking after the hardware or the processes - they are outsourcing this to a vendor.
  3. You can host your static website entirely on Amazon S3. Once you enable your bucket for static website hosting, all your content is accessible to web browsers via the Amazon S3 website endpoint for your bucket.
  4. Each bucket serves a website namespace (e.g. "www.example.com"). Requests for your host name (e.g. "example.com" or "www.example.com") can be routed to the contents in your bucket. You can also redirect requests to another host name (e.g. redirect "example.com" to "www.example.com").
  5. AWS Lambda is arguably the most exciting service released in AWS since EC2. Lambda is a service that lets you run code on someone else’s machine. All you need to do is pick the runtime your code can run in, and provide the code. Currently, the supported runtimes are: - Node.js: v0.10.36, v4.3.2 - Java: Java 8 - Python: Python 2.7
  6. In AWS Lambda, Lambda functions and event sources are the core components in AWS Lambda. An event source is the entity that publishes events, and a Lambda function is the custom code that processes the events. Supported event sources refer to those AWS services that can be preconfigured to work with AWS Lambda. The configuration is referred to as event source mapping, which maps an event source to a Lambda function. It enables automatic invocation of your Lambda function when events occur. Examples: 1. Akka actor chain can be implemented with help of two services: Dynamodb and Lambda 2. Lifecycle hooks which triggered when autoscaling group fired an up/down policy event. Lambda could make some preparation before a new vm is up 3. CRON/ Periodic task which check one metric or another. For instance, Lambda which monitors number of tasks in a custom tasks queue and sends metrics/alarm into CW when it cross the threshold 4. CI/CD 5. Backend for Api Gateway
  7. API Gateway is another exciting service on AWS that aims to ease the task of creating APIs. You define your resources and their models, request transformations, locations where requests should be proxied to, response transformations; and you get a functioning API without deploying a single machine. An API Gateway endpoint can use a Lambda function as its backend, which is the sweet spot touted by serverless architecture advocates. Like every system in its early life, API Gateway and Lambda have minor bugs and areas of improvement. Overall, the combination of these technologies is lethal, and I’m interested in seeing how functionality in existing applications can be chipped away to harness the strengths of these so-called serverless architectures.
  8. You can use Maven or Gradle to build you Lambda function in Java.
  9. You can use Maven or Gradle to build you Lambda function in Java.
  10. Allow the lambda direct access to our database
  11. Add Lambda and DB in the same VPC Assign a private ip to DB Use this IP from Lambda
  12. Introduce Authorizer, yet another feature in Api Gateway It makes sure an access token is present in HTTP request, token is valid and verifies presence of necessary data in the token Base on the token content it accepts or denies the request
  13. Introduce SSO service which issues access tokens It talks to federation-sts and helps end user to authenticate against Accenture IDP Disadvantages: We have to manage infrastructure for SSO service
  14. With Elastic Beanstalk, you can quickly deploy and manage applications in the AWS Cloud without worrying about the infrastructure that runs those applications. AWS Elastic Beanstalk reduces management complexity without restricting choice or control. You simply upload your application, and Elastic Beanstalk automatically handles the details of capacity provisioning, load balancing, scaling, and application health monitoring.
  15. Amazon Cognito lets you easily add user sign-in to your mobile and web apps. With Amazon Cognito, you can also authenticate users through social identity providers such as Facebook, Twitter, or Amazon, or by using your own identity solution.
  16. This call is possible thanks to Fine-Grained Access Control for DynamoDB To implement this kind of fine-grained access control, you write an IAM permissions policy that specifies conditions for accessing database. 
  17. The permissions policy grants permissions that allow a set of DynamoDB actions on the answers table. It uses the dynamodb:LeadingKeys condition key to restrict access for unauthorized users. The Condition entry in this policy uses a substitution variable to grab the Cognito ID from the request. This ensures that only authenticated Cognito users can access the table, and that they only have access to the documents that they created. All you need is to attach this policy to Cognito IAM Role and you will be able to access DB from client’s code completely secure
  18. Sometimes you may want to hide the logic from prying eyes for security reason or don’t want to share the code This could be put into Lambda Lambda supports Java runtime
  19. One major pain point of using Lambda/API Gateway/Cognito is the difficulty of setting things up. So the project uses Terraform to ease that difficulty. Terraform is a tool that lets you define configurations, which it can run to provision resources on datacenters by providers such as AWS, Azure and Google Cloud. In this project, Terraform is used to provision the Lambda function/Cognito Identity Pool/DynamoDb/S3 Bucket. With Terraform installed, the project can be deployed by simply invoking: - terraform apply - terraform destroy
  20. Developing applications using Lambda differs from the way we are typically used to, in terms of codebase management, tooling, frameworks, testing and deployment. On one hand, Lambda offers us the entire AWS ecosystem with simple configurations, and on the other, it requires us to rethink how we approach building even small applications. There aren’t yet enough success stories and best practices out there to give one the confidence to build large applications using Lambda, but there’s enough information to start farming out computation heavy processes to Lambda. Lambda especially shines because of its ability to scale along with its workload.