Lunch at RMA
John McKim
VP of Product & Technology
A Cloud Guru
@johncmckim
History of ACG Architecture
Components:
Q/A session at the end.
The Architecture Sam built
Decoupling the Architecture
Adding a BFF & GraphQL
Service -> Service messages
Conways Law
Student
Team
Mobile
Team
Org Team
Team
A&B
Team
1x Dev Lead
3x Devs
Secret
Team
Serverless Framework
Serverless Framework
Example Service
service: email-service
provider:
name: aws
runtime: nodejs8.10
region: us-east-1
versionFunctions: false
environment:
STAGE: ${opt:stage}
plugins:
- serverless-plugin-aws-alerts
- serverless-domain-manager
- serverless-logless-plugin
custom:
logless:
logRetention: ${ssm:/${opt:stage}/email/config/LOG_RETENTION_IN_DAYS}
alerts:
dashboards: true
stages:
- production
topics:
ok:
topic: ${self:service}-${opt:stage}-alerts-ok
alarm:
topic: ${self:service}-${opt:stage}-alerts-alarm
insufficientData:
topic: ${self:service}-${opt:stage}-alerts-insufficientData
customDomain:
domainName: ${cf:acloudguru-api-gateway-${opt:stage}.InternalDomainName}
stage: ${opt:stage}
basePath: email
certificateName: '*.acloud.guru'
createRoute53Record: false
endpointType: 'regional'
package:
exclude:
- configure/**
- coverage/**
- src/**/*.test.js
- .node-version
- '*.sh'
- package.json
- yarn.lock
- README.md
functions:
graphql:
handler: src/graphql/index.handler
memorySize: 1536
timeout: 20
events:
- http:
path: graphql
method: post
cors: true
private: true
alarms:
- name: functionInvocations
threshold: 3000
tags:
FunctionType: graphql_api
emailQueueWorker:
handler: src/workers/email-queue.handler
reservedConcurrency: 1
events:
- sqs:
arn: ${ssm:/${opt:stage}/email/config/EMAIL_QUEUE_ARN}
batchSize: 1
resources:
Resources:
EmailTable:
Type: AWS::DynamoDB::Table
DeletionPolicy: ${ssm:/${opt:stage}/email/config/EMAIL_TABLE_DELETION_POLICY}
Properties:
TableName: ${ssm:/${opt:stage}/email/config/EMAIL_TABLE_NAME}
....
EmailGraphqlSchemaBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Properties:
BucketName: ${ssm:/${opt:stage}/email/config/S3_EMAIL_GRAPHQL_SCHEMA_BUCKET}
Mono-repo with services in folders
|_ school
|_ .buildkite
|_ backend
|_ infrastructure
|_ services
|_ email-service
|_ .buildkite
|_ src
|_ serverless.yml
|_ frontends
|_ mobile
|_ tools
History
Moving to Oprah
service: oprah-service
provider: ssm # or ddb
config:
path: /${stage}/oprah/config
defaults:
DB_NAME: my-database
DB_HOST: 3200
required:
DB_TABLE: "some database table name for ${stage}"
secret:
path: /${stage}/oprah/secret
required:
DB_PASSWORD: "secret database password"
oprah.yml
Moving to Oprah
const { makeParameterStore } = require('@a-cloud-guru/parameter-store');
const { STAGE } = process.env;
const parameterStore = makeParameterStore({
configPath: `/${SERVICE_STAGE}/foo-service/config`,
secretPath: `/${SERVICE_STAGE}/foo-service/secret`,
provider: {
tableName: `oprah-foo-service-${SERVICE_STAGE}`
}
});
return Promise.all([
parameterStore.getConfigs([
'THE_CONFIG_1',
'THE_CONFIG_2'
]),
parameterStore.getSecrets([
'THE_SECRET_1'
])
])
.then(([configs, secrets]) => ({ ...configs, ...secrets }))
.then(console.log);
example.js
Early Days
Monolithic Deployment with TravisCI
Trunk based dev, monorepo & buildkite
Deployment approach
Commit
Build triggered
Starts Pipelines
Deploy to Test
Deploy to Prod
WAIT
CloudWatch + Sumo
CloudWatch
Sumo
Fairly familiar
Scales with use & good TOC
Costs
Usage
Questions?
johncmckim.me
twitter.com/@johncmckim
medium.com/@johncmckim