hopping in clouds - phpuk 17

136
Hopping a tale of migration from one cloud provider to another in Clouds

Upload: michele-orselli

Post on 23-Feb-2017

100 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Hopping in clouds - phpuk 17

Hopping

a tale of migration from one cloud provider to another

in Clouds

Page 2: Hopping in clouds - phpuk 17

Michele OrselliCTO@Ideato

_orso_

micheleorselli / ideatosrl

[email protected]

Page 3: Hopping in clouds - phpuk 17
Page 4: Hopping in clouds - phpuk 17
Page 5: Hopping in clouds - phpuk 17
Page 6: Hopping in clouds - phpuk 17
Page 7: Hopping in clouds - phpuk 17
Page 8: Hopping in clouds - phpuk 17
Page 9: Hopping in clouds - phpuk 17

Let’s start from the beginning…

Page 10: Hopping in clouds - phpuk 17
Page 11: Hopping in clouds - phpuk 17

What do we Italians like?

Page 12: Hopping in clouds - phpuk 17
Page 13: Hopping in clouds - phpuk 17
Page 14: Hopping in clouds - phpuk 17
Page 15: Hopping in clouds - phpuk 17
Page 16: Hopping in clouds - phpuk 17

“Italians lose wars as if they were football matches, and football matches as if they were wars”

Winston Churchill

Page 17: Hopping in clouds - phpuk 17
Page 18: Hopping in clouds - phpuk 17

Peaks on gen - jun - aug up to 70 M pg/mth

Peaks during big matches

Page 19: Hopping in clouds - phpuk 17
Page 20: Hopping in clouds - phpuk 17

PaaS

IaaS

SaaS

Page 21: Hopping in clouds - phpuk 17

PaaS

IaaS

SaaS

Page 22: Hopping in clouds - phpuk 17

PaaS Platform as a Service

Zero configuration (almost)

Push the code “on the cloud” and you’re done

Page 23: Hopping in clouds - phpuk 17
Page 24: Hopping in clouds - phpuk 17

Hard limits on resource (e.g 50 db con)

Deploy via ftp on shared nfs dir (sf cache mess)

Blackbox: No realtime log, no access

PHP 5.3

Page 25: Hopping in clouds - phpuk 17

Web: all articles categories, team details, ...

symfony1

Page 26: Hopping in clouds - phpuk 17

Mobile: all articles categories, team details, ...

Sf2 components

Page 27: Hopping in clouds - phpuk 17

Community Site with user generated content

Symfony2

Page 28: Hopping in clouds - phpuk 17

μServices

Page 29: Hopping in clouds - phpuk 17
Page 30: Hopping in clouds - phpuk 17

Macro services

Page 31: Hopping in clouds - phpuk 17

Talk: api for comments, votes, ratings

Symfony2

Page 32: Hopping in clouds - phpuk 17

Adv: api for serving ads

Symfony2

Page 33: Hopping in clouds - phpuk 17

Media: api for asset mgmt

Symfony2

Page 34: Hopping in clouds - phpuk 17
Page 35: Hopping in clouds - phpuk 17

The problems started with talk…

Page 36: Hopping in clouds - phpuk 17
Page 37: Hopping in clouds - phpuk 17

Quick wins

Tuning HTTP response headers

Caching more endpoints

Optimize queries

Page 38: Hopping in clouds - phpuk 17
Page 39: Hopping in clouds - phpuk 17

Tuning HTTP Headers

Page 40: Hopping in clouds - phpuk 17

1 $date = new \DateTime(); 2 $date->modify("+$lifetime seconds"); 3 4 $response->setExpires($date); 5 $response->setMaxAge($lifetime); 6 $response->setSharedMaxAge($lifetime);

Page 41: Hopping in clouds - phpuk 17
Page 42: Hopping in clouds - phpuk 17
Page 43: Hopping in clouds - phpuk 17

PaaS

IaaS

SaaS

Page 44: Hopping in clouds - phpuk 17

PaaS

IaaS

SaaS

Page 45: Hopping in clouds - phpuk 17

First candidate for migration was… the talk app

Page 46: Hopping in clouds - phpuk 17
Page 47: Hopping in clouds - phpuk 17

