title: Lessons I learned from a cab drive about Serverless author: Camal Cakar patat: wrap: true margins: left: 0 right: 10 theme: syntaxHighlighting: decVal: [bold, onDullRed] bulletListMarkers: '-+' emph: [vividWhite, underline] header: [vividBlue, bold] codeBlock: [vividWhite, bold] code: [dullRed, bold] quoted: [bold, onDullRed] ...
golang pro tip: Don’t blindly apply dogmatic advice, use your judgment each and every time.
- Jaana B. Dogan
Was talking recently with a friend about how hard it is to write blog posts and give talks these days. The longer you’re in the tech industry the more your opinions end up being “well it depends” and “I’m not sure”. These don’t quite make for good blog posts, hah.
- Zach Holman
- In a startup or corporate enviroment
- Public cloud is an option
- No realtime critical system
- Serving highly mutable business requirements
- Caring about fast business value delivery
(Web,
"OpenFaaS",
"Fn Project")
RFC for 700 HTTP Status Codes
. . . .
2.2. Novelty Implementations . . . . . . . . . . . . . 3
. . . .
2.2. Novelty Implementations
o 710 - PHP
o 719 - Haskell
(GitHub,
"7XX-rfc")
Give you a hard time writing notes about:
. . .
- 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽
- Things Camal did wrong
- Articles to read
- Tools to try
- Video Clips to watch
- Suggestions to start
-
✈️ -
🚋
-
🚵🏽♀️
From the first programming languages, to object-oriented programming, to the development of virtualisation and cloud infrastructure, the history of computer science is a history of the development of abstractions that hide complexity and empower your to build ever more sophisticated applications.
- Kubernetes - Up & Running
┌──────────────┬─────┬───────┬──────┬────┬───┐
│ on-premise │ VM │ IaaS │ PaaS │ ? │ ? │
└──────────────┴─────┴───────┴──────┴────┴───┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ Micro Service│ │ FaaS │
│ │ │ │ └──────────────┘
│ Monolith │ └──────────────┘ ┌──────────────┐
│ │ │ FaaS │
│ │ ┌──────────────┐ └──────────────┘
│ │ │ Micro Service│ ┌──────────────┐
│ │ │ │ │ FaaS │
└──────────────┘ └──────────────┘ └──────────────┘
┌────────────────────────┬────────────┬──────────────────────┐
│ │ PaaS │ FaaS │
┌────────────────────────┬────────────┬──────────────────────┐
│ Startup time │ Minutes │ Milliseconds │
┌────────────────────────┬────────────┬──────────────────────┐
│ Running time │ 24/7 │ Runs incoming req. │
┌────────────────────────┬────────────┬──────────────────────┐
│ Cost │ Interval │ Pay for usage │
┌────────────────────────┬────────────┬──────────────────────┐
│ Unit of Code │ Monolithic │ Single-purpose func │
“Serverless” is just a name. We could have called it “Jeff”
- Jeff Conf
(Twitter,
"JeffConf")
A Serverless solution is one that costs you nothing to run if nobody is using it (excluding data storage)
┌────────────────────────┬──────────┬────────────────────┐
│ Functions as a Service + Patterns + 3rd Party Services │
└────────────────────────┴──────────┴────────────────────┘
Speed is king.
- Boxing proverb
// app.js
const express = require('express')
const app = express()
app.get('/', async (req, res, next) => {
res.status(200).send('Hello, DDD Cologne!')
})
app.listen(3000, () => console.log('Server is running on port 3000'))
# Dockerfile
FROM node:alpine
# Create app directory
WORKDIR /usr/src/app
# COPY package.json .
# For npm@5 or later, copy package-lock.json as well
COPY package.json package-lock.json ./
# Install app dependencies
RUN npm install
# Bundle app source
COPY . .
EXPOSE 3000
# Start Node server
CMD [ "npm", "start" ]
docker build . -t <docker_hub_username>/<image_name>
docker push <docker_hub_username>/<image_name>
$ export ORGANIZATION_NAME=your-org-name
# create state store
$ export BUCKET_NAME=${ORGANIZATION_NAME}-state-store
$ aws s3api create-bucket \
--bucket ${BUCKET_NAME} \
--region eu-central-1 \
--create-bucket-configuration LocationConstraint=eu-central-1
$ aws s3api put-bucket-versioning \
--bucket ${BUCKET_NAME} \
--versioning-configuration Status=Enabled
# create cluster
$ export KOPS_CLUSTER_NAME=${ORGANIZATION_NAME}.k8s.local
$ export KOPS_STATE_STORE=s3://${BUCKET_NAME}
# define cluster configuration
$ kops create cluster \
--master-count=1 --master-size=t2.micro \
--node-count=1 --node-size=t2.micro \
--zones=eu-central-1a \
--name=${KOPS_CLUSTER_NAME}
# if you want to edit config
$ kops edit cluster --name ${KOPS_CLUSTER_NAME}
# apply and create cluster
$ kops update cluster --name ${KOPS_CLUSTER_NAME} --yes
# validate cluster is running
$ kops validate cluster
# node-deployment.yml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: node
spec:
selector:
matchLabels:
app: node
tier: backend
replicas: 9
template:
metadata:
labels:
app: node
tier: backend
spec:
containers:
- name: node
image: <docker_hub_username>/<image_name>
ports:
- containerPort: 3000
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
# node-service.yml
apiVersion: v1
kind: Service
metadata:
name: node
labels:
app: node
tier: backend
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
app: node
tier: backend
$ kubectl apply -f node-deployment.yml
$ kubectl apply -f node-service.yml
# Framework
$ npm i -g serverless
# Express.js router proxy module
$ npm i serverless-http
// app.js
const express = require('express')
const sls = require('serverless-http')
const app = express()
app.get('/', async (req, res, next) => {
res.status(200).send('Hello, DDD Cologne!')
})
module.exports.server = sls(app)
# serverless.yml
service: express-sls-app
provider:
name: aws
runtime: nodejs8.10
stage: dev
region: eu-central-1
functions:
app:
handler: app.server
events:
- http:
path: /
method: ANY
- http:
path: /{proxy+}
method: ANY
$ serverless deploy
Imagine a new-gen developer that starts her/his career learning and working on nothing but AWS Lambda.
That experience will shape forever her/his worldwide and expectations about how IT works. Everything we know and do today will be irrelevant.
This is the issue.
- Alessandro Perilli
┌──────────────┐
┌──────────────┐ ┌──────────└──────────────┘
│ API │/ ┌──────────────┐
┌──────────────┐ │ │─────────────└──────────────┘
│ Incoming req.│------>│ Gateway │ ┌──────────────┐
└──────────────┘ │ │──────────────└──────────────┘
│ │\ ┌──────────────┐
└──────────────┘ └─────────────└──────────────┘
┌──────────────┐
┌──────────────┐ ┌───└──────────────┘
│ API │ /
│ │ ┌────────┐
------>│ Gateway │───└────────┘
│ │ \ ┌──────────────┐
│ │ └────└──────────────┘
└──────────────┘
. . . The danger is that it's very easy to make nicely decoupled systems with event notification, without realizing that you're losing sight of that larger-scale flow, and thus set yourself up for trouble in future years. The pattern is still very useful, but you have to be careful of the trap.
- Martin Fowler
A step machine with:
- Visual feedback
- Condition programming
Already used by Coca Cola shrink down a processing task from 18 hours to 10 seconds!
(Youtube,
"AWS re:Invent 2017: State Machines in the Wild! How Customers use AWS Step Functions")
Art by Joan Stark
_.===========================._
.'` .- - __- - - -- --__--- -. `'.
__ / ,'` _|--|_________|--|_ `'. \
/'--| ; _.'\ | ' ' | /'._ ; |
// | |_.-' .-'.' - -- - '.'-. '-._| |
(\) \"` _.-` / \ `-._ `"/
(\) `-` / .---------. \ `-`
(\) | ||1||2||3|| |
(\) | ||4||5||6|| |
(\) | ||7||8||9|| |
(\) ___| ||*||0||#|| |
(\) /.--| '---------' |
(\) (\) |\_ _ __ _ __ __/|
(\) (\) | |
(\\\\jgs\\\) '.___________________.'
'-'-'-'--'
(YouTube,
“What is Success? ElmConf”)
New platform capabilities lead to new architectural style and new operational practices
- Simon Wardley
(YouTube,
“Why the fuzz about Serverless”)
Netflix -> Cloud VM-native architecture
Airbnb -> Cloud Container-native architecture
?,you? -> Cloud Serverless-native architecture
(Slideshare,
"Asher Sterkin")
package hello
import (
"fmt"
"net/http"
)
func HelloWorld(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, DDD Cologne!")
}
import (
"fmt"
"net/http"
"go.opencensus.io/plugin/ochttp"
)
func HelloWorld(w http.ResponseWriter, r *http.Request) {
fn := func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, DDD Cologne!")
}
traced := &ochttp.Handler{
Handler: http.HandlerFunc(fn),
}
traced.ServeHTTP(w, r)
}
- Document the steps
- Create automation equivalents
- Create automation
- Self-service and autonomous systems
(acmequeue, "Manual work is a bug" Thomas A. Limoncelli)
The 200$ return statement ... just use a different storage bucket every time :)
(Sourcebox,
"https://sourcebox.be/blog/2017/08/07/serverless-a-lesson-learned-the-hard-way/"
)
Kinesis is just scaling to a specific limit!
(DevZone,
"Why It's Important to Try and Break Your Serverless Application")
(runbook,
"How We Massively Reduced Our AWS Lambda Bill With Go")
Arc42 (Dr. Gernot Starke und Peter Hruschka) or C4 (Simon Brown)
Platforms
OpenFaaS
Fn Project
Tools
Epsagon
DataBird
Sensu
Cloudcraft (AWS only 😢)
Frameworks
Serverless
Apex
SAM
Careless
Books
Serverless Architecture on AWS (Peter Sbarski)
Hands-On Serverless Applications with Go (Mohamed Labouardy)
YouTube
Why the fuss about Serverless? (Simon Wardley)
^----------------+------------------+
| | |
| | |
M | Re-Design | Not you cup |
E | or not | |
M | a good fit | of tea |
O | | |
R | | |
Y | | |
+-----------------------------------+
| | |
| | |
| | |
| Perfect | Re-Design? |
| | |
| | |
| | |
+----------------+------------------>
TIME
Get your ticket at kandddinsky.com ( https://www.kandddinsky.com/ ) We’ve created a discount code for your local DDD community in particular: “KanDDDinsky_LOVES_Cologne”