Share
Embed
Transcript
108 slides
-
@rhyselsmore >>> import rhyselsmore Platform Security Engineer at Heroku. I
focus on Anti-Abuse Systems. I develop using a mixture of Python/Go. -
@rhyselsmore 3,000,000+ apps created. 130+ add-ons services. 90,000+ requests per
second. 500,000+ log entries per second. -
@rhyselsmore Play & Scala & Clojure & Gradle & Grails
& C & Common Lisp & Dart & Elixir & Erlang & Go & Haskell & JRuby & Lua & Perl & Rust & … -
@rhyselsmore Lets assume that You want to learn about Heroku
You know (a bit) of Python You have Python, pip, and can create a virtualenv -
@rhyselsmore Lets assume that You want to learn about Heroku
You know (a bit) of Python You have Python, pip, and can create a virtualenv install.python-guide.org -
@rhyselsmore $ heroku create Creating myapp... done, stack is cedar
http://myapp.herokuapp.com/ | [email protected]:myapp.git Git remote heroku added -
@rhyselsmore $ cat .git/config [core] repositoryformatversion = 0 filemode =
true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "heroku"] url = [email protected]:myapp.git fetch = +refs/heads/*:refs/remotes/heroku/* -
@rhyselsmore $ virtualenv venv $ pip install flask gunicorn $
pip freeze > requirements.txt -
@rhyselsmore import os! from flask import Flask! ! app =
Flask(__name__)! ! @app.route('/')! def index():! return "Hello, World!" heroku101.py -
@rhyselsmore $ foreman start 21:51:53 web.1 | started with pid
20276 Launch your application locally -
@rhyselsmore $ git add . $ git commit -m ‘initial
commit’ Store our changes in git -
@rhyselsmore $ git push heroku master ! -----> Python app
detected -----> Preparing Python runtime (python-2.7.7) -----> Installing Setuptools (3.6) -----> Installing Pip (1.5.6) ! …. ! -----> Discovering process types Procfile declares types -> web ! -----> Compressing... done, 31.6MB -----> Launching... done, v3 http://myapp.herokuapp.com/ deployed to Heroku ! To [email protected]:myapp.git * [new branch] master -> master -
@rhyselsmore X. Dev/Prod Parity Keep development, staging, and production as
similar as possible -
@rhyselsmore VI. Processes Execute the app as one or more
stateless processes -
@rhyselsmore Runs processes concurrently locally via a Procfile Foreman Exposes
a configuration to our processes Creates parity between production and development -
@rhyselsmore Runs processes concurrently locally via a Procfile Foreman Exposes
a configuration to our processes Creates parity between production and development -
@rhyselsmore web web web web web worker worker worker worker
worker clock monitor web worker -
@rhyselsmore web web web web web worker worker worker worker
worker clock ! monitor web worker -
@rhyselsmore web web web web web clock ! monitor web
! ! ! ! ! worker ! ! ! ! -
@rhyselsmore web web web web web ! monitor web !
! ! ! ! worker ! ! ! ! -
@rhyselsmore Runs processes concurrently locally via a Procfile Foreman Exposes
a configuration to our processes Creates parity between production and development -
@rhyselsmore import os! from flask import Flask! ! app =
Flask(__name__)! ! @app.route('/')! def index():! name = os.environ.get('PAGE_NAME', 'Rhys')! return "Hello, {0}!".format(name)! heroku101.py -
@rhyselsmore $ foreman start 21:51:53 web.1 | started with pid
20276 Launch your application locally. Did it work? -
@rhyselsmore $ git add heroku101.py $ git commit -m ‘loading
name from configuration’ $ git push heroku master … $ heroku open Commit our changes, and push to Heroku -
@rhyselsmore $ heroku config:set PAGE_NAME=‘App User’ $ heroku open Launch
your application locally. Did it work? -
@rhyselsmore $ heroku releases === myapp v5 Set PAGE_NAME config
vars [email protected] 2014/06/17 22:49:44 v4 Deploy 0b7df5b [email protected] 2014/06/17 22:49:33 v3 Deploy f6fc054 [email protected] 2014/06/17 22:00:32 v2 Enable Logplex [email protected] 2014/06/17 21:10:58 v1 Initial release [email protected] 2014/06/17 21:10:57 Viewing your Releases -
@rhyselsmore $ heroku rollback v4 Rolling back myapp... done, v4
! Warning: rollback affects code and config vars; it doesn't add or remove addons. To undo, run: heroku rollback v5 Rolling back to another Release -
@rhyselsmore ! app ! postgres ! redis ! s3 !
outbound mail -
@rhyselsmore ! app ! redis Dev ! app ! redis
Prod redis://my.production.redis redis://localhost -
@rhyselsmore X. Dev/Prod Parity Keep development, staging, and production as
similar as possible -
@rhyselsmore CREATE TABLE ips ( id serial primary key, ip
inet not null … -
@rhyselsmore CREATE TABLE ips ( id serial primary key, ip
inet not null … -
@rhyselsmore import os! from flask import Flask! import redis! !
app = Flask(__name__)! db = redis.from_url(os.environ.get('REDISCLOUD_URL'))! ! ! @app.route('/name/<name>')! def setname(name):! db.set('PAGE_NAME', name)! return "Name successfully updated"! ! ! @app.route('/')! def index():! name = db.get('PAGE_NAME') or "Rhys"! return "Hello, {0}!".format(name)! heroku101.py -
@rhyselsmore $heroku addons:add rediscloud Adding rediscloud on myapp... done, v7
(free) Use `heroku addons:docs rediscloud` to view documentation. Add RedisCloud -
@rhyselsmore $ heroku config REDISCLOUD_URL=xxxxxxx PAGE_NAME=Rhys Addons are exposed to
your application as config vars -
@rhyselsmore $ git add heroku101.py requirements.txt $ git commit -m
‘using redis as our db store’ $ git push heroku master … $ heroku open Commit our changes, and push to Heroku -
@rhyselsmore 2014-06-17T16:03:07.702584+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=7be32154-cbca-4e9c-b235-2a86a204f32d fwd="50.31.252.204" dyno=web.1
connect=1ms service=3ms status=200 bytes=172 2014-06-17T16:03:21.624306+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=180ee5c1-5c7e-4370-925c-4532bab44bb1 fwd="50.31.252.204" dyno=web.1 connect=1ms service=7ms status=200 bytes=172 2014-06-17T16:03:26.160610+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=71337d5d-ca00-49ed-98f6-e007123142de fwd="50.31.252.204" dyno=web.1 connect=0ms service=2ms status=200 bytes=172 2014-06-17T16:03:31.690643+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=b156826f-6db3-480d-bcc0-34239b2ad5a2 fwd="50.31.252.204" dyno=web.1 connect=1ms service=3ms status=200 bytes=172 2014-06-17T16:03:33.123754+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=a3768595-4fa5-41b7-aa2b-24ac4fa81880 fwd="50.31.252.204" dyno=web.1 connect=1ms service=3ms status=200 bytes=172 2014-06-17T16:03:34.186475+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=2e02b838-bdd6-47b2-b9c9-cd4d999ef1bc fwd="50.31.252.204" dyno=web.1 connect=0ms service=30ms status=200 bytes=172 2014-06-17T16:03:38.245823+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=c50b652a-1632-4727-b27a-03b0e89cdc4f fwd="50.31.252.204" dyno=web.1 connect=8ms service=30ms status=200 bytes=172 2014-06-17T16:03:48.101998+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.herokuapp.com request_id=94bd1cb4-446e-4309-9a67-94b210cdc3b2 fwd="50.31.252.204" dyno=web.1 connect=1ms service=2ms status=200 bytes=172 2014-06-17T16:03:49.663855+00:00 heroku[router]: at=info method=GET path="/" host=whispering-lake-5026.he -
@rhyselsmore import os! from flask import Flask! import log_metrics, random,
time! ! app = Flask(__name__)! ! ! @app.route('/')! def index():! with log_metrics.timer('timed-function'):! time.sleep(random.uniform(0.5, 1.5))! log_metrics.increment('requests')! return "Hello, Librato!"! heroku101.py -
@rhyselsmore 00:18:20 web.1 | measure#timed-function.ms=1261.87 00:18:20 web.1 | count#requests=1 00:18:24
web.1 | measure#timed-function.ms=925.83 00:18:24 web.1 | count#requests=1 -
@rhyselsmore >>> import requests! >>> import json! ! >>> heroku
= requests.session()! >>> heroku.auth = ('', '<my API token>')! >>> heroku.headers.update({! "Accept": "application/vnd.heroku+json; version=3",! "Content-Type": "application/json"! })! ! >>> heroku.get('/apps').json()! {! "id":49939049,! "name":"my-app-1",! "dynos":0,! "workers":0,! "repo_size":null,! "slug_size":null,! "stack":"cedar",! "requested_stack":null, -
@rhyselsmore >>> heroku.get('/apps/myapp/config-vars').json()! {! "NAME": "My App",! "SECRET_KEY": "hunter2"! }
>>> heroku.patch(‘/apps/myapp/config-vars’, json.dumps({! ! "NAME": "My Apps new config var",! })) -
@rhyselsmore Further Questions… ! SSL Endpoints? File Storage? Multiple Languages?
Free Limits? Does an add-on for $task exist? EU vs US region? Show us how to…