PHP from 5.3 to 5.6

Mysql from 5.0 to 5.6

Apache to nginx (+ php fpm)

Page 48: Hopping in clouds - phpuk 17

Web servers ip are dynamic

Can connect only through bastion

Share user sessions between servers

Page 49: Hopping in clouds - phpuk 17

Web servers ip are dynamic

Can connect only through bastion

Share user sessions between servers

Page 50: Hopping in clouds - phpuk 17

1 'hosts' => function () { 2 $c = Ec2Client::factory([ 3 'profile' => 'calciomercato', 4 'region' => 'eu-central-1', 5 ]); 6 7 $ips = new GetInstancesIps($c); 8 9 return $ips->execute(); 10 }

Page 51: Hopping in clouds - phpuk 17

1 public function execute() 2 { 3 $instances = $this->ec2Client 4 ->describeInstances( 5 [ 6 'DryRun' => false, 7 'Filters' => [ 8 [ 9 'Name' => 'instance.group-name', 10 'Values' => ['Web Public Auto-assign SG'], 11 ], 12 ], 13 ]); 14 15 return $instancesDescription->getPath( 16 'Reservations/*/Instances/*/NetworkInterfaces/*/PrivateIpAddresses/*/PrivateIpAddress' 18 ); 19 }

Page 52: Hopping in clouds - phpuk 17

Web servers ip are dynamic

Can connect only through bastion

Share user sessions between servers

Page 53: Hopping in clouds - phpuk 17

1 Host cmbastion 2 HostName xx.xx.xx.xx 3 User ec2-user 4 Port 9760 5 StrictHostKeyChecking no 6 UserKnownHostsFile /dev/null 7 IdentityFile ~/.ssh/cm_bastion.pem 8 LogLevel quiet

Page 54: Hopping in clouds - phpuk 17

10 Host 10.0.14.* 11 User centos 12 StrictHostKeyChecking no 13 UserKnownHostsFile /dev/null 14 IdentityFile ~/.ssh/cm_production.pem 15 ProxyCommand ssh -W %h:%p cmbastion 16 LogLevel quiet 17 18 Host 10.0.24.* 19 User centos 20 StrictHostKeyChecking no 21 UserKnownHostsFile /dev/null 22 IdentityFile ~/.ssh/cm_production.pem 23 ProxyCommand ssh -W %h:%p cmbastion 24 LogLevel quiet

Page 55: Hopping in clouds - phpuk 17

Web servers ip are dynamic

Can connect only through bastion

Share user sessions between servers

Page 56: Hopping in clouds - phpuk 17

Nginx static cache

Page 57: Hopping in clouds - phpuk 17

1 fastcgi_cache_key “$scheme$request_method$host$request_uri";

2 fastcgi_cache_lock on; 3 fastcgi_cache_revalidate on; 4 fastcgi_cache_valid 3m;

Page 58: Hopping in clouds - phpuk 17

