SlideShare a Scribd company logo
1 of 51
Download to read offline
Cloud patterns
applied
Making the most of EC2 at EyeEm
• Site Reliability Engineer at
EyeEm
• How do computers even
work?
• Started as an operations guy
in a scientific datacenter
• Now mostly developing and
making users and
developers happy
M E
@LarsFronius lars@eyeem.com
Resilience, Development, Culture.
—Paul Hammond
“If you think you can prevent failure, then you
aren’t developing your ability to respond.”
• Have as few as possible machines containing
application state
• Test restores of stateful machines
• Have as few as possible machines containing
application state
• Test restores of stateful machines
• …all the time.
• Have as few as possible machines containing
application state
• Test restores of stateful machines
• …all the time.
• Throw away stateless servers
• Throw away stateless servers
• Make sure they can come up again towards their
expected behaviour
—John Allspaw, Richard Cook
“The goal of operations is to have every day be
just another boring day. Achieving this boredom
depends on foreseeing the future performance
of the system and making adjustments
accordingly.”
• Distributed datastores
• Many small servers, rather than few big
33% 33% 33%
33% 33% 33%
50% 50% 33%
50% traffic increase on a single instance
12.5%12.5% 12.5% 12.5% 12.5% 12.5% 12.5% 12.5%
12.5%12.5% 12.5% 12.5% 12.5% 12.5% 12.5% 12.5%
14.3%14.3% 14.3% 14.3% 14.3% 14.3% 14.3% 12.5%
14.3%14.3% 14.3% 14.3% 14.3% 14.3% 14.3% 12.5%
14.4% traffic increase on a single instance
• Mark endpoints dead
• Test timeouts
• Single responsibility servers / services
• Security Groups control the interface how
services are supposed to talk to another
• Single responsibility servers / services
• Security Groups control the interface how
services are supposed to talk to another
• …and can be used to assign server role.
Backend
Security Group
role=backend
Database
Security Group
role=database
Redis Security
Group
role=feeds
Allow Inbound Backend 3306
Allow Inbound Backend 6379
Backend
Security Group
role=backend
Database
Security Group
role=database
Redis Security
Group
role=feeds
Allow Inbound Backend 3306
Allow Inbound Backend 6379
Base Security
Group
Metrics Security
Group
role=metrics
Allow Inbound Base 8125
Backend
Security Group
role=backend
Database
Security Group
role=database
Redis Security
Group
role=feeds
Allow Inbound Backend 3306
Allow Inbound Backend 6379Base Security
Group
Metrics Security
Group
role=metrics
Allow Inbound Base 8125
production
branch=master
Backend
Security Group
role=backend
Database
Security Group
role=database
Redis Security
Group
role=feeds
Allow Inbound Backend 3306
Allow Inbound Backend 6379Base Security
Group
Metrics Security
Group
role=metrics
Allow Inbound Base 8125
production
branch=master
feature_x staging
branch=feature_x
Backend
Security Group
role=backend
Database
Security Group
role=database
Redis Security
Group
role=feeds
Allow Inbound Backend 3306
Allow Inbound Backend 6379 Base Security
Group
{!
"Outputs": {!
"ApiEndpoint": {!
"Description": "DNS Endpoint to feature_xAPI staging",!
"Value": {!
"Ref": "apiendpoint"!
}!
},!
"backend1PrivateDNS": {!
"Description": "Private DNSName of the newly created EC2 backend1 instance",!
"Value": {!
"Fn::GetAtt": [!
"backend1",!
"PrivateDnsName"!
]!
}!
},!
"backend1PublicDNS": {!
"Description": "Public DNSName of the newly created EC2 backend1 instance",!
"Value": {!
"Fn::GetAtt": [!
"backend1",!
"PublicDnsName"!
]!
}!
},!
"db1PrivateDNS": {!
"Description": "Private DNSName of the newly created EC2 db1 instance",!
"Value": {!
"Fn::GetAtt": [!
"db1",!
"PrivateDnsName"!
]!
}!
},!
"db1PublicDNS": {!
"Description": "Public DNSName of the newly created EC2 db1 instance",!
"Value": {!
"Fn::GetAtt": [!
"db1",!
"PublicDnsName"!
]!
}!
},!
"redis1PrivateDNS": {!
"Description": "Private DNSName of the newly created EC2 redis1 instance",!
"Value": {!
"Fn::GetAtt": [!
"redis1",!
"PrivateDnsName"!
]!
}!
},!
"redis1PublicDNS": {!
"Description": "Public DNSName of the newly created EC2 redis1 instance",!
"Value": {!
"Fn::GetAtt": [!
"redis1",!
"PublicDnsName"!
]!
}!
}!
},!
"Resources": {!
"apiendpoint": {!
"Properties": {!
"HostedZoneId": "Z3HTG0V9588TAA",!
"Name": "api.feature_x.eyeem.com.",!
"ResourceRecords": [!
{!
"Fn::GetAtt": [!
"backend1",!
"PublicDnsName"!
]!
}!
],!
"TTL": 300,!
"Type": "CNAME"!
},!
"Type": "AWS::Route53::RecordSet"!
},!
"backend1": {!
"Properties": {!
"IamInstanceProfile": {!
"Ref": "puppetprovisioningprofile"!
},!
"ImageId": "ami-f2191786",!
"InstanceType": "c3.large",!
"KeyName": "eyeem-prod-new",!
"SecurityGroups": [!
{!
"Ref": "backendsg"!
},!
"puppeteers"!
],!
"Tags": [!
{!
"Key": "background_tasks",!
"Value": "false"!
},!
{!
"Key": "branch",!
"Value": "feature_x"!
},!
{!
"Key": "jenkins_access",!
"Value": ""!
},!
{!
"Key": "puppetbranch",!
"Value": "master"!
},!
{!
"Key": "service_discovery",!
"Value": "true"!
}!
],!
"UserData": {!
"Fn::Base64": {!
"Fn::Join": [!
"",!
[!
"#!/bin/bashncurl https://s3-eu-west-1.amazonaws.com/eyeem-deb-packages/gpg-key.asc | apt-key add -necho "deb http://eyeem-deb-packages.s3-website-eu-west-1.amazonaws.com $(lsb_release -cs) stable" > /etc/apt/sources.list.d/eyeem.listnecho "Package: *nPin: origin eyeem-deb-packages.s3-website-eu-west-1.amazonaws.comnPin-Priority: 550" > /etc/apt/preferences.d/eyeemnaptitude updatenaptitude install -y python-botonfetch_file s3://eyeem-configuration-management/provisioning/sg_tags.py > sg_tags.pynexport puppetbranch=$(python sg_tags.py puppetbranch)nif [ $puppetbranch != "" ]; thenn fetch_file "s3://eyeem-configuration-management/
provisioning-${puppetbranch}/base.user-data" > ./base.shnelsen fetch_file "s3://eyeem-configuration-management/provisioning/base.user-data" > ./base.shnfinbash ./base.shn",!
"ncurl -X PUT -H 'Content-Type:' --data-binary '{"Status":"SUCCESS","Reason":"we made it here.","UniqueId":"puppetwait","Data":"Its gonna be alright."}' '",!
{!
"Ref": "backend1puppetwaithandle"!
},!
"'"!
]!
]!
}!
}!
},!
"Type": "AWS::EC2::Instance"!
},!
"backend1puppetwaitcondition": {!
"Properties": {!
"Handle": {!
"Ref": "backend1puppetwaithandle"!
},!
"Timeout": "7200"!
},!
"Type": "AWS::CloudFormation::WaitCondition"!
},!
"backend1puppetwaithandle": {!
"Type": "AWS::CloudFormation::WaitConditionHandle"!
},!
"backendsg": {!
"Properties": {!
"GroupDescription": "backend",!
"SecurityGroupIngress": [!
{!
"CidrIp": "0.0.0.0/0",!
"FromPort": "22",!
"IpProtocol": "tcp",!
"ToPort": "22"!
},!
{!
"CidrIp": "0.0.0.0/0",!
"FromPort": "80",!
"IpProtocol": "tcp",!
"ToPort": "80"!
}!
],!
"Tags": [!
{!
"Key": "branch",!
"Value": "feature_x"!
},!
{!
"Key": "monitoring",!
"Value": "false"!
},!
{!
"Key": "puppetbranch",!
"Value": "master"!
},!
{!
"Key": "role",!
"Value": "backend"!
}!
]!
},!
"Type": "AWS::EC2::SecurityGroup"!
},!
"db1": {!
"Properties": {!
"IamInstanceProfile": {!
"Ref": "dbprovisioningprofile"!
},!
"ImageId": "ami-25488752",!
"InstanceType": "c3.large",!
"KeyName": "eyeem-prod-new",!
"SecurityGroups": [!
{!
"Ref": "dbsg"!
},!
"puppeteers"!
],!
"Tags": [!
{!
"Key": "restore_from_extract",!
"Value": "true"!
}!
],!
"UserData": {!
"Fn::Base64": {!
"Fn::Join": [!
"",!
[!
"#!/bin/bashncurl https://s3-eu-west-1.amazonaws.com/eyeem-deb-packages/gpg-key.asc | apt-key add -necho "deb http://eyeem-deb-packages.s3-website-eu-west-1.amazonaws.com $(lsb_release -cs) stable" > /etc/apt/sources.list.d/eyeem.listnecho "Package: *nPin: origin eyeem-deb-packages.s3-website-eu-west-1.amazonaws.comnPin-Priority: 550" > /etc/apt/preferences.d/eyeemnaptitude updatenaptitude install -y python-botonfetch_file s3://eyeem-configuration-management/provisioning/sg_tags.py > sg_tags.pynexport puppetbranch=$(python sg_tags.py puppetbranch)nif [ $puppetbranch != "" ]; thenn fetch_file "s3://eyeem-configuration-management/
provisioning-${puppetbranch}/base.user-data" > ./base.shnelsen fetch_file "s3://eyeem-configuration-management/provisioning/base.user-data" > ./base.shnfinbash ./base.shn",!
"ncurl -X PUT -H 'Content-Type:' --data-binary '{"Status":"SUCCESS","Reason":"we made it here.","UniqueId":"puppetwait","Data":"Its gonna be alright."}' '",!
{!
"Ref": "db1puppetwaithandle"!
},!
"'"!
]!
]!
}!
}!
},!
"Type": "AWS::EC2::Instance"!
},!
"db1puppetwaitcondition": {!
"Properties": {!
"Handle": {!
"Ref": "db1puppetwaithandle"!
},!
"Timeout": "7200"!
},!
"Type": "AWS::CloudFormation::WaitCondition"!
},!
"db1puppetwaithandle": {!
"Type": "AWS::CloudFormation::WaitConditionHandle"!
},!
"dbprovisioningprofile": {!
"Properties": {!
"Path": "/",!
"Roles": [!
"extract-access"!
]!
},!
"Type": "AWS::IAM::InstanceProfile"!
},!
"dbsg": {!
"Properties": {!
"GroupDescription": "db",!
"SecurityGroupIngress": [!
{!
"FromPort": "3306",!
"IpProtocol": "tcp",!
"SourceSecurityGroupName": {!
"Ref": "backendsg"!
},!
"ToPort": "3306"!
},!
{!
"CidrIp": "0.0.0.0/0",!
"FromPort": "22",!
"IpProtocol": "tcp",!
"ToPort": "22"!
}!
],!
"Tags": [!
{!
"Key": "branch",!
"Value": "feature_x"!
},!
{!
"Key": "monitoring",!
"Value": "false"!
},!
{!
"Key": "puppetbranch",!
"Value": "master"!
},!
{!
"Key": "role",!
"Value": "db"!
}!
]!
},!
"Type": "AWS::EC2::SecurityGroup"!
},!
"puppetprovisioningprofile": {!
"Properties": {!
"Path": "/",!
"Roles": [!
"puppet-provisioning"!
]!
},!
"Type": "AWS::IAM::InstanceProfile"!
},!
"redis1": {!
"Properties": {!
"IamInstanceProfile": {!
"Ref": "puppetprovisioningprofile"!
},!
"ImageId": "ami-25488752",!
"InstanceType": "c3.large",!
"KeyName": "eyeem-prod-new",!
"SecurityGroups": [!
{!
"Ref": "redissg"!
},!
"puppeteers"!
],!
"Tags": [],!
"UserData": {!
"Fn::Base64": {!
"Fn::Join": [!
"",!
[!
"#!/bin/bashncurl https://s3-eu-west-1.amazonaws.com/eyeem-deb-packages/gpg-key.asc | apt-key add -necho "deb http://eyeem-deb-packages.s3-website-eu-west-1.amazonaws.com $(lsb_release -cs) stable" > /etc/apt/sources.list.d/eyeem.listnecho "Package: *nPin: origin eyeem-deb-packages.s3-website-eu-west-1.amazonaws.comnPin-Priority: 550" > /etc/apt/preferences.d/eyeemnaptitude updatenaptitude install -y python-botonfetch_file s3://eyeem-configuration-management/provisioning/sg_tags.py > sg_tags.pynexport puppetbranch=$(python sg_tags.py puppetbranch)nif [ $puppetbranch != "" ]; thenn fetch_file "s3://eyeem-configuration-management/
provisioning-${puppetbranch}/base.user-data" > ./base.shnelsen fetch_file "s3://eyeem-configuration-management/provisioning/base.user-data" > ./base.shnfinbash ./base.shn",!
"ncurl -X PUT -H 'Content-Type:' --data-binary '{"Status":"SUCCESS","Reason":"we made it here.","UniqueId":"puppetwait","Data":"Its gonna be alright."}' '",!
{!
"Ref": "redis1puppetwaithandle"!
},!
"'"!
]!
]!
}!
}!
},!
"Type": "AWS::EC2::Instance"!
},!
"redis1puppetwaitcondition": {!
"Properties": {!
"Handle": {!
"Ref": "redis1puppetwaithandle"!
},!
"Timeout": "7200"!
},!
"Type": "AWS::CloudFormation::WaitCondition"!
},!
"redis1puppetwaithandle": {!
"Type": "AWS::CloudFormation::WaitConditionHandle"!
},!
"redissg": {!
"Properties": {!
"GroupDescription": "redis",!
"SecurityGroupIngress": [!
{!
"FromPort": "6379",!
"IpProtocol": "tcp",!
"SourceSecurityGroupName": {!
"Ref": "backendsg"!
},!
"ToPort": "6379"!
},!
{!
"CidrIp": "0.0.0.0/0",!
"FromPort": "22",!
"IpProtocol": "tcp",!
"ToPort": "22"!
}!
],!
"Tags": [!
{!
"Key": "branch",!
"Value": "feature_x"!
},!
{!
"Key": "monitoring",!
"Value": "false"!
},!
{!
"Key": "puppetbranch",!
"Value": "master"!
},!
{!
"Key": "role",!
"Value": "redis"!
}!
]!
},!
"Type": "AWS::EC2::SecurityGroup"!
}!
}!
}
{!
"Outputs": {!
"ApiEndpoint": {!
"Description": "DNS Endpoint to feature_xAPI
staging",!
"Value": {!
"Ref": "apiendpoint"!
}!
},!
"backend1PrivateDNS": {!
"Description": "Private DNSName of the newly
created EC2 backend1 instance",!
"Value": {!
"Fn::GetAtt": [!
"backend1",!
"PrivateDnsName"!
]!
}!
},!
"backend1PublicDNS": {!
"Description": "Public DNSName of the newly
created EC2 backend1 instance",!
"Value": {!
"Fn::GetAtt": [!
"backend1",!
"PublicDnsName"!
]!
}!
},!
"db1PrivateDNS": {!
"Description": "Private DNSName of the newly
created EC2 db1 instance",!
"Value": {!
"Fn::GetAtt": [!
"db1",!
"PrivateDnsName"!
]!
}!
},!
"db1PublicDNS": {!
"Description": "Public DNSName of the newly
created EC2 db1 instance",!
"Value": {!
"Fn::GetAtt": [!
"db1",!
"PublicDnsName"!
]!
}!
},!
"redis1PrivateDNS": {!
"Description": "Private DNSName of the newly
created EC2 redis1 instance",!
"Value": {!
"Fn::GetAtt": [!
"redis1",!
"PrivateDnsName"!
]!
}!
},!
"redis1PublicDNS": {!
"Description": "Public DNSName of the newly
created EC2 redis1 instance",!
"Value": {!
"Fn::GetAtt": [!
"redis1",!
"PublicDnsName"!
]!
}!
}!
},!
"Resources": {!
"apiendpoint": {!
"Properties": {!
"HostedZoneId": "Z3HTG0V9588TAA",!
"Name": "api.feature_x.eyeem.com.",!
"ResourceRecords": [!
{!
"Fn::GetAtt": [!
"backend1",!
"PublicDnsName"!
]!
}!
],!
"TTL": 300,!
"Type": "CNAME"!
},!
"Type": "AWS::Route53::RecordSet"!
},!
"backend1": {!
"Properties": {!
"IamInstanceProfile": {!
"Ref": "puppetprovisioningprofile"!
},!
"ImageId": "ami-f2191786",!
"InstanceType": "c3.large",!
"KeyName": "eyeem-prod-new",!
"SecurityGroups": [!
{!
"Ref": "backendsg"!
},!
"base"!
],!
"Tags": [!
{!
"Key": "background_tasks",!
"Value": "false"!
},!
{!
"Key": "branch",!
"Value": "feature_x"!
},!
{!
"Key": "jenkins_access",!
"Value": ""!
},!
{!
"Key": "puppetbranch",!
"Value": "master"!
},!
{!
"Key": "service_discovery",!
"Value": "true"!
}!
],!
"UserData": {!
"Fn::Base64": {!
"Fn::Join": [!
"",!
[!
{!
"Ref":
"backend1puppetwaithandle"!
},!
"'"!
]!
]!
}!
}!
},!
"Type": "AWS::EC2::Instance"!
},!
"backend1puppetwaitcondition": {!
"Properties": {!
"Handle": {!
"Ref": "backend1puppetwaithandle"!
},!
"Timeout": "7200"!
},!
"Type": "AWS::CloudFormation::WaitCondition"!
},!
"backend1puppetwaithandle": {!
"Type":
"AWS::CloudFormation::WaitConditionHandle"!
},!
"backendsg": {!
"Properties": {!
"GroupDescription": "backend",!
"SecurityGroupIngress": [!
{!
"CidrIp": "0.0.0.0/0",!
"FromPort": "22",!
"IpProtocol": "tcp",!
"ToPort": "22"!
},!
{!
"CidrIp": "0.0.0.0/0",!
"FromPort": "80",!
"IpProtocol": "tcp",!
"ToPort": "80"!
}!
],!
"Tags": [!
{!
"Key": "branch",!
"Value": "feature_x"!
},!
{!
"Key": "monitoring",!
"Value": "false"!
},!
{!
"Key": "puppetbranch",!
"Value": "master"!
},!
{!
"Key": "role",!
"Value": "backend"!
}!
]!
},!
"Type": "AWS::EC2::SecurityGroup"!
},!
"db1": {!
"Properties": {!
"IamInstanceProfile": {!
"Ref": "dbprovisioningprofile"!
},!
"ImageId": "ami-25488752",!
"InstanceType": "c3.large",!
"KeyName": "eyeem-prod-new",!
"SecurityGroups": [!
{!
"Ref": "dbsg"!
},!
–json.org
“JSON (JavaScript Object Notation) is a
lightweight data-interchange format. It is easy
for humans to read and write. It is easy for
machines to parse and generate.”
–json.org
“JSON (JavaScript Object Notation) is a
lightweight data-interchange format. It is easy
for humans to read and write. It is easy for
machines to parse and generate.”
eyeemstack create --machines backend db feed
--restore_db extract --branch feature_x
• Python tool on top of troposphere, a python
library to create CloudFormation descriptions
vagrant up backend db feed
class eyeem::profiles::backend::deploy {!
eyeem::deploy_codebase { “backend”:!
directory => ‘/var/www/backend’,!
bucket => ‘eyeem-web-backend’,!
filename => “backend-${::branch}.tar.gz”,!
restart => [‘nginx’, ’php5-fpm’]!
}!
}!
!
!
!
define eyeem::deploy_codebase (!
$prefix = '',!
$directory,!
$bucket,!
$filename,!
$restart ) {!
!
if (member($::mountpoints, “${directory}/current”) and $::environment == ‘local’) {!
notice(“Looks like we are on Vagrant and you mounted the code in, skipping deploy.”)!
} else {!
( . . . )!
}!
}
• ~70 Cents for a single test run.
• ~3.50 $ per workday.
• ~17.64 $ for always on staging per day.
• Tests disaster recovery on a sample dataset.
• Scalable setup.
• < 10 minutes
• Stagings just a click away.
Backend
Security Group
role=backend
Base Security
Group
Metrics Security
Group
role=metrics
Allow Inbound Base 8125
production
branch=master
feature_x staging
branch=feature_x
Backend
Security Group
role=backend
Base Security
Group
Inventory
Service Security
Group
role=inventory
InstanceInstance
branch=feature_x
public_dns=api.feature_x.eyeem.com
branch=master
public_dns=api.eyeem.com
Backend
Security Group
role=backend
Base Security
Group
Metrics Security
Group
role=metrics
Allow Inbound Base 8125
production
branch=master
feature_x staging
branch=feature_x
Backend
Security Group
role=backend
Base Security
Group
Inventory
Service Security
Group
role=inventory
InstanceInstance
branch=feature_x
public_dns=api.feature_x.eyeem.com
branch=master
public_dns=api.eyeem.com
Jobrunner
Service Security
Group
role=jobrunner
Culture
Practices
Tools
• ~350 Job Executions last month
• 350 times self service operations
• Stagings everywhere
• Definition of Done: Can you boot it up using
EyeEmStack and Vagrant?
• Lots of 99.999s%
• “Everything fails all the time.”
• Test your repairs, automate everything.
• Distribute your data.
• Applications should be able to handle state
transitions of service-parts and diagnose failure.
• Design your infrastructure towards acting as a
service provider to your developers.
Questions?
Questions?

More Related Content

What's hot

Catalina.2013 03-05
Catalina.2013 03-05Catalina.2013 03-05
Catalina.2013 03-05
NX21
 
Alfrescotomcat stderr.2013-03-05
Alfrescotomcat stderr.2013-03-05Alfrescotomcat stderr.2013-03-05
Alfrescotomcat stderr.2013-03-05
NX21
 
Site Performance - From Pinto to Ferrari
Site Performance - From Pinto to FerrariSite Performance - From Pinto to Ferrari
Site Performance - From Pinto to Ferrari
Joseph Scott
 

What's hot (20)

Catalina.2013 03-05
Catalina.2013 03-05Catalina.2013 03-05
Catalina.2013 03-05
 
MySQL Enterprise Backup: Better Very Large Database Backup & Recovery and More!!
MySQL Enterprise Backup: Better Very Large Database Backup & Recovery and More!!MySQL Enterprise Backup: Better Very Large Database Backup & Recovery and More!!
MySQL Enterprise Backup: Better Very Large Database Backup & Recovery and More!!
 
Alfrescotomcat stderr.2013-03-05
Alfrescotomcat stderr.2013-03-05Alfrescotomcat stderr.2013-03-05
Alfrescotomcat stderr.2013-03-05
 
Build Automation 101
Build Automation 101Build Automation 101
Build Automation 101
 
Django in the Real World
Django in the Real WorldDjango in the Real World
Django in the Real World
 
Fixing Growing Pains With Puppet Data Patterns
Fixing Growing Pains With Puppet Data PatternsFixing Growing Pains With Puppet Data Patterns
Fixing Growing Pains With Puppet Data Patterns
 
AWS ElasticBeanstalk Advanced configuration
AWS ElasticBeanstalk Advanced configurationAWS ElasticBeanstalk Advanced configuration
AWS ElasticBeanstalk Advanced configuration
 
AWS Webcast - Backup & Restore for ElastiCache/Redis: Getting Started & Best ...
AWS Webcast - Backup & Restore for ElastiCache/Redis: Getting Started & Best ...AWS Webcast - Backup & Restore for ElastiCache/Redis: Getting Started & Best ...
AWS Webcast - Backup & Restore for ElastiCache/Redis: Getting Started & Best ...
 
NZ Code Camp 2011 PowerShell + SharePoint
NZ Code Camp 2011 PowerShell + SharePointNZ Code Camp 2011 PowerShell + SharePoint
NZ Code Camp 2011 PowerShell + SharePoint
 
Adobe AEM Maintenance - Customer Care Office Hours
Adobe AEM Maintenance - Customer Care Office HoursAdobe AEM Maintenance - Customer Care Office Hours
Adobe AEM Maintenance - Customer Care Office Hours
 
(APP306) Using AWS CloudFormation for Deployment and Management at Scale | AW...
(APP306) Using AWS CloudFormation for Deployment and Management at Scale | AW...(APP306) Using AWS CloudFormation for Deployment and Management at Scale | AW...
(APP306) Using AWS CloudFormation for Deployment and Management at Scale | AW...
 
Azure Expert Leading Camp UA - 2015
Azure Expert Leading Camp UA - 2015Azure Expert Leading Camp UA - 2015
Azure Expert Leading Camp UA - 2015
 
How to Upgrade Your Database Plan on Heroku and Rails Setup?
How to Upgrade Your Database Plan on Heroku and Rails Setup?How to Upgrade Your Database Plan on Heroku and Rails Setup?
How to Upgrade Your Database Plan on Heroku and Rails Setup?
 
Site Performance - From Pinto to Ferrari
Site Performance - From Pinto to FerrariSite Performance - From Pinto to Ferrari
Site Performance - From Pinto to Ferrari
 
Master Chef class: learn how to quickly cook delightful CQ/AEM infrastructures
Master Chef class: learn how to quickly cook delightful CQ/AEM infrastructuresMaster Chef class: learn how to quickly cook delightful CQ/AEM infrastructures
Master Chef class: learn how to quickly cook delightful CQ/AEM infrastructures
 
S903 palla
S903 pallaS903 palla
S903 palla
 
DevOps for database
DevOps for databaseDevOps for database
DevOps for database
 
Ansible
AnsibleAnsible
Ansible
 
The new repository in AEM 6
The new repository in AEM 6The new repository in AEM 6
The new repository in AEM 6
 
Immutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaImmutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS Lambda
 

Similar to Cloud patterns applied

Similar to Cloud patterns applied (20)

AHMED JASSAT SOUTH ARICAN ORACLE USER GROUP PRESENTATION
AHMED JASSAT SOUTH ARICAN ORACLE USER GROUP PRESENTATIONAHMED JASSAT SOUTH ARICAN ORACLE USER GROUP PRESENTATION
AHMED JASSAT SOUTH ARICAN ORACLE USER GROUP PRESENTATION
 
Ansible: How to Get More Sleep and Require Less Coffee
Ansible: How to Get More Sleep and Require Less CoffeeAnsible: How to Get More Sleep and Require Less Coffee
Ansible: How to Get More Sleep and Require Less Coffee
 
SaltConf14 - Ben Cane - Using SaltStack in High Availability Environments
SaltConf14 - Ben Cane - Using SaltStack in High Availability EnvironmentsSaltConf14 - Ben Cane - Using SaltStack in High Availability Environments
SaltConf14 - Ben Cane - Using SaltStack in High Availability Environments
 
DevOps Fest 2019. Сергей Марченко. Terraform: a novel about modules, provider...
DevOps Fest 2019. Сергей Марченко. Terraform: a novel about modules, provider...DevOps Fest 2019. Сергей Марченко. Terraform: a novel about modules, provider...
DevOps Fest 2019. Сергей Марченко. Terraform: a novel about modules, provider...
 
TIAD : Automating the modern datacenter
TIAD : Automating the modern datacenterTIAD : Automating the modern datacenter
TIAD : Automating the modern datacenter
 
Iac d.damyanov 4.pptx
Iac d.damyanov 4.pptxIac d.damyanov 4.pptx
Iac d.damyanov 4.pptx
 
Getting started with Splunk Breakout Session
Getting started with Splunk Breakout SessionGetting started with Splunk Breakout Session
Getting started with Splunk Breakout Session
 
Container Days Boston - Kubernetes in production
Container Days Boston - Kubernetes in productionContainer Days Boston - Kubernetes in production
Container Days Boston - Kubernetes in production
 
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
 
PowerShell - Be A Cool Blue Kid
PowerShell - Be A Cool Blue KidPowerShell - Be A Cool Blue Kid
PowerShell - Be A Cool Blue Kid
 
Declarative Infrastructure Tools
Declarative Infrastructure Tools Declarative Infrastructure Tools
Declarative Infrastructure Tools
 
Scaling with Automation
Scaling with AutomationScaling with Automation
Scaling with Automation
 
OSDC 2015: Mitchell Hashimoto | Automating the Modern Datacenter, Development...
OSDC 2015: Mitchell Hashimoto | Automating the Modern Datacenter, Development...OSDC 2015: Mitchell Hashimoto | Automating the Modern Datacenter, Development...
OSDC 2015: Mitchell Hashimoto | Automating the Modern Datacenter, Development...
 
Terraform in deployment pipeline
Terraform in deployment pipelineTerraform in deployment pipeline
Terraform in deployment pipeline
 
20190615 hkos-mysql-troubleshootingandperformancev2
20190615 hkos-mysql-troubleshootingandperformancev220190615 hkos-mysql-troubleshootingandperformancev2
20190615 hkos-mysql-troubleshootingandperformancev2
 
Delegated Configuration with Multiple Hiera Databases - PuppetConf 2014
Delegated Configuration with Multiple Hiera Databases - PuppetConf 2014Delegated Configuration with Multiple Hiera Databases - PuppetConf 2014
Delegated Configuration with Multiple Hiera Databases - PuppetConf 2014
 
Merging and Migrating: Data Portability from the Trenches
Merging and Migrating: Data Portability from the TrenchesMerging and Migrating: Data Portability from the Trenches
Merging and Migrating: Data Portability from the Trenches
 
SEC303 Automating Security in Cloud Workloads with DevSecOps
SEC303 Automating Security in Cloud Workloads with DevSecOpsSEC303 Automating Security in Cloud Workloads with DevSecOps
SEC303 Automating Security in Cloud Workloads with DevSecOps
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.
 
Meetup bangalore aug31st2019
Meetup bangalore aug31st2019Meetup bangalore aug31st2019
Meetup bangalore aug31st2019
 

Recently uploaded

哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
ydyuyu
 
PowerDirector Explination Process...pptx
PowerDirector Explination Process...pptxPowerDirector Explination Process...pptx
PowerDirector Explination Process...pptx
galaxypingy
 
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdfpdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
JOHNBEBONYAP1
 
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
ayvbos
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
ydyuyu
 
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Monica Sydney
 
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
gajnagarg
 
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
ayvbos
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Monica Sydney
 

Recently uploaded (20)

哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
 
PowerDirector Explination Process...pptx
PowerDirector Explination Process...pptxPowerDirector Explination Process...pptx
PowerDirector Explination Process...pptx
 
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdfpdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
 
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
 
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime NagercoilNagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
 
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
 
APNIC Updates presented by Paul Wilson at ARIN 53
APNIC Updates presented by Paul Wilson at ARIN 53APNIC Updates presented by Paul Wilson at ARIN 53
APNIC Updates presented by Paul Wilson at ARIN 53
 
2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs
2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs
2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs
 
Meaning of On page SEO & its process in detail.
Meaning of On page SEO & its process in detail.Meaning of On page SEO & its process in detail.
Meaning of On page SEO & its process in detail.
 
Trump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts SweatshirtTrump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts Sweatshirt
 
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
 
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
 
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
 
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
 
20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf
 
Microsoft Azure Arc Customer Deck Microsoft
Microsoft Azure Arc Customer Deck MicrosoftMicrosoft Azure Arc Customer Deck Microsoft
Microsoft Azure Arc Customer Deck Microsoft
 
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
一比一原版(Curtin毕业证书)科廷大学毕业证原件一模一样
 
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency""Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
 

Cloud patterns applied

  • 1.
  • 2. Cloud patterns applied Making the most of EC2 at EyeEm
  • 3. • Site Reliability Engineer at EyeEm • How do computers even work? • Started as an operations guy in a scientific datacenter • Now mostly developing and making users and developers happy M E @LarsFronius lars@eyeem.com
  • 5. —Paul Hammond “If you think you can prevent failure, then you aren’t developing your ability to respond.”
  • 6.
  • 7.
  • 8.
  • 9. • Have as few as possible machines containing application state • Test restores of stateful machines
  • 10. • Have as few as possible machines containing application state • Test restores of stateful machines • …all the time.
  • 11. • Have as few as possible machines containing application state • Test restores of stateful machines • …all the time.
  • 12. • Throw away stateless servers
  • 13. • Throw away stateless servers • Make sure they can come up again towards their expected behaviour
  • 14. —John Allspaw, Richard Cook “The goal of operations is to have every day be just another boring day. Achieving this boredom depends on foreseeing the future performance of the system and making adjustments accordingly.”
  • 15.
  • 16. • Distributed datastores • Many small servers, rather than few big
  • 19. 50% 50% 33% 50% traffic increase on a single instance
  • 20. 12.5%12.5% 12.5% 12.5% 12.5% 12.5% 12.5% 12.5%
  • 21. 12.5%12.5% 12.5% 12.5% 12.5% 12.5% 12.5% 12.5%
  • 22. 14.3%14.3% 14.3% 14.3% 14.3% 14.3% 14.3% 12.5%
  • 23. 14.3%14.3% 14.3% 14.3% 14.3% 14.3% 14.3% 12.5% 14.4% traffic increase on a single instance
  • 24.
  • 25.
  • 26. • Mark endpoints dead • Test timeouts
  • 27. • Single responsibility servers / services • Security Groups control the interface how services are supposed to talk to another
  • 28. • Single responsibility servers / services • Security Groups control the interface how services are supposed to talk to another • …and can be used to assign server role.
  • 29. Backend Security Group role=backend Database Security Group role=database Redis Security Group role=feeds Allow Inbound Backend 3306 Allow Inbound Backend 6379
  • 30. Backend Security Group role=backend Database Security Group role=database Redis Security Group role=feeds Allow Inbound Backend 3306 Allow Inbound Backend 6379 Base Security Group Metrics Security Group role=metrics Allow Inbound Base 8125
  • 31.
  • 32. Backend Security Group role=backend Database Security Group role=database Redis Security Group role=feeds Allow Inbound Backend 3306 Allow Inbound Backend 6379Base Security Group Metrics Security Group role=metrics Allow Inbound Base 8125 production branch=master
  • 33. Backend Security Group role=backend Database Security Group role=database Redis Security Group role=feeds Allow Inbound Backend 3306 Allow Inbound Backend 6379Base Security Group Metrics Security Group role=metrics Allow Inbound Base 8125 production branch=master feature_x staging branch=feature_x Backend Security Group role=backend Database Security Group role=database Redis Security Group role=feeds Allow Inbound Backend 3306 Allow Inbound Backend 6379 Base Security Group
  • 34. {! "Outputs": {! "ApiEndpoint": {! "Description": "DNS Endpoint to feature_xAPI staging",! "Value": {! "Ref": "apiendpoint"! }! },! "backend1PrivateDNS": {! "Description": "Private DNSName of the newly created EC2 backend1 instance",! "Value": {! "Fn::GetAtt": [! "backend1",! "PrivateDnsName"! ]! }! },! "backend1PublicDNS": {! "Description": "Public DNSName of the newly created EC2 backend1 instance",! "Value": {! "Fn::GetAtt": [! "backend1",! "PublicDnsName"! ]! }! },! "db1PrivateDNS": {! "Description": "Private DNSName of the newly created EC2 db1 instance",! "Value": {! "Fn::GetAtt": [! "db1",! "PrivateDnsName"! ]! }! },! "db1PublicDNS": {! "Description": "Public DNSName of the newly created EC2 db1 instance",! "Value": {! "Fn::GetAtt": [! "db1",! "PublicDnsName"! ]! }! },! "redis1PrivateDNS": {! "Description": "Private DNSName of the newly created EC2 redis1 instance",! "Value": {! "Fn::GetAtt": [! "redis1",! "PrivateDnsName"! ]! }! },! "redis1PublicDNS": {! "Description": "Public DNSName of the newly created EC2 redis1 instance",! "Value": {! "Fn::GetAtt": [! "redis1",! "PublicDnsName"! ]! }! }! },! "Resources": {! "apiendpoint": {! "Properties": {! "HostedZoneId": "Z3HTG0V9588TAA",! "Name": "api.feature_x.eyeem.com.",! "ResourceRecords": [! {! "Fn::GetAtt": [! "backend1",! "PublicDnsName"! ]! }! ],! "TTL": 300,! "Type": "CNAME"! },! "Type": "AWS::Route53::RecordSet"! },! "backend1": {! "Properties": {! "IamInstanceProfile": {! "Ref": "puppetprovisioningprofile"! },! "ImageId": "ami-f2191786",! "InstanceType": "c3.large",! "KeyName": "eyeem-prod-new",! "SecurityGroups": [! {! "Ref": "backendsg"! },! "puppeteers"! ],! "Tags": [! {! "Key": "background_tasks",! "Value": "false"! },! {! "Key": "branch",! "Value": "feature_x"! },! {! "Key": "jenkins_access",! "Value": ""! },! {! "Key": "puppetbranch",! "Value": "master"! },! {! "Key": "service_discovery",! "Value": "true"! }! ],! "UserData": {! "Fn::Base64": {! "Fn::Join": [! "",! [! "#!/bin/bashncurl https://s3-eu-west-1.amazonaws.com/eyeem-deb-packages/gpg-key.asc | apt-key add -necho "deb http://eyeem-deb-packages.s3-website-eu-west-1.amazonaws.com $(lsb_release -cs) stable" > /etc/apt/sources.list.d/eyeem.listnecho "Package: *nPin: origin eyeem-deb-packages.s3-website-eu-west-1.amazonaws.comnPin-Priority: 550" > /etc/apt/preferences.d/eyeemnaptitude updatenaptitude install -y python-botonfetch_file s3://eyeem-configuration-management/provisioning/sg_tags.py > sg_tags.pynexport puppetbranch=$(python sg_tags.py puppetbranch)nif [ $puppetbranch != "" ]; thenn fetch_file "s3://eyeem-configuration-management/ provisioning-${puppetbranch}/base.user-data" > ./base.shnelsen fetch_file "s3://eyeem-configuration-management/provisioning/base.user-data" > ./base.shnfinbash ./base.shn",! "ncurl -X PUT -H 'Content-Type:' --data-binary '{"Status":"SUCCESS","Reason":"we made it here.","UniqueId":"puppetwait","Data":"Its gonna be alright."}' '",! {! "Ref": "backend1puppetwaithandle"! },! "'"! ]! ]! }! }! },! "Type": "AWS::EC2::Instance"! },! "backend1puppetwaitcondition": {! "Properties": {! "Handle": {! "Ref": "backend1puppetwaithandle"! },! "Timeout": "7200"! },! "Type": "AWS::CloudFormation::WaitCondition"! },! "backend1puppetwaithandle": {! "Type": "AWS::CloudFormation::WaitConditionHandle"! },! "backendsg": {! "Properties": {! "GroupDescription": "backend",! "SecurityGroupIngress": [! {! "CidrIp": "0.0.0.0/0",! "FromPort": "22",! "IpProtocol": "tcp",! "ToPort": "22"! },! {! "CidrIp": "0.0.0.0/0",! "FromPort": "80",! "IpProtocol": "tcp",! "ToPort": "80"! }! ],! "Tags": [! {! "Key": "branch",! "Value": "feature_x"! },! {! "Key": "monitoring",! "Value": "false"! },! {! "Key": "puppetbranch",! "Value": "master"! },! {! "Key": "role",! "Value": "backend"! }! ]! },! "Type": "AWS::EC2::SecurityGroup"! },! "db1": {! "Properties": {! "IamInstanceProfile": {! "Ref": "dbprovisioningprofile"! },! "ImageId": "ami-25488752",! "InstanceType": "c3.large",! "KeyName": "eyeem-prod-new",! "SecurityGroups": [! {! "Ref": "dbsg"! },! "puppeteers"! ],! "Tags": [! {! "Key": "restore_from_extract",! "Value": "true"! }! ],! "UserData": {! "Fn::Base64": {! "Fn::Join": [! "",! [! "#!/bin/bashncurl https://s3-eu-west-1.amazonaws.com/eyeem-deb-packages/gpg-key.asc | apt-key add -necho "deb http://eyeem-deb-packages.s3-website-eu-west-1.amazonaws.com $(lsb_release -cs) stable" > /etc/apt/sources.list.d/eyeem.listnecho "Package: *nPin: origin eyeem-deb-packages.s3-website-eu-west-1.amazonaws.comnPin-Priority: 550" > /etc/apt/preferences.d/eyeemnaptitude updatenaptitude install -y python-botonfetch_file s3://eyeem-configuration-management/provisioning/sg_tags.py > sg_tags.pynexport puppetbranch=$(python sg_tags.py puppetbranch)nif [ $puppetbranch != "" ]; thenn fetch_file "s3://eyeem-configuration-management/ provisioning-${puppetbranch}/base.user-data" > ./base.shnelsen fetch_file "s3://eyeem-configuration-management/provisioning/base.user-data" > ./base.shnfinbash ./base.shn",! "ncurl -X PUT -H 'Content-Type:' --data-binary '{"Status":"SUCCESS","Reason":"we made it here.","UniqueId":"puppetwait","Data":"Its gonna be alright."}' '",! {! "Ref": "db1puppetwaithandle"! },! "'"! ]! ]! }! }! },! "Type": "AWS::EC2::Instance"! },! "db1puppetwaitcondition": {! "Properties": {! "Handle": {! "Ref": "db1puppetwaithandle"! },! "Timeout": "7200"! },! "Type": "AWS::CloudFormation::WaitCondition"! },! "db1puppetwaithandle": {! "Type": "AWS::CloudFormation::WaitConditionHandle"! },! "dbprovisioningprofile": {! "Properties": {! "Path": "/",! "Roles": [! "extract-access"! ]! },! "Type": "AWS::IAM::InstanceProfile"! },! "dbsg": {! "Properties": {! "GroupDescription": "db",! "SecurityGroupIngress": [! {! "FromPort": "3306",! "IpProtocol": "tcp",! "SourceSecurityGroupName": {! "Ref": "backendsg"! },! "ToPort": "3306"! },! {! "CidrIp": "0.0.0.0/0",! "FromPort": "22",! "IpProtocol": "tcp",! "ToPort": "22"! }! ],! "Tags": [! {! "Key": "branch",! "Value": "feature_x"! },! {! "Key": "monitoring",! "Value": "false"! },! {! "Key": "puppetbranch",! "Value": "master"! },! {! "Key": "role",! "Value": "db"! }! ]! },! "Type": "AWS::EC2::SecurityGroup"! },! "puppetprovisioningprofile": {! "Properties": {! "Path": "/",! "Roles": [! "puppet-provisioning"! ]! },! "Type": "AWS::IAM::InstanceProfile"! },! "redis1": {! "Properties": {! "IamInstanceProfile": {! "Ref": "puppetprovisioningprofile"! },! "ImageId": "ami-25488752",! "InstanceType": "c3.large",! "KeyName": "eyeem-prod-new",! "SecurityGroups": [! {! "Ref": "redissg"! },! "puppeteers"! ],! "Tags": [],! "UserData": {! "Fn::Base64": {! "Fn::Join": [! "",! [! "#!/bin/bashncurl https://s3-eu-west-1.amazonaws.com/eyeem-deb-packages/gpg-key.asc | apt-key add -necho "deb http://eyeem-deb-packages.s3-website-eu-west-1.amazonaws.com $(lsb_release -cs) stable" > /etc/apt/sources.list.d/eyeem.listnecho "Package: *nPin: origin eyeem-deb-packages.s3-website-eu-west-1.amazonaws.comnPin-Priority: 550" > /etc/apt/preferences.d/eyeemnaptitude updatenaptitude install -y python-botonfetch_file s3://eyeem-configuration-management/provisioning/sg_tags.py > sg_tags.pynexport puppetbranch=$(python sg_tags.py puppetbranch)nif [ $puppetbranch != "" ]; thenn fetch_file "s3://eyeem-configuration-management/ provisioning-${puppetbranch}/base.user-data" > ./base.shnelsen fetch_file "s3://eyeem-configuration-management/provisioning/base.user-data" > ./base.shnfinbash ./base.shn",! "ncurl -X PUT -H 'Content-Type:' --data-binary '{"Status":"SUCCESS","Reason":"we made it here.","UniqueId":"puppetwait","Data":"Its gonna be alright."}' '",! {! "Ref": "redis1puppetwaithandle"! },! "'"! ]! ]! }! }! },! "Type": "AWS::EC2::Instance"! },! "redis1puppetwaitcondition": {! "Properties": {! "Handle": {! "Ref": "redis1puppetwaithandle"! },! "Timeout": "7200"! },! "Type": "AWS::CloudFormation::WaitCondition"! },! "redis1puppetwaithandle": {! "Type": "AWS::CloudFormation::WaitConditionHandle"! },! "redissg": {! "Properties": {! "GroupDescription": "redis",! "SecurityGroupIngress": [! {! "FromPort": "6379",! "IpProtocol": "tcp",! "SourceSecurityGroupName": {! "Ref": "backendsg"! },! "ToPort": "6379"! },! {! "CidrIp": "0.0.0.0/0",! "FromPort": "22",! "IpProtocol": "tcp",! "ToPort": "22"! }! ],! "Tags": [! {! "Key": "branch",! "Value": "feature_x"! },! {! "Key": "monitoring",! "Value": "false"! },! {! "Key": "puppetbranch",! "Value": "master"! },! {! "Key": "role",! "Value": "redis"! }! ]! },! "Type": "AWS::EC2::SecurityGroup"! }! }! }
  • 35. {! "Outputs": {! "ApiEndpoint": {! "Description": "DNS Endpoint to feature_xAPI staging",! "Value": {! "Ref": "apiendpoint"! }! },! "backend1PrivateDNS": {! "Description": "Private DNSName of the newly created EC2 backend1 instance",! "Value": {! "Fn::GetAtt": [! "backend1",! "PrivateDnsName"! ]! }! },! "backend1PublicDNS": {! "Description": "Public DNSName of the newly created EC2 backend1 instance",! "Value": {! "Fn::GetAtt": [! "backend1",! "PublicDnsName"! ]! }! },! "db1PrivateDNS": {! "Description": "Private DNSName of the newly created EC2 db1 instance",! "Value": {! "Fn::GetAtt": [! "db1",! "PrivateDnsName"! ]! }! },! "db1PublicDNS": {! "Description": "Public DNSName of the newly created EC2 db1 instance",! "Value": {! "Fn::GetAtt": [! "db1",! "PublicDnsName"! ]! }! },! "redis1PrivateDNS": {! "Description": "Private DNSName of the newly created EC2 redis1 instance",! "Value": {! "Fn::GetAtt": [! "redis1",! "PrivateDnsName"! ]! }! },! "redis1PublicDNS": {! "Description": "Public DNSName of the newly created EC2 redis1 instance",! "Value": {! "Fn::GetAtt": [! "redis1",! "PublicDnsName"! ]! }! }! },! "Resources": {! "apiendpoint": {! "Properties": {! "HostedZoneId": "Z3HTG0V9588TAA",! "Name": "api.feature_x.eyeem.com.",! "ResourceRecords": [! {! "Fn::GetAtt": [! "backend1",! "PublicDnsName"! ]! }! ],! "TTL": 300,! "Type": "CNAME"! },! "Type": "AWS::Route53::RecordSet"! },! "backend1": {! "Properties": {! "IamInstanceProfile": {! "Ref": "puppetprovisioningprofile"! },! "ImageId": "ami-f2191786",! "InstanceType": "c3.large",! "KeyName": "eyeem-prod-new",! "SecurityGroups": [! {! "Ref": "backendsg"! },! "base"! ],! "Tags": [! {! "Key": "background_tasks",! "Value": "false"! },! {! "Key": "branch",! "Value": "feature_x"! },! {! "Key": "jenkins_access",! "Value": ""! },! {! "Key": "puppetbranch",! "Value": "master"! },! {! "Key": "service_discovery",! "Value": "true"! }! ],! "UserData": {! "Fn::Base64": {! "Fn::Join": [! "",! [! {! "Ref": "backend1puppetwaithandle"! },! "'"! ]! ]! }! }! },! "Type": "AWS::EC2::Instance"! },! "backend1puppetwaitcondition": {! "Properties": {! "Handle": {! "Ref": "backend1puppetwaithandle"! },! "Timeout": "7200"! },! "Type": "AWS::CloudFormation::WaitCondition"! },! "backend1puppetwaithandle": {! "Type": "AWS::CloudFormation::WaitConditionHandle"! },! "backendsg": {! "Properties": {! "GroupDescription": "backend",! "SecurityGroupIngress": [! {! "CidrIp": "0.0.0.0/0",! "FromPort": "22",! "IpProtocol": "tcp",! "ToPort": "22"! },! {! "CidrIp": "0.0.0.0/0",! "FromPort": "80",! "IpProtocol": "tcp",! "ToPort": "80"! }! ],! "Tags": [! {! "Key": "branch",! "Value": "feature_x"! },! {! "Key": "monitoring",! "Value": "false"! },! {! "Key": "puppetbranch",! "Value": "master"! },! {! "Key": "role",! "Value": "backend"! }! ]! },! "Type": "AWS::EC2::SecurityGroup"! },! "db1": {! "Properties": {! "IamInstanceProfile": {! "Ref": "dbprovisioningprofile"! },! "ImageId": "ami-25488752",! "InstanceType": "c3.large",! "KeyName": "eyeem-prod-new",! "SecurityGroups": [! {! "Ref": "dbsg"! },!
  • 36. –json.org “JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate.”
  • 37. –json.org “JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate.”
  • 38. eyeemstack create --machines backend db feed --restore_db extract --branch feature_x • Python tool on top of troposphere, a python library to create CloudFormation descriptions
  • 40. class eyeem::profiles::backend::deploy {! eyeem::deploy_codebase { “backend”:! directory => ‘/var/www/backend’,! bucket => ‘eyeem-web-backend’,! filename => “backend-${::branch}.tar.gz”,! restart => [‘nginx’, ’php5-fpm’]! }! }! ! ! ! define eyeem::deploy_codebase (! $prefix = '',! $directory,! $bucket,! $filename,! $restart ) {! ! if (member($::mountpoints, “${directory}/current”) and $::environment == ‘local’) {! notice(“Looks like we are on Vagrant and you mounted the code in, skipping deploy.”)! } else {! ( . . . )! }! }
  • 41.
  • 42. • ~70 Cents for a single test run. • ~3.50 $ per workday. • ~17.64 $ for always on staging per day. • Tests disaster recovery on a sample dataset. • Scalable setup. • < 10 minutes
  • 43. • Stagings just a click away.
  • 44. Backend Security Group role=backend Base Security Group Metrics Security Group role=metrics Allow Inbound Base 8125 production branch=master feature_x staging branch=feature_x Backend Security Group role=backend Base Security Group Inventory Service Security Group role=inventory InstanceInstance branch=feature_x public_dns=api.feature_x.eyeem.com branch=master public_dns=api.eyeem.com
  • 45. Backend Security Group role=backend Base Security Group Metrics Security Group role=metrics Allow Inbound Base 8125 production branch=master feature_x staging branch=feature_x Backend Security Group role=backend Base Security Group Inventory Service Security Group role=inventory InstanceInstance branch=feature_x public_dns=api.feature_x.eyeem.com branch=master public_dns=api.eyeem.com Jobrunner Service Security Group role=jobrunner
  • 46.
  • 48. • ~350 Job Executions last month • 350 times self service operations • Stagings everywhere • Definition of Done: Can you boot it up using EyeEmStack and Vagrant? • Lots of 99.999s%
  • 49. • “Everything fails all the time.” • Test your repairs, automate everything. • Distribute your data. • Applications should be able to handle state transitions of service-parts and diagnose failure. • Design your infrastructure towards acting as a service provider to your developers.