SlideShare a Scribd company logo
1 of 94
Download to read offline
DevOps in PHP environment
1
Who?!
Gabriel Koerich
Over 10 years of experience in PHP and 6 in Laravel
Founder of Bulldesk, responsible for finance and technology
gabriel@bulldesk.com.br
twi3er.com/gabrielmkoerich
github.com/gabrielkoerich
2
3
Who?!
Evaldo Felipe
Blackops @ Neoway
8 years of SysAdmin
2,5 years of DevOps
contato@evaldofelipe.com
twi1er.com/evaldofelipe
4
5
Agenda
• PHP Sucks?!
• Workflow
• Infrastructure
• Tools
• Issues and Fixes
6
PHP Sucks?!
7
PHP Sucks?!
• Easy for beginners
• Easy to "deploy"
• PHP mixed in HTML
• No conven>ons for func>on names
• Wordpress
8
I don't know how to stop it, there
was never any intent to write a
programming language
— Rasmus Lerdorf
9
PHP Evolu)on
Version Evolu,on
< 5.3 !
5.3 Namespaces, closures
5.4 Traits, [] for arrays
5.5 OPCache, finally on try blocks
5.6 Argument unpacking (...$args)
6.0 "
7.0 Performance (thanks to HHVM), return and scalar types,
improved excepPons
7.1 Nullable types (?int), catch mulPple excepPons
10
I have absolutely no idea how to
write a programming language, I just
kept adding the next logical step on
the way.
— Rasmus Lerdorf
11
Community Evolu-on
Autoloaders, Composer & Packagist
Frameworks (Zend, Symfony, Laravel)
PHP FIG and PSRs
Standards
PSR-1: Basic Coding
PSR-2: Coding Style Guide
PSR-3: Logger Interface
PSR-4: Autoloader
PSR-5: Caching Interface
12
Modern PHP
/**
* Create a new instance.
*/
public function __construct(AutomationRepository $automations)
{
$this->automations = $automations;
}
/**
* @Get("automation", as="automation.index")
*/
public function index(Request $request): Response
{
if ($request->expectsJson())) {
return $this->automations->getActive()->pluck('name', 'id');
}
$automations = $this->automations->categorized($request->input('categories'))
->orderBy('name')
->paginate(50);
return new Response(view('pages.automation.index')->with(compact('automations')), 200);
}
13
Laravel Features
• Routes & Controllers
• Service Container & Dependency Injec9on
• Migra9ons & ORM
• Ar9san command line
• Queues (beanstalkd, redis, amazon sqs)
• Broadcas9ng (Pusher or socket.io)
14
Development Workflow &
Source Management
15
Development Workflow & Source
Management
• People
• Workflow
• Rules, code pa4erns, PSRs
• Local environment
• Database dump Migra@ons / Seeds
16
Github Flow
• Anything in master is deployable
• Every new branch should be created off of master
• Branches must have descrip<ve names (create-cache-manager,
improve-auth, refactor-acl)
• Pull requests must be reviewed by at least 2 people
• When ready, you should merge and deploy immediately
17
Github Flow
18
Bulldesk Guidelines
19
20
Local Environment
21
Laravel Valet
# Install PHP/Composer/MySQL/Redis local
# On MacOS
$ composer global require laravel/valet
# On Linux
$ composer global require cpriego/valet-linux
$ valet install
$ cd ~/Projects && valet park
# All directories in ~/Projects will be acessible at http://{folder}.test
22
Vessel (Docker)
PHP 7.2, MySQL 5.7, Redis & NodeJS with NPM, Yarn &
Gulp
# Install docker
$ composer require shipping-docker/vessel
# Register VesselVesselServiceProvide if not on Laravel 5.5
$ php artisan vendor:publish --provider="VesselVesselServiceProvider"
$ bash vessel init
$ ./vessel start
# Acessible at http://localhost
23
Con$nuous Integra$on
24
Con$nuous Integra$on
• Tests
• Code coverage
• Code quality
25
26
27
28
Produc'on/QA Environment
29
Provision/Deploy
• Mul% Servers / Instances
• Con%nuous Deploy
• Zero down%me
• Database Replica%on
• PHP 7.2
• SSL & hFp2
30
31
32
33
Recipes
34
35
Firewall Rules
ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:mysql
ACCEPT udp -- 10.132.103.204 anywhere udp dpt:mysql
ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:postgresql
ACCEPT udp -- 10.132.103.204 anywhere udp dpt:postgresql
ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:11211
ACCEPT udp -- 10.132.103.204 anywhere udp dpt:11211
ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:6379
ACCEPT udp -- 10.132.103.204 anywhere udp dpt:6379
ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:11300
ACCEPT udp -- 10.132.103.204 anywhere udp dpt:11300
36
37
38
Beanstalkd queues + Supervisor
39
40
Issue
Laravel doesn't understand that the request
came from a client and not from the load
balancer
41
Trusted Proxy
$ composer require fideloper/proxy
# Register FideloperProxyTrustedProxyServiceProvider
$ php artisan vendor:publish --provider="FideloperProxyTrustedProxyServiceProvider"
// Http/Kernel.php
protected $middleware = [
//...
FideloperProxyTrustProxies::class,
];
// config/trustedproxy.php
return [
'proxies' => [
'192.168.10.10', // Load balancer's IP address
],
//...
42
Issue
How to serve some files from a single server?
43
Nginx Websocket Proxy
upstream websocket {
least_conn;
server 10.xx.xx.xx:2095; #websocket server ip
}
location /socket.io {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
}
44
Database Replica-on
45
Master/Slave Config
//...
'connections' => [
'mysql' => [
'write' => [
'host' => env('DB_WRITE_HOST', env('DB_HOST', '127.0.0.1')),
],
'read' => [
'host' => [
env('DB_WRITE_HOST', env('DB_HOST', '127.0.0.1')),
env('DB_READ_HOST', env('DB_HOST', '127.0.0.1')),
],
],
'backup' => [
'host' => env('DB_BACKUP_HOST', env('DB_READ_HOST', '127.0.0.1')),
'arguments' => '--single-transaction --skip-tz-utc',
],
//...
];
46
47
48
49
50
.env
REDIS_HOST=
BEANSTALKD_HOST=
DB_HOST=
DB_WRITE_HOST=
DB_READ_HOST=
DB_BACKUP_HOST=
DB_NAME=
DB_USER=
DB_PASSWORD=
CACHE_DRIVER=redis
SESSION_DRIVER=redis
51
52
53
54
55
56
57
Monitoring, Security & Op2miza2on
58
Monitoring, Security & Op2miza2on
• CDN
• Monitors
• Logs e excep3ons centralized
• Backups
• Load tests
59
60
61
/**
* Set the CloudFlare conneting IP and https if applied.
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (! app()->environment('production')) {
return $next($request);
}
if ($request->server->has('HTTP_CF_CONNECTING_IP')) {
if ($request->isSecure()) {
$request->server->set('HTTPS', true);
}
$request->server->set('REMOTE_ADDR', $request->server->get('HTTP_CF_CONNECTING_IP'));
return $next($request);
}
logf('CF: Blocked request to %s from %s', [$request->fullUrl(), $request->ip()]);
return new Response('', 404);
}
62
63
Issue
How to clear this cache automa0cally?
64
/**
* Get the path to a versioned asset file.
*
* @param string $asset
* @return string
*/
function versioned($asset)
{
static $production, $base, $deploy, $sha;
$production = app()->environment('production');
if (is_null($base)) {
$base = $production ? 'https://static.bulldesk.com.br/' : '/';
}
if ($production === false) {
return $base.$asset . '?v=' . str_random(3);
}
if (is_null($deploy)) {
$deploy = public_path('build/deploy');
}
if (is_null($sha) && file_exists($deploy)) {
$sha = file_get_contents($deploy);
}
if (! empty($sha)) {
return $base.$asset . '?v='.$sha;
}
return $base.$asset;
}
<script src="{{ versioned('build/scripts/app.js') }}"></script> //https://static.bulldesk.com.br/build/scripts/app.js?v=fbe06e04c4f8ddd1c94c63f3a001807bace679e0
65
Monitoring
66
67
68
69
70
71
Issue
How to centralize logs and excep3ons?
72
73
74
// LogServiceProvider.php
/**
* The papertrail log format.
*
* @var string
*/
protected $papertrailFormat = '%channel%.%level_name%: %message% %extra%';
/**
* Configure the application's logging facilities.
*
* @return void
*/
public function boot()
{
if ($this->app->environment('production', 'staging')) {
$syslog = new MonologHandlerSyslogHandler('laravel');
$formatter = new MonologFormatterLineFormatter($this->papertrailFormat);
$syslog->setFormatter($formatter);
$this->app['log']->getMonolog()->pushHandler($syslog);
}
}
75
76
77
78
79
80
Backups
$ composer require backup-manager/backup-manager
# OR
$ composer require backup-manager/laravel
# OR
$ composer require spatie/laravel-backup
81
(...)
/**
* Execute the backup command.
*
* @return void
*/
public function handle()
{
$database = $this->option('database') ?: 'mysql';
$destination = $this->option('destination') ?: 's3';
$destinationPath = 'dump_'. (new Carbon)->format('Y_m_d_H_i_s').'.sql';
$compression = 'gzip';
$this->info('Dumping database and uploading...');
$destinations = [new Destination($destination, $destinationPath)];
$this->backupProcedure->run($database, $destinations, $compression);
$completePath = 'database/' . $destinationPath;
$this->info(sprintf('Successfully dumped %s, compressed with %s and store it to %s at %s',
$database,
$compression,
$destination,
$completePath
));
$last = new Carbon('last day of this month');
// Delete file in 10 days if this not the last
if ((new Carbon)->isSameAs('d/m/Y', $last)) {
$this->info('Scheduled job to delete the backup file ' . $completePath . ' in 10 days.');
dispatch((new DeleteFile($completePath . '.gz', 's3_backup'))->delay(24 * 60 * 60 * 10));
}
}
82
Then
83
Now
84
Lessons Learned
85
1. Don't op*mize or escale
prematurely, but be prepared for
this.
86
2. Time is money.
87
3. Use microservices only if you can
maintain them.
88
4. Study/learn and enjoy everything
the internet gives you for free.
89
90
91
Thanks!
92
We're hiring!
Ques%ons?
bulldesk.com.br
gabriel@bulldesk.com.br
twi3er.com/gabrielmkoerich
93
Ref
en.wikiquote.org/wiki/Rasmus_Lerdorf
guides.github.com/introduc9on/flow
github.com/gabrielkoerich/guidelines
vessel.shippingdocker.com
docs.spa9e.be/laravel-backup
gabrielkoerich.com/talks/infra
php-fig.org
94

More Related Content

What's hot

How to deploy node to production
How to deploy node to productionHow to deploy node to production
How to deploy node to production
Sean Hess
 

What's hot (20)

Composer, putting dependencies on the score
Composer, putting dependencies on the scoreComposer, putting dependencies on the score
Composer, putting dependencies on the score
 
Composer: putting dependencies on the score
Composer: putting dependencies on the scoreComposer: putting dependencies on the score
Composer: putting dependencies on the score
 
Composer for busy developers - DPC13
Composer for busy developers - DPC13Composer for busy developers - DPC13
Composer for busy developers - DPC13
 
Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn Flow
 
Statyczna analiza kodu PHP
Statyczna analiza kodu PHPStatyczna analiza kodu PHP
Statyczna analiza kodu PHP
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
 
Information security programming in ruby
Information security programming in rubyInformation security programming in ruby
Information security programming in ruby
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
Gearman work queue in php
Gearman work queue in phpGearman work queue in php
Gearman work queue in php
 
Better detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codeBetter detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 code
 
Converting Your Dev Environment to a Docker Stack - php[world]
Converting Your Dev Environment to a Docker Stack - php[world]Converting Your Dev Environment to a Docker Stack - php[world]
Converting Your Dev Environment to a Docker Stack - php[world]
 
How to deploy node to production
How to deploy node to productionHow to deploy node to production
How to deploy node to production
 
Php through the eyes of a hoster confoo
Php through the eyes of a hoster confooPhp through the eyes of a hoster confoo
Php through the eyes of a hoster confoo
 
Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.
 
Debugging PHP with Xdebug - PHPUK 2018
Debugging PHP with Xdebug - PHPUK 2018Debugging PHP with Xdebug - PHPUK 2018
Debugging PHP with Xdebug - PHPUK 2018
 
Everything as a code
Everything as a codeEverything as a code
Everything as a code
 

Similar to DevOps in PHP environment

Tips
TipsTips
Tips
mclee
 
2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku
ronnywang_tw
 
Facebook的缓存系统
Facebook的缓存系统Facebook的缓存系统
Facebook的缓存系统
yiditushe
 

Similar to DevOps in PHP environment (20)

DevOps in PHP environment
DevOps in PHP environmentDevOps in PHP environment
DevOps in PHP environment
 
Control your deployments with Capistrano
Control your deployments with CapistranoControl your deployments with Capistrano
Control your deployments with Capistrano
 
Pecl Picks
Pecl PicksPecl Picks
Pecl Picks
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php Presentation
 
Drupaljam 2017 - Deploying Drupal 8 onto Hosted Kubernetes in Google Cloud
Drupaljam 2017 - Deploying Drupal 8 onto Hosted Kubernetes in Google CloudDrupaljam 2017 - Deploying Drupal 8 onto Hosted Kubernetes in Google Cloud
Drupaljam 2017 - Deploying Drupal 8 onto Hosted Kubernetes in Google Cloud
 
Chef - industrialize and automate your infrastructure
Chef - industrialize and automate your infrastructureChef - industrialize and automate your infrastructure
Chef - industrialize and automate your infrastructure
 
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, OrchestrationThe Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
 
Next Generation DevOps in Drupal: DrupalCamp London 2014
Next Generation DevOps in Drupal: DrupalCamp London 2014Next Generation DevOps in Drupal: DrupalCamp London 2014
Next Generation DevOps in Drupal: DrupalCamp London 2014
 
Lumen
LumenLumen
Lumen
 
Infrastructure = code - 1 year later
Infrastructure = code - 1 year laterInfrastructure = code - 1 year later
Infrastructure = code - 1 year later
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
Harmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetHarmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and Puppet
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Running Docker in Development & Production (#ndcoslo 2015)
Running Docker in Development & Production (#ndcoslo 2015)Running Docker in Development & Production (#ndcoslo 2015)
Running Docker in Development & Production (#ndcoslo 2015)
 
Dockerize Laravel Application
Dockerize Laravel ApplicationDockerize Laravel Application
Dockerize Laravel Application
 
Tips
TipsTips
Tips
 
Wordpress y Docker, de desarrollo a produccion
Wordpress y Docker, de desarrollo a produccionWordpress y Docker, de desarrollo a produccion
Wordpress y Docker, de desarrollo a produccion
 
2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku2012 coscup - Build your PHP application on Heroku
2012 coscup - Build your PHP application on Heroku
 
Docker Security workshop slides
Docker Security workshop slidesDocker Security workshop slides
Docker Security workshop slides
 
Facebook的缓存系统
Facebook的缓存系统Facebook的缓存系统
Facebook的缓存系统
 

Recently uploaded

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Recently uploaded (20)

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 

DevOps in PHP environment

  • 1. DevOps in PHP environment 1
  • 2. Who?! Gabriel Koerich Over 10 years of experience in PHP and 6 in Laravel Founder of Bulldesk, responsible for finance and technology gabriel@bulldesk.com.br twi3er.com/gabrielmkoerich github.com/gabrielkoerich 2
  • 3. 3
  • 4. Who?! Evaldo Felipe Blackops @ Neoway 8 years of SysAdmin 2,5 years of DevOps contato@evaldofelipe.com twi1er.com/evaldofelipe 4
  • 5. 5
  • 6. Agenda • PHP Sucks?! • Workflow • Infrastructure • Tools • Issues and Fixes 6
  • 8. PHP Sucks?! • Easy for beginners • Easy to "deploy" • PHP mixed in HTML • No conven>ons for func>on names • Wordpress 8
  • 9. I don't know how to stop it, there was never any intent to write a programming language — Rasmus Lerdorf 9
  • 10. PHP Evolu)on Version Evolu,on < 5.3 ! 5.3 Namespaces, closures 5.4 Traits, [] for arrays 5.5 OPCache, finally on try blocks 5.6 Argument unpacking (...$args) 6.0 " 7.0 Performance (thanks to HHVM), return and scalar types, improved excepPons 7.1 Nullable types (?int), catch mulPple excepPons 10
  • 11. I have absolutely no idea how to write a programming language, I just kept adding the next logical step on the way. — Rasmus Lerdorf 11
  • 12. Community Evolu-on Autoloaders, Composer & Packagist Frameworks (Zend, Symfony, Laravel) PHP FIG and PSRs Standards PSR-1: Basic Coding PSR-2: Coding Style Guide PSR-3: Logger Interface PSR-4: Autoloader PSR-5: Caching Interface 12
  • 13. Modern PHP /** * Create a new instance. */ public function __construct(AutomationRepository $automations) { $this->automations = $automations; } /** * @Get("automation", as="automation.index") */ public function index(Request $request): Response { if ($request->expectsJson())) { return $this->automations->getActive()->pluck('name', 'id'); } $automations = $this->automations->categorized($request->input('categories')) ->orderBy('name') ->paginate(50); return new Response(view('pages.automation.index')->with(compact('automations')), 200); } 13
  • 14. Laravel Features • Routes & Controllers • Service Container & Dependency Injec9on • Migra9ons & ORM • Ar9san command line • Queues (beanstalkd, redis, amazon sqs) • Broadcas9ng (Pusher or socket.io) 14
  • 16. Development Workflow & Source Management • People • Workflow • Rules, code pa4erns, PSRs • Local environment • Database dump Migra@ons / Seeds 16
  • 17. Github Flow • Anything in master is deployable • Every new branch should be created off of master • Branches must have descrip<ve names (create-cache-manager, improve-auth, refactor-acl) • Pull requests must be reviewed by at least 2 people • When ready, you should merge and deploy immediately 17
  • 20. 20
  • 22. Laravel Valet # Install PHP/Composer/MySQL/Redis local # On MacOS $ composer global require laravel/valet # On Linux $ composer global require cpriego/valet-linux $ valet install $ cd ~/Projects && valet park # All directories in ~/Projects will be acessible at http://{folder}.test 22
  • 23. Vessel (Docker) PHP 7.2, MySQL 5.7, Redis & NodeJS with NPM, Yarn & Gulp # Install docker $ composer require shipping-docker/vessel # Register VesselVesselServiceProvide if not on Laravel 5.5 $ php artisan vendor:publish --provider="VesselVesselServiceProvider" $ bash vessel init $ ./vessel start # Acessible at http://localhost 23
  • 25. Con$nuous Integra$on • Tests • Code coverage • Code quality 25
  • 26. 26
  • 27. 27
  • 28. 28
  • 30. Provision/Deploy • Mul% Servers / Instances • Con%nuous Deploy • Zero down%me • Database Replica%on • PHP 7.2 • SSL & hFp2 30
  • 31. 31
  • 32. 32
  • 33. 33
  • 35. 35
  • 36. Firewall Rules ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:mysql ACCEPT udp -- 10.132.103.204 anywhere udp dpt:mysql ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:postgresql ACCEPT udp -- 10.132.103.204 anywhere udp dpt:postgresql ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:11211 ACCEPT udp -- 10.132.103.204 anywhere udp dpt:11211 ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:6379 ACCEPT udp -- 10.132.103.204 anywhere udp dpt:6379 ACCEPT tcp -- 10.132.103.204 anywhere tcp dpt:11300 ACCEPT udp -- 10.132.103.204 anywhere udp dpt:11300 36
  • 37. 37
  • 38. 38
  • 39. Beanstalkd queues + Supervisor 39
  • 40. 40
  • 41. Issue Laravel doesn't understand that the request came from a client and not from the load balancer 41
  • 42. Trusted Proxy $ composer require fideloper/proxy # Register FideloperProxyTrustedProxyServiceProvider $ php artisan vendor:publish --provider="FideloperProxyTrustedProxyServiceProvider" // Http/Kernel.php protected $middleware = [ //... FideloperProxyTrustProxies::class, ]; // config/trustedproxy.php return [ 'proxies' => [ '192.168.10.10', // Load balancer's IP address ], //... 42
  • 43. Issue How to serve some files from a single server? 43
  • 44. Nginx Websocket Proxy upstream websocket { least_conn; server 10.xx.xx.xx:2095; #websocket server ip } location /socket.io { proxy_pass http://websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; send_timeout 300; } 44
  • 46. Master/Slave Config //... 'connections' => [ 'mysql' => [ 'write' => [ 'host' => env('DB_WRITE_HOST', env('DB_HOST', '127.0.0.1')), ], 'read' => [ 'host' => [ env('DB_WRITE_HOST', env('DB_HOST', '127.0.0.1')), env('DB_READ_HOST', env('DB_HOST', '127.0.0.1')), ], ], 'backup' => [ 'host' => env('DB_BACKUP_HOST', env('DB_READ_HOST', '127.0.0.1')), 'arguments' => '--single-transaction --skip-tz-utc', ], //... ]; 46
  • 47. 47
  • 48. 48
  • 49. 49
  • 50. 50
  • 52. 52
  • 53. 53
  • 54. 54
  • 55. 55
  • 56. 56
  • 57. 57
  • 58. Monitoring, Security & Op2miza2on 58
  • 59. Monitoring, Security & Op2miza2on • CDN • Monitors • Logs e excep3ons centralized • Backups • Load tests 59
  • 60. 60
  • 61. 61
  • 62. /** * Set the CloudFlare conneting IP and https if applied. * * @param IlluminateHttpRequest $request * @param Closure $next * @return mixed */ public function handle($request, Closure $next) { if (! app()->environment('production')) { return $next($request); } if ($request->server->has('HTTP_CF_CONNECTING_IP')) { if ($request->isSecure()) { $request->server->set('HTTPS', true); } $request->server->set('REMOTE_ADDR', $request->server->get('HTTP_CF_CONNECTING_IP')); return $next($request); } logf('CF: Blocked request to %s from %s', [$request->fullUrl(), $request->ip()]); return new Response('', 404); } 62
  • 63. 63
  • 64. Issue How to clear this cache automa0cally? 64
  • 65. /** * Get the path to a versioned asset file. * * @param string $asset * @return string */ function versioned($asset) { static $production, $base, $deploy, $sha; $production = app()->environment('production'); if (is_null($base)) { $base = $production ? 'https://static.bulldesk.com.br/' : '/'; } if ($production === false) { return $base.$asset . '?v=' . str_random(3); } if (is_null($deploy)) { $deploy = public_path('build/deploy'); } if (is_null($sha) && file_exists($deploy)) { $sha = file_get_contents($deploy); } if (! empty($sha)) { return $base.$asset . '?v='.$sha; } return $base.$asset; } <script src="{{ versioned('build/scripts/app.js') }}"></script> //https://static.bulldesk.com.br/build/scripts/app.js?v=fbe06e04c4f8ddd1c94c63f3a001807bace679e0 65
  • 67. 67
  • 68. 68
  • 69. 69
  • 70. 70
  • 71. 71
  • 72. Issue How to centralize logs and excep3ons? 72
  • 73. 73
  • 74. 74
  • 75. // LogServiceProvider.php /** * The papertrail log format. * * @var string */ protected $papertrailFormat = '%channel%.%level_name%: %message% %extra%'; /** * Configure the application's logging facilities. * * @return void */ public function boot() { if ($this->app->environment('production', 'staging')) { $syslog = new MonologHandlerSyslogHandler('laravel'); $formatter = new MonologFormatterLineFormatter($this->papertrailFormat); $syslog->setFormatter($formatter); $this->app['log']->getMonolog()->pushHandler($syslog); } } 75
  • 76. 76
  • 77. 77
  • 78. 78
  • 79. 79
  • 80. 80
  • 81. Backups $ composer require backup-manager/backup-manager # OR $ composer require backup-manager/laravel # OR $ composer require spatie/laravel-backup 81
  • 82. (...) /** * Execute the backup command. * * @return void */ public function handle() { $database = $this->option('database') ?: 'mysql'; $destination = $this->option('destination') ?: 's3'; $destinationPath = 'dump_'. (new Carbon)->format('Y_m_d_H_i_s').'.sql'; $compression = 'gzip'; $this->info('Dumping database and uploading...'); $destinations = [new Destination($destination, $destinationPath)]; $this->backupProcedure->run($database, $destinations, $compression); $completePath = 'database/' . $destinationPath; $this->info(sprintf('Successfully dumped %s, compressed with %s and store it to %s at %s', $database, $compression, $destination, $completePath )); $last = new Carbon('last day of this month'); // Delete file in 10 days if this not the last if ((new Carbon)->isSameAs('d/m/Y', $last)) { $this->info('Scheduled job to delete the backup file ' . $completePath . ' in 10 days.'); dispatch((new DeleteFile($completePath . '.gz', 's3_backup'))->delay(24 * 60 * 60 * 10)); } } 82
  • 86. 1. Don't op*mize or escale prematurely, but be prepared for this. 86
  • 87. 2. Time is money. 87
  • 88. 3. Use microservices only if you can maintain them. 88
  • 89. 4. Study/learn and enjoy everything the internet gives you for free. 89
  • 90. 90
  • 91. 91