python deployment with fabric 3401
TRANSCRIPT
-
8/3/2019 Python Deployment With Fabric 3401
1/30
Prodution Architectureand Deployment
with Fabric
- Andy McCurdy -@andymccurdy
-
8/3/2019 Python Deployment With Fabric 3401
2/30
Whiskey Media
-
8/3/2019 Python Deployment With Fabric 3401
3/30
Whiskey Sites
-
8/3/2019 Python Deployment With Fabric 3401
4/30
Your First Django App
-
8/3/2019 Python Deployment With Fabric 3401
5/30
Basic Config (web)
Apachemod_wsgi
use daemon mode
threads more efficientprocesses if you're unsure of thread safety
WSGIDaemonProcess my-site python-path=/home/code/processes=2 threads=150 maximum-requests=5000
WSGIProcessGroup my-site
WSGIScriptAlias / /home/code/my-site/deploy/wsgi/my-site.wsgi
-
8/3/2019 Python Deployment With Fabric 3401
6/30
Basic Config (media)
NginxUse Nginx to proxy traffic to ApacheMeanwhile Nginx serves media
upstream my-site {server 127.0.0.1:8000;
}server {
listen 80;
location ~ ^/media/ {root /home/code/my-site;expires 30d;
}location / {
proxy_pass http://my-site;
proxy_set_header X-Real-IP $remote_addr;}
-
8/3/2019 Python Deployment With Fabric 3401
7/30
Basic Config (db)
DatabasesPostgreSQL
Frank Wiles @ www.revsys.com
MySQLPercona @ www.mysqlperformanceblog.com
-
8/3/2019 Python Deployment With Fabric 3401
8/30
Basic Config (cache)
Use Memcached! Even 16mb willsignificantly help against a Digg orbeing Slashdot'edIt's incredibly easy...
# settings.py
MIDDLEWARE_CLASSES = ('django.middleware.cache.UpdateCacheMiddleware','django.middleware.common.CommonMiddleware','django.middleware.cache.FetchFromCacheMiddleware')
CACHE_BACKEND = 'memcached://127.0.0.1:11211/'CACHE_MIDDLEWARE_SECONDS = 60*5 # 5 minutes
-
8/3/2019 Python Deployment With Fabric 3401
9/30
Basic Deployment
Copy Code & Media (rsync or scp)Run DB migrations / syncdbBounce wsgi daemons
-
8/3/2019 Python Deployment With Fabric 3401
10/30
Managing Growth (db)
Move DB to its own serverAs much RAM as possibleWrite-heavy (>10%)? Get fastdisksTune your config file
-
8/3/2019 Python Deployment With Fabric 3401
11/30
Managing Growth (web)
Add more web serversUse a resource monitoring tool likeMunin to understand if your app isCPU or memory bound
-
8/3/2019 Python Deployment With Fabric 3401
12/30
Even More Growth
Replicated or sharded DatabasesMultiple load balancers forredundancyMessage queuesCrons
Search daemons (Solr, Sphinx)etc...
-
8/3/2019 Python Deployment With Fabric 3401
13/30
(not so) Basic
Deployment
image credit:Brad Fitzpatrick
-
8/3/2019 Python Deployment With Fabric 3401
14/30
-
8/3/2019 Python Deployment With Fabric 3401
15/30
Deployment Options
Capistrano
+ Out of box support for common use cases
+ Hooks to customize tasks+ Source control integration+ Threaded deployment to multiple hosts
- Ruby :(
-
8/3/2019 Python Deployment With Fabric 3401
16/30
Deployment Options
Fabric
+ Very simple, tasks are just Python functions
+ Easy to chain together tasks to create complexscripts out of bite size pieces
- No source control integration- No out of box support- Some bugs, although fairly easy to work around,and new maintainer is working on fixes
-
8/3/2019 Python Deployment With Fabric 3401
17/30
Fabric Basics
sudo easy_install fabricneed a fabfile.pyfrom fabric.api import *
be mindful of tasks that may fail
each remote command starts freshchanging directories
-
8/3/2019 Python Deployment With Fabric 3401
18/30
Core Functionality
local() - Run a command locallyrun() - Run a command remotelysudo() - Run a command remotely asanother user
put() - Copy a file from local to remoteget() - Copy a file from remote to localmany more helper-ish commands
-
8/3/2019 Python Deployment With Fabric 3401
19/30
Authentication
Relies on SSH modelUse SSH keysControl access to root user viasudoersWhen you have to revoke access,
you just turn off their SSH account
-
8/3/2019 Python Deployment With Fabric 3401
20/30
Configuration
Fabric environment (env) -- it'sjust a dictionary
Hosts and Roles
Code RepositoriesWhatever you need
~/fabricrc
Global settings or all Fabric deploymentsSSH username
-
8/3/2019 Python Deployment With Fabric 3401
21/30
Example Config
# fabfile.pyfrom fabric.api import *
env.roledefs = {'web' : ['10.1.1.1', '10.1.1.2'],
'db' : ['10.1.1.3'],
'lb' : ['10.1.1.4'],
}
env.repositories = {...}
-
8/3/2019 Python Deployment With Fabric 3401
22/30
Tasks
# fabfile.pydef uptime():
run('uptime')
$> fab uptime -H 10.1.1.3
[10.1.1.3] run: uptime
[10.1.1.3] out: 05:20:39 up 88 days,
12:00, 0 users, load average: 0.03,0.03, 0.00
-
8/3/2019 Python Deployment With Fabric 3401
23/30
Mapping Roles to Tasks
# fabfile.py
@roles('web')
def uptime():run('uptime')
$> fab uptime
[10.1.1.1] run: uptime[10.1.1.1] out: 05:20:39 up 88
days...
[10.1.1.2] run: uptime
-
8/3/2019 Python Deployment With Fabric 3401
24/30
Decorator ProblemsSome problems with Fabric's role managementCan't override decorated tasks at command lineas docs suggest
def default_roles(*role_list):
def selectively_attach(func):
if not env.roles and not env.hosts:
return roles(*role_list)(func)
else:if env.hosts:
func = hosts(*env.hosts)(func)
if env.roles:
func = roles(*env.roles)(func)
return func
-
8/3/2019 Python Deployment With Fabric 3401
25/30
All better now
#fabfile.py
@default_roles('web', 'db')
def uptime():run('uptime')
$> fab uptime
# runs on all hosts in the 'web' and'db' roles
$> fab uptime --roles lb
-
8/3/2019 Python Deployment With Fabric 3401
26/30
Dealing with Failures
By default Fabric dies if a task failsUse a context manager whenfailures are anticipated
# fabfile.py
from __future__ import with_statement #
py2.5
def symlink_me():
with settings(warn_only=True):
run('rm /path/to/symlink')
run('ln -s /home/andy /path/to/symlink')
-
8/3/2019 Python Deployment With Fabric 3401
27/30
Easy sys-admin
Make an "invoke" commandGreat for sys-admin and one-offtasks
# fabfile.py
@default_roles('all')def invoke(command):
"Invoke an arbritrary command"
sudo(command)
# install new acka es on all hosts in one command
l ld k
-
8/3/2019 Python Deployment With Fabric 3401
28/30
Real World Tasks$> fab --list
Available commands:
bounce_wsgi_procs Bounce the WSGI procs by touching the filesdeploy Full deploymentdeploy_media Push media to S3invoke Invoke an arbritrary commandmigrate Run any migrations via Southreload_nginx Update Nginx's running configsplash_off Configure Nginx to serve the site
splash_on Configure Nginx to serve a downed-site pageupdate_repositories Push code to serversupdate_dependencies Update dependencies to third party libs
hi k ' l
-
8/3/2019 Python Deployment With Fabric 3401
29/30
Whiskey's Deployment
def deploy(splash='no'):"Full deployment"
deploy_media()
update_cached_repositories()
update_dependencies()
generate_releases()if splash == 'yes':
splash_on()
_symlink_code()
migrate()
bounce_wsgi_procs()if splash == 'yes':
splash_off()
$> fab deploy:splash=yes
-
8/3/2019 Python Deployment With Fabric 3401
30/30
Questions?