1 if ($request_method ~ ^(POST|PUT|DELETE)$ ) { 2 set $no_cache 1; 3 } 4 5 if ($request_uri ~* "/api/queue") { 6 set $no_cache 1; 7 } 8 9 location ~ ^/(app|dev)\.php(/|$) { [..] 17 18 # Enable fastcgi_cache 19 add_header X-Cache $upstream_cache_status; 20 fastcgi_cache CALCIOMERCATO_TALK; 21 fastcgi_cache_bypass $no_cache; 22 fastcgi_no_cache $no_cache; 23 }

Page 59: Hopping in clouds - phpuk 17

8 9 location ~ ^/(app|dev)\.php(/|$) { 10 fastcgi_split_path_info ^(.+\.php)(/.*)$; 11 include fastcgi_params; 12 fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 13 fastcgi_param DOCUMENT_ROOT $realpath_root; 14 fastcgi_param HTTPS off; 15 fastcgi_index app.php; 16 fastcgi_intercept_errors on; 17 18 # Enable fastcgi_cache [..] 23 }

Page 60: Hopping in clouds - phpuk 17

Load test using old logs

Create AMI Images

Deploy latest version of the code

Switch DNS

Page 61: Hopping in clouds - phpuk 17
Page 62: Hopping in clouds - phpuk 17
Page 63: Hopping in clouds - phpuk 17
Page 64: Hopping in clouds - phpuk 17

The platform now runs on two clouds: RCS and AWS

Page 65: Hopping in clouds - phpuk 17

Backup

Page 66: Hopping in clouds - phpuk 17
Page 67: Hopping in clouds - phpuk 17

DB and Machine snapshotted every night

Copied to another region

Page 68: Hopping in clouds - phpuk 17

snapshot_id=` aws --profile snapshotdr rds describe-db-snapshots --db-instance-identifier $instance_identifier --region eu-central-1 | tail -n 1 | awk -F '{print $5}’ `

Page 69: Hopping in clouds - phpuk 17

aws rds copy-db-snapshot --source-db-snapshot-identifier arn:aws:rds:eu-central-1:$id:snapshot:$snapshot_id --region eu-west-1 --target-db-snapshot-identifier mysqlrds-snap-copy-$NOW --copy-tags

Page 70: Hopping in clouds - phpuk 17

snapshot_id=`aws --profile snapshotdr rds describe-db-snapshots --region eu-west-1 --db-instance-identifier $instance_identifier | head -n 1 | awk -F '{print $4}’`

aws rds delete-db-snapshot --region eu-west-1 --db-snapshot-identifier $snapshot_id

Page 71: Hopping in clouds - phpuk 17

Adv

Page 72: Hopping in clouds - phpuk 17

Only stateless apis

Small database small traffic

Infrastructure was already set

Easy!

Page 73: Hopping in clouds - phpuk 17

Created a Cloudfront distribution for

dynamic content (adv.calciomercato.com)

Page 74: Hopping in clouds - phpuk 17
Page 75: Hopping in clouds - phpuk 17

Mobile

Page 76: Hopping in clouds - phpuk 17

No database, it consumes data from other services

High impact, 40% of the total traffic

Page 77: Hopping in clouds - phpuk 17

How to deal with static assets?

Page 78: Hopping in clouds - phpuk 17

s3://com-calciomercato-cdn-mobile/

Page 79: Hopping in clouds - phpuk 17

Created 2 Cloudfront distribution

dynamic content (m.calciomercato.com)

static content (cdnmobile.calciomercato.com)

Page 80: Hopping in clouds - phpuk 17

Sync asset to s3 via s3cmd

s3cmd -m text/javascript --no-preserve sync /var/www/mobile/content/js s3://com-calciomercato-cdn-mobile/

Page 81: Hopping in clouds - phpuk 17

Deploy on a sample machine

Performance test based on log

Deploy

Rebuilding AMI

Switch DNS

Page 82: Hopping in clouds - phpuk 17

Tweaking assets caching

s3cmd --recursive modify --add-header='Cache-Control:max-age=3600' s3://com-calciomercato-cdn-mobile/assets/

Page 83: Hopping in clouds - phpuk 17

Tweaking assets caching

s3cmd --recursive modify --add-header='Cache-Control:max-age=3600' s3://com-calciomercato-cdn-mobile/assets/

Less CF -> S3 requests Less $$$

Page 84: Hopping in clouds - phpuk 17

Community

Page 85: Hopping in clouds - phpuk 17

Allows uses to create their own personal blog

First app that can be considered “complete”

Exposes api for user related stuff

Works as SSO

Page 86: Hopping in clouds - phpuk 17

Web servers ip are dynamic

Can connect only through bastion

Share user sessions between servers

Page 87: Hopping in clouds - phpuk 17
Page 88: Hopping in clouds - phpuk 17

1 services: 2 memcache: 3 class: Memcache 4 calls: 5 - [ addServer, [%memc_host%, %memc_port% ]] 6 session.handler.memcache: 7 class: 8 Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler 10 arguments: [ 11 @memcache, 12 { prefix: %session_memcache_prefix%, 13 expiretime: %session_memcache_expire% } 14 ]

Page 89: Hopping in clouds - phpuk 17

1 framework: 2 session: 3 handler_id: %session_handler_id%

Page 90: Hopping in clouds - phpuk 17

Deal with User Generated Content

Page 91: Hopping in clouds - phpuk 17

Created 2 Cloudfront distributions

dynamic content (vxl.calciomercato.com)

static content (cdnvxl.calciomercato.com)

Page 92: Hopping in clouds - phpuk 17

Gaufrette

Filesystem abstraction layer

http://knplabs.github.io/Gaufrette/

Page 93: Hopping in clouds - phpuk 17

1 knp_gaufrette: 2 adapters: 3 photo_storage: 4 aws_s3: 5 service_id: cdn.amazon_s3 6 bucket_name: %amazon_s3_bucket_name% 7 options: 8 directory: data 9 filesystems: 10 photo_storage: 11 adapter: photo_storage 12 alias: photo_storage_filesystem 13

Page 94: Hopping in clouds - phpuk 17

8 cdn.amazon_s3: 9 class: Aws\S3\S3Client 10 factory_class: Aws\S3\S3Client 11 factory_method: 'factory' 12 arguments: 13 - 14 key: %cdn.amazon_s3.aws_key% 15 secret: %cdn.amazon_s3.aws_secret_key% 16 region: eu-central-1

Page 95: Hopping in clouds - phpuk 17

7 class PhotoUploader 8 { [..] 27 public function upload(File $file, $dir) 28 { 29 $fullPath = $dir.'/'.$file->getFilename(); 30 31 if (!in_array($file->getMimeType(), self::$allowedTypes)) { 32 throw new \InvalidArgumentException($file->getMimeType()); 35 } 36 40 return $this->filesystem->write( 41 $fullPath, 42 file_get_contents($file->getPathname()) 43 ); 44 }

Page 96: Hopping in clouds - phpuk 17

7 class PhotoUploader 8 { [..] 27 public function upload(File $file, $dir) 28 { 29 $fullPath = $dir.'/'.$file->getFilename(); 30 31 if (!in_array($file->getMimeType(), self::$allowedTypes)) { 32 throw new \InvalidArgumentException($file->getMimeType()); 35 } 36 40 return $this->filesystem->write( 41 $fullPath, 42 file_get_contents($file->getPathname()) 43 ); 44 }

return $this->filesystem->write( 41 $fullPath, 42 file_get_contents($file->getPathname()) 43 );

Page 97: Hopping in clouds - phpuk 17

Deploy on a sample machine

Performance test based on log

Deploy

Rebuilding AMI

Copy User Assets on S3

Switch DNS

Page 98: Hopping in clouds - phpuk 17
Page 99: Hopping in clouds - phpuk 17

Web

Page 100: Hopping in clouds - phpuk 17

Oldest and biggest codebase

Proxy for mobile calls

High traffic 60%

Page 101: Hopping in clouds - phpuk 17

PHP 5.6 not supported by symfony 1

Page 102: Hopping in clouds - phpuk 17

Plan A: try to upgrade sf1 to support php 5.6

Plan B: deploy web on different machines

Page 103: Hopping in clouds - phpuk 17

https://github.com/LExpress/symfony1

Page 104: Hopping in clouds - phpuk 17

1 protected function camelize($text) 2 { 3 return preg_replace(array('#/(.?)#e', '/(^|_|-)+(.)/e'), array("'::'. 4 strtoupper('\\1')", "strtoupper('\\2')"), $text); 5 } 6 7 public static function camelize($text) 8 { 9 return strtr(ucwords(strtr($text, array('/' => 10 ':: ', '_' => ' ', '-' => ' '))), array(' ' => '')); 11 }

Page 105: Hopping in clouds - phpuk 17

Created 1 Cloudfront distribution for static content (cdnweb.calciomercato.com)

Page 106: Hopping in clouds - phpuk 17

https://blog.cloudflare.com/zone-apex-naked-domain-root-domain-cname-supp/

calciomercato.com => cmelb-463612445.eu-central-1.elb.amazonaws.com 

Page 107: Hopping in clouds - phpuk 17

Deploy on a sample machine

Performance test based on log

Deploy

Rebuilding AMI

Switch DNS

Page 108: Hopping in clouds - phpuk 17
Page 109: Hopping in clouds - phpuk 17

Media

Page 110: Hopping in clouds - phpuk 17

Only stateful api

Handles image thumbailing

Pretty big archive (70GB)

Page 111: Hopping in clouds - phpuk 17

1 public function generateThumbAndUploadToCdn(File $file, $width, $height) 2 { 3 $downloadedFile = $this->downloadFromFileManager($file); 4 5 $cdnKey = $this->generateThumbCdnKey($file, $width, $height); 6 $resizedFile = $this->resizeFilesystemImage($downloadedFile, $width, $height); 8 9 $optimizedFile = $this->optimizeImage($resizedFile); 10 11 $this->uploadFileToCdn($optimizedFile, $cdnKey) 12 13 $this->updateFileInfoTumbs($file, $width, $height, $cdnKey); 14 15 $this->deleteTemporaryFile($downloadedFile); 16 $this->deleteTemporaryFile($optimizedFile); 17 18 return true; 19 }

Page 112: Hopping in clouds - phpuk 17

Transfer from Rackspace CDN to S3

Page 113: Hopping in clouds - phpuk 17

#!/bin/bash login="USERNAME_FTP" pass="FTP_PASSWORD" host="HOST_FTP_RACKSPACE" remote_dir='/web/content/data' local_dir=“/var/www/vhosts/media.calciomercato.pro/data"base_name="$(basename "$0")"

lftp -u $login,$pass $host << EOF set ftp:ssl-allow no set mirror:use-pget-n 5

mirror -c -P5 --log="/var/log/$base_name.log" "$remote_dir" "$local_dir"

quit

Page 114: Hopping in clouds - phpuk 17
Page 115: Hopping in clouds - phpuk 17

1 public function slugifyFilename($text) 2 { 3 $text = preg_replace('~[^\\pL\d]+~u', '.', $text); 4 $text = trim($text, '-'); 5 6 if (function_exists('iconv')) { 7 $text = iconv('utf-8', 'us - ascii//TRANSLIT', $text); 8 } 9 10 $text = preg_replace('~[^-\w\.]+~', '', $text); 11 12 return $text; 13 }

Page 116: Hopping in clouds - phpuk 17
Page 117: Hopping in clouds - phpuk 17

Monitoring

Page 118: Hopping in clouds - phpuk 17

cloudwatch -> nagios -> catcicw retention max 2 sett

Page 119: Hopping in clouds - phpuk 17
Page 120: Hopping in clouds - phpuk 17

2 weeks retention: integration with cacti and nagios

Page 121: Hopping in clouds - phpuk 17

...and Slack

Page 122: Hopping in clouds - phpuk 17

Autoscaling

Page 123: Hopping in clouds - phpuk 17

2 autoscaling groups

3 metrics

- CPU % (> 70%)

- Response Time (> 100 ms)

- # of req/sec (> 10000)

Page 124: Hopping in clouds - phpuk 17
Page 125: Hopping in clouds - phpuk 17

Full migration took 1 year

Page 126: Hopping in clouds - phpuk 17

50% cost reduction

Page 127: Hopping in clouds - phpuk 17

This talk is not about blaming RCS…

Page 128: Hopping in clouds - phpuk 17

…simply it wasn’t suitable anymore for our needs :-)

Page 129: Hopping in clouds - phpuk 17
Page 130: Hopping in clouds - phpuk 17

Macro services FTW!

HTTP cache helped us a lot!

Measure measure measure

Page 131: Hopping in clouds - phpuk 17

Rationalising api: less call, less $$$

Reorganise frontend stuff

Get rid of sf1

Page 132: Hopping in clouds - phpuk 17

Upgrading to php7

Upgrading to ALB (HTTP/2)

Page 133: Hopping in clouds - phpuk 17
Page 134: Hopping in clouds - phpuk 17

Verona

Page 135: Hopping in clouds - phpuk 17

JsDay: May 10th-11thPHPDay: May 12th-13th

Verona

Page 136: Hopping in clouds - phpuk 17

Thank you!

https://joind.in/talk/cd6af

Michele OrselliCTO@Ideato

_orso_

micheleorselli / ideatosrl

[email protected]