Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Open Source Modern Web Development

Open Source Modern Web Development

Open Source Modern Web Development Module at the MSc in Development and Integration of Software Solutions. Deusto, Bilbao - Spain.

Jorge Bastida

May 08, 2013
Tweet

More Decks by Jorge Bastida

Other Decks in Technology

Transcript

  1. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  2. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  3. renderiza ejecuta habla Browser Más que un terminal tonto, pero

    no tanto más HTML + CSS JavaScript HTTP (+DNS)
  4. HTML + CSS JavaScript HTTP (+DNS) Browser Más que un

    terminal tonto, pero no tanto más frontend backend
  5. renderiza HTML + CSS <html> <head> <title>Example</title> <link rel="stylesheet" type="text/css"

    href="example.css"> </head> <body> <h1>Title</h1> <p> This is <strong>important</strong>. </p> </body> </html> body { font-family: 'Arial'; } strong { color: red; } + = example.html example.css
  6. ejecuta JavaScript <html> ... <body> <h1>Title</h1> ... <script type="text/javascript" src="example.js"></script>

    </body> </html> document.getElementsByTagName('h1') [0].onclick = function() { alert("You've clicked!"); }; + = example.html example.js
  7. Escribes una URL en el navegador 1 Se hace una

    petición DNS para traducir el hostname de la URL a su dirección IP 2 Se hace una petición HTTP a esa IP pidiendo el recurso / y se recibe el resultado, normalmente un fichero .html 3 www.wikipedia.org 91.198.174.225 91.198.174.225 GET / HTTP/1.1 ... HTTP/1.1 200 OK ... $ #
  8. El navegador comienza a renderizar el HTML y hace más

    peticiones [DNS+] HTTP para cada recurso (css, img, js, etc) que encuentre referenciado en el código (src=..., href=...) 4 <div class="central-featured-logo-inner"> <img src="//upload.wikimedia.org/wikipedia/commons/Wikipedia-logo.png"> </div> A partir de aquí, y hasta la próxima petición HTTP que fuerce una recarga completa de la página, todo lo que puede ocurrir son efectos CSS y código JavaScript. 5 Desde JavaScript podemos hacer peticiones HTTP asíncronas (AJAX) que fuercen acciones en el servidor y como resultado realicen cambios en el DOM de la página. Y esto es todo.
  9. El navegador comienza a renderizar el HTML y hace más

    peticiones [DNS+] HTTP para cada recurso (css, img, js, etc) que encuentre referenciado en el código (src=..., href=...) 4 <div class="central-featured-logo-inner"> <img src="//upload.wikimedia.org/wikipedia/commons/Wikipedia-logo.png"> </div> A partir de aquí, y hasta la próxima petición HTTP que fuerce una recarga completa de la página, todo lo que puede ocurrir son efectos CSS y código JavaScript. 5 Desde JavaScript podemos hacer peticiones HTTP asíncronas (AJAX) que fuercen acciones en el servidor y como resultado realicen cambios en el DOM de la página. Y esto es todo.
  10. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  11. físico enlace de datos red transporte sesión presentación aplicación Modelo

    OSI Hardware Acceso al medio (MAC) Enrutamiento entre redes Transmisión fiable del mensaje Diálogo Codificación, cifrado, compresión... Contenido del mensaje
  12. acceso al medio red transporte aplicación TCP/IP físico enlace de

    datos red transporte sesión presentación aplicación Modelo OSI http, ftp, smtp, pop, imap, ssh, irc, ... TCP, UDP IP ethernet, token ring, fddi, ...
  13. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  14. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Respuesta Petición $ #
  15. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  16. Un recurso se identifica mediante una URL <OPERACIÓN> <recurso> HTTP/1.1

    protocol://[user:pass@]host[:port][/resource] en http, por defecto: user = pass = port = 80 resource = / http://www.wikipedia.org:80/
  17. <OPERACIÓN> <recurso> HTTP/1.1 Las URLs son parte fundamental del diseño

    de una aplicación web http://www.wordpress.org/ http://www.wordpress.org/about/ http://www.wordpress.org/support/ http://www.wordpress.org/extend/themes/ http://www.wordpress.org/extend/themes/montezuma ...
  18. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  19. GET Obtiene un recurso. No debería producir cambios. POST PUT

    Crea un recurso. Reemplaza o crea un recurso. DELETE Elimina un recurso. <OPERACIÓN> <recurso> HTTP/1.1 HEAD Como GET, pero pide sólo las cabeceras. TRACE Diagnóstico. OPTIONS Pregunta por los métodos que soporta el servidor. CONNECT Diagnóstico.
  20. <OPERACIÓN> <recurso> HTTP/1.1 REST es un enfoque de diseño de

    APIs que, entre otras cosas, explota la pureza de estos conceptos http://example.com/recetas/ http://example.com/recetas/453 PUT GET POST DELETE PUT GET POST DELETE Lista las URIs de recetas y quizá otros detalles. Reemplaza la colección de recetas por una nueva. Inserta una nueva receta y devuelve su URI. Borra la colección de recetas. Devuelve el detalle de una receta. Reemplaza o crea (si no existe) una receta. --- Borra una receta.
  21. La navaja suiza de las URLs $ curl example.com/recetas $

    curl -XGET example.com/recetas $ curl -XPOST example.com/recetas $ curl -XPUT example.com/recetas $ curl -XDELETE example.com/recetas cURL
  22. La navaja suiza de las URLs $ curl example.com/recetas $

    curl -XGET example.com/recetas $ curl -XPOST example.com/recetas $ curl -XPUT example.com/recetas $ curl -XDELETE example.com/recetas cURL
  23. $ curl -X GET google.com <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY>

    <H1>301 Moved</H1> The document has moved <A HREF="http://www.google.com/">here</A>. </BODY></HTML> cURL La navaja suiza de las URLs
  24. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  25. <cabeceras> Son parejas Clave: valor que transmiten al servidor información

    acerca de la request Accept: text/plain Accept-Charset: utf-8 Accept-Encoding: gzip, deflate Accept-Language: en-US Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Cache-Control: no-cache Connection: keep-alive Cookie: $Version=1; Skin=new; Content-Length: 348
  26. <cabeceras> Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== Content-Type: application/x-www-form-urlencoded Date: Tue, 15 Nov 1994

    08:12:31 GMT Expect: 100-continue From: [email protected] Host: en.wikipedia.org:80 If-Match: "737060cd8c284d8af7ad3082f209582d" If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT If-None-Match: "737060cd8c284d8af7ad3082f209582d" If-Range: "737060cd8c284d8af7ad3082f209582d" If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
  27. <cabeceras> Max-Forwards: 10 Origin: http://www.example-social-network.com Pragma: no-cache Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

    Range: bytes=500-999 Referer: http://en.wikipedia.org/wiki/Main_Page TE: trailers, deflate Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, ... User-Agent: Mozilla/5.0 (X11; Linux x86_64; ... Via: 1.0 fred, 1.1 example.com (Apache/1.1) Warning: 199 Miscellaneous warning X-<YYY>: ZZZ
  28. cURL: ver cabeceras $ curl -v -X GET google.com *

    About to connect() to google.com port 80 (#0) * Trying 173.194.41.8... * connected * Connected to google.com (173.194.41.8) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5 > Host: google.com > Accept: */* > < HTTP/1.1 301 Moved Permanently < Location: http://www.google.com/ < Content-Type: text/html; charset=UTF-8 < Date: Mon, 06 May 2013 08:03:50 GMT < Expires: Wed, 05 Jun 2013 08:03:50 GMT < Cache-Control: public, max-age=2592000 < Server: gws < Content-Length: 219 < X-XSS-Protection: 1; mode=block < X-Frame-Options: SAMEORIGIN < <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="http://www.google.com/">here</A>. </BODY></HTML> * Connection #0 to host google.com left intact * Closing connection #0
  29. cURL: enviar cabeceras $ curl -v -X GET google.com -H

    'User-Agent: Mozilla/5.0' * About to connect() to google.com port 80 (#0) * Trying 173.194.41.232... * connected * Connected to google.com (173.194.41.232) port 80 (#0) > GET / HTTP/1.1 > Host: google.com > Accept: */* > User-Agent: Mozilla/5.0 > < HTTP/1.1 301 Moved Permanently < Location: http://www.google.com/ < Content-Type: text/html; charset=UTF-8 < Date: Mon, 06 May 2013 08:16:10 GMT < Expires: Wed, 05 Jun 2013 08:16:10 GMT < Cache-Control: public, max-age=2592000 < Server: gws < Content-Length: 219 < X-XSS-Protection: 1; mode=block < X-Frame-Options: SAMEORIGIN < <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="http://www.google.com/">here</A>. </BODY></HTML> * Connection #0 to host google.com left intact * Closing connection #0
  30. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  31. <cuerpo> POST /blog/posts HTTP/1.1 Accept: application/json Content-Type: application/json Content-Length: 57

    Host: www.example.com:80 {"title":"Hello!","body":"This is my first post!"} POST /blog/posts HTTP/1.1 Accept: */* Content-Type: application/x-www-form-urlencoded Content-Length: 47 Host: www.example.com:80 title=Hello%21&body=This+is+my+first+post%21
  32. <cuerpo> POST /blog/posts HTTP/1.1 Accept: text/html, application/xhtml+xml, */* Content-Type: multipart/form-data;

    boundary=AaB03x Content-Length: 240 Host: www.example.com:80 --AaB03x Content-Disposition: form-data; name="name" Larry --AaB03x Content-Disposition: form-data; name="files" Content-Type: multipart/mixed; boundary=BbC04y --BbC04y Content-Disposition: file; filename="file1.txt" Content-Type: text/plain ... contents of file1.txt ... --BbC04y Content-Disposition: file; filename="file2.gif" Content-Type: image/gif Content-Transfer-Encoding: binary ...contents of file2.gif... --BbC04y-- --AaB03x--
  33. cURL: cuerpo de una petición $ curl -v -X POST

    localhost:8000/jugadores/ -d "username=pablo" * About to connect() to localhost port 8000 (#0) * Trying ::1... * Connection refused * Trying 127.0.0.1... * connected * Connected to localhost (127.0.0.1) port 8000 (#0) > POST /jugadores/ HTTP/1.1 > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5 > Host: localhost:8000 > Accept: */* > Content-Length: 14 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 14 out of 14 bytes * HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Date: Mon, 06 May 2013 07:48:08 GMT < Server: WSGIServer/0.1 Python/2.7.2 < Content-Type: text/html; charset=utf-8 < ... ... * Closing connection #0
  34. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  35. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  36. HTTP/1.1 <código> <descripción> 200 OK 201 Created 202 Accepted 203

    Non-Authoritative Information 204 No Content 205 Reset Content 206 Partial Content ✓ ℹ 1XX Informational 2XX Success 100 Continue 101 Switching Protocols 300 Multiple Choices 301 Moved Permanently 302 Found 303 See Other 304 Not Modified 305 Use Proxy 306 (Unused) 307 Temporary Redirect  3XX Redirection
  37. HTTP/1.1 <código> <descripción> # 4XX Client Error 400 Bad Request

    401 Unauthorized 402 Payment Required 403 Forbidden 404 Not Found 405 Method Not Allowed 406 Not Acceptable 407 Proxy Authentication Required 408 Request Timeout 409 Conflict 410 Gone 411 Length Required 412 Precondition Failed 413 Request Entity Too Large 414 Request-URI Too Long 415 Unsupported Media Type 416 Requested Range Not Satisfiable 417 Expectation Failed 500 Internal Server Error 501 Not Implemented 502 Bad Gateway 503 Service Unavailable 504 Gateway Timeout 505 HTTP Version Not Supported 5XX Server Error $
  38. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  39. <cabeceras> Access-Control-Allow-Origin: * Accept-Ranges: bytes Age: 12 Allow: GET, HEAD

    Cache-Control: max-age=3600 Connection: close Content-Encoding: gzip Content-Language: en Content-Length: 348 Content-Location: /index.html Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== Content-Disposition: attachment; filename="f.txt"
  40. <cabeceras> Content-Range: bytes 21010-47021/47022 Content-Type: text/html; charset=utf-8 Date: Tue, 15

    Nov 1994 08:12:31 GMT ETag: "737060cd8c284d8af7ad3082f209582d" Expires: Thu, 01 Dec 1994 16:00:00 GMT Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT Link: </feed>; rel="alternate"[25] Location: http://www.w3.org/pub/WWW/People.html P3P: CP="This is not a P3P policy! See..." Pragma: no-cache Proxy-Authenticate: Basic Refresh: 5; url=http://...
  41. <cabeceras> Retry-After: 120 Server: Apache/2.4.1 (Unix) Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1

    Status: 200 OK Strict-Transport-Security: max-age=16070; includeSubDomains Trailer: Max-Forwards Transfer-Encoding: chunked Vary: * Via: 1.0 fred, 1.1 example.com (Apache/1.1) Warning: 199 Miscellaneous warning WWW-Authenticate: Basic X-<YYY>: ZZZ
  42. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  43. <cuerpo> HTTP/1.1 200 OK Content-Type: text/html Date: Thu, 31 May

    2007 20:35:00 GMT <html> <head> <title>Web page</title> </head> <body> <h1>Hello world</h1> </body> </html>
  44. HTTP Protocolo de manipulación de recursos, sin estado <OPERACIÓN> <recurso>

    HTTP/1.1 <cabeceras> <cuerpo> HTTP/1.1 <código> <descripción> <cabeceras> <cuerpo> Petición Respuesta $ #
  45. HTTP/1.1 200 OK Content-Type: text/html Date: Thu, 31 May 2007

    20:35:00 GMT <html> <body> <h1>Hello world</h1> </body> </html> HTTP/1.1 304 Not Modified Date: Thu, 06 Jun 2007 19:40:00 GMT HTTP Imprescindible
  46. HTTP/1.1 301 Moved Permanently Location: http://www.example.com/new/url/ HTTP/1.1 302 Found Location:

    http://www.example.com/other/url/ HTTP/1.1 303 See Other Location: http://www.example.com/other/url/ HTTP/1.1 307 Temporary Redirect Location: http://www.example.com/other/url/ http 1.0 http 1.1 GET XXX GET XXX HTTP Imprescindible
  47. HTTP/1.1 400 Bad Request HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="..."

    HTTP/1.1 403 Forbidden HTTP/1.1 404 Not Found HTTP/1.1 405 Method Not Allowed HTTP/1.1 410 Gone HTTP Imprescindible
  48. HTTP/1.1 500 Internal Server Error HTTP/1.1 501 Not Implemented HTTP/1.1

    502 Bad Gateway HTTP/1.1 503 Service Unavailable HTTP Imprescindible
  49. Cookies Solucionan la falta de estado del protocolo HTTP $

    # $ # Son simples strings que se almacenan en el navegador GET / HTTP/1.1 ... GET / HTTP/1.1 Cookie: sessionid=xxx HTTP/1.1 200 OK Set-Cookie: sessionid=xxx HTTP/1.1 200 OK ... Cliente Servidor
  50. Cookies Set-Cookie: sessionid=xxx; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13 Jan 2021 22:23:01

    GMT; Secure; HttpOnly En qué requests debería enviarse como Cookie: Domain + Path Expires Cuándo el User-Agent debería borrar la cookie Secure Sólo debe enviarse si el tráfico es https HttpOnly Sólo accessible desde HTTP, no desde JavaScript XSS! ⚠ document.cookie = ...
  51. Cookies Set-Cookie: sessionid=xxx; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13 Jan 2021 22:23:01

    GMT; Secure; HttpOnly En qué requests debería enviarse como Cookie: Domain + Path Expires Cuándo el User-Agent debería borrar la cookie Secure Sólo debe enviarse si el tráfico es https HttpOnly Sólo accessible desde HTTP, no desde JavaScript XSS! ⚠ document.cookie = ...
  52. Método sencillo para proveer de autenticación a peticiones HTTP, sin

    necesidad de cookies $ # GET / HTTP/1.1 ... Cliente Servidor HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="Login" Basic HTTP auth
  53. Basic HTTP auth Método sencillo para proveer de autenticación a

    peticiones HTTP, sin necesidad de cookies $ # GET / HTTP/1.1 ... Cliente Servidor HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="Login" $ # GET / HTTP/1.1 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== HTTP/1.1 200 OK ... base64(username:password) HTTPS! ⚠
  54. cURL: Basic HTTP auth $ curl -v -X GET localhost:8000/

    --user pablo:x6f8 * About to connect() to localhost port 8000 (#0) * Trying ::1... * Connection refused * Trying 127.0.0.1... * connected * Connected to localhost (127.0.0.1) port 8000 (#0) * Server auth using Basic with user 'pablo' > GET / HTTP/1.1 > Authorization: Basic cGFibG86eDZmOA== > User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5 > Host: localhost:8000 > Accept: */* > * HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Date: Mon, 06 May 2013 08:36:25 GMT < Server: WSGIServer/0.1 Python/2.7.2 < Content-Type: text/html; charset=utf-8 < Bienvenido a la mazmorra, espera instrucciones! * Closing connection #0
  55. Ejercicio cURL: La guarida del dragón. $ curl -v -XPOST

    10.172.104.175/jugadores/ -d "username=pablo" )
  56. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  57. acceso al medio red transporte aplicación físico enlace de datos

    red transporte sesión presentación aplicación HTTP TLS/SSL HTTPS
  58. HTTPS $ # Certificado Public key (P) P(K) Ok K

    = ... Clave simétrica compartida mediante algoritmo asimétrico K(mensaje) K(mensaje) Cliente Servidor +
  59. Otras navajas suizas tcpflow $ sudo tcpflow -i eth0 port

    80 -C Sniffer de tráfico TCP por excelencia en UNIX Chrome inspector
  60. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  61. Cliente Servidor Canal Cachear, Delegar, Indexar varnish, redis, cron, batch...

    Reducir request ( número y tamaño ) Minify, sprites, gzip, cdn... Cachear + Optimizar Cache, dns lookups, redirects, etags... Optimización 3
  62. Cliente Servidor Canal Cachear, Delegar, Indexar varnish, redis, cron, batch...

    Reducir request ( número y tamaño ) Minify, sprites, gzip, cdn... Cachear + Optimizar Cache, dns lookups, redirects, etags... Optimización 3
  63. 30m 10m no-cache Memcached, redis etc... Contenido externo • APIs,

    RSS, Twitter Contenido “Estático” • Últimas noticias • Nuevos usuarios • Últimos tweets • ... Cachear Contenido 3.1.1
  64. > GET last_tweets <h1>\n<ul><li>Hello from.... Memcached •Ventajas • Velocidad •

    Sencillez •Inconvenientes • Volátil: sólo reside en memoria. • Sólo entiende cadenas de texto. Cachear Contenido 3.1.1
  65. > INCR message:143:comments 1 4445 Redis •Ventajas • Velocidad •

    Tipos de datos complejos • Operaciones atómicas •Inconvenientes • Muy pocas • Abuso = Problemas (como todo) Welcome to my site. 4445 Comments Cachear Contenido 3.1.1
  66. Existen múltiples “puntos” donde cachear. •Servidor web • Intrusismo •

    Complejidad media •Código del proyecto “backend” • Sencillo de implementar • Poco eficiente •Proxy • Sencillo • Muy eficiente Cachear Requests 3.1.1
  67. •Requests Anónimas • Digg effect • Landing page • Google

    •Contenido Estático • Assets • Thumbnails •APIs •“Hot Pages” Request Response Varnish Server Miss Hit Cachear Requests 3.1.1
  68. Request vcl_recv() lookup * Versión muy simplificada del funcionamiento de

    Varnish in cache? Build Response yes Varnish Varnish 3.1.1
  69. Request vcl_recv() lookup * Versión muy simplificada del funcionamiento de

    Varnish in cache? Build Response Response yes Varnish Varnish 3.1.1
  70. Request vcl_recv() pass lookup * Versión muy simplificada del funcionamiento

    de Varnish in cache? no Build Response Response yes Varnish Varnish 3.1.1
  71. Request vcl_recv() Backend pass lookup * Versión muy simplificada del

    funcionamiento de Varnish in cache? no Build Response vcl_fetch() Response yes cache? Varnish Varnish 3.1.1
  72. Request vcl_recv() Backend pass lookup * Versión muy simplificada del

    funcionamiento de Varnish in cache? no Build Response vcl_fetch() Response yes cache? no Varnish Varnish 3.1.1
  73. Request vcl_recv() Backend pass lookup * Versión muy simplificada del

    funcionamiento de Varnish in cache? no Build Response vcl_fetch() Response yes Cache cache? yes no Varnish Varnish 3.1.1
  74. sub vcl_recv { # Pass anything other than GET and

    HEAD directly. if (req.request != "GET" && req.request != "HEAD"){ return(pass); } # Always lookup static files from the cache. # We don't need request cookies neither Authorization. if (req.request == "GET" && req.url ~ "^/static/") { unset req.http.cookie; unset req.http.Authorization; return(lookup); } # Remove any cookie we don't know about except `sessionid`. if (req.http.Cookie) { set req.http.Cookie = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(sessionid)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.Cookie == "") { # If there are no cookies, remove the header and lookup the cache. unset req.http.Cookie; return(lookup); } else { # If `sessionid` cookie is pressent pass the request to the backend. return (pass); } } } vcl_recv
  75. sub vcl_fetch { # If the response status >= 400

    don't cache it. if (beresp.status >= 400) { return (hit_for_pass); } # Remove cookies if this is a static request and set 1 week of ttl. if (req.url ~ "^/static/") { unset beresp.http.set-cookie; set beresp.ttl = 1w; return (deliver); } else{ # If the response is setting any cookie, don't cache it. if (beresp.http.Set-Cookie) { return (hit_for_pass); } # Cache this response for 10 minutes. set beresp.ttl = 10m; return (deliver); } } vcl_fetch
  76. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s Dejar que alguien haga el trabajo sucio, antes o después csv #
  77. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s ¿Cuánto del trabajo sucio es imprescindible al instante? csv # ? ? ?
  78. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s ¿Cuánto del trabajo sucio es imprescindible al instante? csv # ? ¿caché? ?
  79. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s ¿Cuánto del trabajo sucio es imprescindible al instante? csv # ? ¿caché? ¿tarea periódica?
  80. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s ¿Cuánto del trabajo sucio es imprescindible al instante? csv # ¿caché? ¿tarea periódica? ¿cola de mensajes?
  81. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s ¿Cuánto del trabajo sucio es imprescindible al instante? csv # ¿caché? Delegar antes Delegar después
  82. Scheduler de trabajos de UNIX cron * * * *

    * <cmd> día de la semana (0 - 7) mes (1 - 12) día del mes (1 - 31) hora (0 - 23) minuto (0 - 59) # crontab -e $ crontab -e
  83. Scheduler de trabajos de UNIX # crontab -l 0 1

    * * * /usr/sbin/ntpdate pool.ntp.org 0 */2 * * * /home/root/bin/server-backup @reboot /home/root/bin/email-admins.sh cron $ crontab -l */5 * * * * /home/ops/bin/billing.sh @hourly /home/ops/bin/caches.py @daily /home/ops/bin/users-csv.py @weekly /home/ops/bin/spending-reports.sh
  84. Delegar 3.2 $ # Cliente Servidor 500ms bd ! ,

    smtp 200ms 5s ¿Cuánto del trabajo sucio es imprescindible al instante? csv # ¿caché? Delegar antes Delegar después
  85. Celery 3.2 Sistema de Tareas Asíncronas distribuidas. • Features: Colas,

    Concurrencia, Distribuido... • Pro: Muy fácil de implementar y escalable. • Casos prácticos: • Enviar un email (Notificationes, ...) • Calcular el karma de de los usuarios del sistema. • Tareas programadas (Limpieza, Post-procesado, etc...) • Regenerar caches etc.. !h#p://celeryproject.org
  86. Celery 3.2 El principal componente es el Broker. Se encarga

    de almacenar y entregar tareas a todos los workers. Estable Experimental
  87. Funcionamiento 3.2 Server #1 celery worker celery beat Server #3

    celery worker Server #4 web node Server #5 web node añadir procesar procesar añadir añadir Server #2 celery worker procesar
  88. Funcionamiento 3.2 Server #1 celery worker celery beat Server #3

    celery worker Server #4 web node Server #5 web node añadir procesar procesar añadir añadir Server #2 celery worker procesar
  89. Funcionamiento 3.2 Server #1 celery worker celery beat Server #3

    celery worker Server #4 web node Server #5 web node añadir procesar procesar añadir añadir Server #2 celery worker procesar
  90. Funcionamiento 3.2 Conceptos clave: • Atómico: Las tareas se entregan

    solo a un worker. • Distribuido: Los nodos son independientes unos de otros y el número puede aumentar y disminuir dinámicamente. • Fiable: Si no se informa a RabbitMQ sobre la finalización de una tarea, esta vuelve a formar parte de la cola. En caso de catástrofe no perdemos tareas. • Rates: Celery nos permite definir rates para nos sobrecargar el sistema o APIs externas. • Tareas Periodicas: Celery beat registrará por nosotros tareas en la cola de la misma manera que lo haría cron.
  91. Indexar 3.3 Preparar la información para acceder más rápido a

    ella en el momento de la consulta ! DB Search -
  92. !DB index SELECT date(timestamp) as day, count(*) FROM stamp WHERE

    key=%s AND date(timestamp) > current_date - interval %s GROUP BY day ORDER BY day; BEGIN; DROP TABLE IF EXISTS "stamp"; CREATE TABLE "stamp" ( "key" varchar(255) NOT NULL, "timestamp" timestamp without time zone NOT NULL ) ; COMMIT; con 4.221.883 registros, 11.488 segundos
  93. BEGIN; DROP TABLE IF EXISTS "stamp"; CREATE TABLE "stamp" (

    "key" varchar(255) NOT NULL, "timestamp" timestamp without time zone NOT NULL ) ; CREATE INDEX "stamp_key_idx" ON stamp(key); COMMIT; SELECT date(timestamp) as day, count(*) FROM stamp WHERE key=%s AND date(timestamp) > current_date - interval %s GROUP BY day ORDER BY day; con 4.221.883 registros, !DB index 11.488 segundos
  94. BEGIN; DROP TABLE IF EXISTS "stamp"; CREATE TABLE "stamp" (

    "key" varchar(255) NOT NULL, "timestamp" timestamp without time zone NOT NULL ) ; CREATE INDEX "stamp_key_idx" ON stamp(key); COMMIT; SELECT date(timestamp) as day, count(*) FROM stamp WHERE key=%s AND date(timestamp) > current_date - interval %s GROUP BY day ORDER BY day; con 4.221.883 registros, !DB index 11.488 0.107 segundos
  95. Search index - $ # Cliente Servidor bd ! q='covent

    garden' SELECT * FROM messages WHERE subject like '%covent garden%' OR body like '%covent garden%' OR author like '%covent garden%'; SELECT * FROM locations WHERE name like '%covent garden%' OR description like '%covent garden%'; SELECT * FROM pages WHERE name like '%covent garden%' OR description like '%covent garden%'; SELECT * FROM shareables WHERE name like '%covent garden%' OR description like '%covent garden%';
  96. Search index - $ # Cliente Servidor bd ! q='covent

    garden' SELECT * FROM messages WHERE subject like '%covent garden%' OR body like '%covent garden%' OR author like '%covent garden%'; SELECT * FROM locations WHERE name like '%covent garden%' OR description like '%covent garden%'; SELECT * FROM pages WHERE name like '%covent garden%' OR description like '%covent garden%'; SELECT * FROM shareables WHERE name like '%covent garden%' OR description like '%covent garden%'; mmm... NO
  97. Redis 3.3.3 Redis is an open source, BSD licensed, advanced

    key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. “ ” hashes lists sets sorted sets strings pub/sub scripts
  98. Redis como Indice 3.1 Problema: Mostrar avatares de 25 usuarios

    que compartan algún área contigo promocionando aquellos que no tengan uno de los avatares por defecto. Custom Default
  99. 3.1 Solución: Sorted Sets 1. Para cada area crear un

    sorted set con el id de todos los miembros. > ZADD area:1:followers 1 1 area:1:followers 1 Redis como Indice
  100. 3.1 Solución: Sorted Sets 1. Para cada area crear un

    sorted set con el id de todos los miembros. > ZADD area:1:followers 1 1 > ZADD area:1:followers 0 2 area:1:followers 1 2 Redis como Indice
  101. 3.1 Solución: Sorted Sets 1. Para cada area crear un

    sorted set con el id de todos los miembros. > ZADD area:1:followers 1 1 > ZADD area:1:followers 0 2 > ZADD area:2:followers 1 1 area:1:followers 1 2 area:2:followers 1 Redis como Indice
  102. 3.1 Solución: Sorted Sets 1. Para cada area crear un

    sorted set con el id de todos los miembros. > ZADD area:1:followers 1 1 > ZADD area:1:followers 0 2 > ZADD area:2:followers 1 1 > ZADD area:3:followers 0 4 area:1:followers 1 2 area:2:followers 1 area:3:followers 4 Redis como Indice
  103. 3.1 Solución: Sorted Sets 1. Para cada area crear un

    sorted set con el id de todos los miembros. > ZADD area:1:followers 1 1 > ZADD area:1:followers 0 2 > ZADD area:2:followers 1 1 > ZADD area:3:followers 0 4 > ZADD area:3:followers 1 5 area:1:followers 1 2 area:2:followers 1 area:3:followers 5 4 Redis como Indice
  104. 3.1 Problema: ¿Usuarios que siguen el area #1? > GET

    area:1:followers area:1:followers 1 2 area:2:followers 1 area:3:followers 5 4 Redis como Indice
  105. 3.1 Problema: ¿Usuarios que siguen el area #1 o el

    area #2? > ZINTERSTORE areas:1-2:followers 2 area:1:followers area:2:followers AGGREGATE MAX > GET areas:1-2:followers area:2:followers 1 area:3:followers 5 4 areas:1-2:followers area:1:followers 1 2 1 2 Redis como Indice
  106. 3.1 Problema: 25 usuarios que sigan el area #1 o

    el area #2 promocionando aquellos que tengan avatar. > ZREVRANGE areas:1-2:followers 0 25 area:2:followers 1 area:3:followers 5 4 area:1:followers 1 2 Redis como Indice
  107. 3.1 Problema: 25 usuarios que sigan el area #1 o

    el area #2 promocionando aquellos que tengan avatar. > ZREVRANGE areas:1-2:followers 0 25 area:2:followers 1 area:3:followers 5 4 areas:1-2:followers area:1:followers 1 2 1 2 Redis como Indice
  108. Cliente Servidor Canal Cachear, Delegar, Indexar varnish, redis, cron, batch...

    Reducir request ( número y tamaño ) Minify, sprites, gzip, cdn... Cachear + Optimizar Cache, dns lookups, redirects, etags... Optimización 3
  109. Minimizar JS y CSS  SL.Utils.flash = { init: function

    () { // Handle closing of flash messages $('#flashes .close, .flashes .close').live('click', function (e) { $(e.target).closest('li').slideUp(120, function () { // Cleanup after the last one var container = $(this).closest('#flashes, .flashes'), all_messages = container.find('li:visible'); if (all_messages.length < 1) { container.remove(); } }); e.preventDefault(); }); } }; SL.Utils.flash={init:function(){$("#flashes .close, .flashes .close").live("click",function(a){$ (a.target).closest("li").slideUp(120,function(){var a=$(this).closest("#flashes, .flashes"); 1>a.find("li:visible").length&&a.remove()});a.preventDefault()})}}; 585 bytes 255 bytes (~56%) Un paso más del proceso de build + deploy
  110. --line-break --type js|css --charset character-set --disable-optimizations $ java -jar yuicompressor.jar

    file.js -o file-min.js https://github.com/yui/yuicompressor/ Yahoo YUI compressor http://refresh-sf.com/yui/ 0 1
  111. N 1

  112. gzip 3.2.2 GET /index.html Accept-Encoding: gzip HTTP 1.1 200 OK

    <html><head> ... gzip Servidor Servidor sin gzip configurado Pese a que el navegador soporte gzip y envíe el header adecuado en la petición, el servidor lo ignora y envía el contenido sin comprimir. 100Kb
  113. GET /index.html Accept-Encoding: gzip Servidor con gzip configurado Estando gzip

    configurado en el servidor, si los clientes envían los header adecuados, el servidor comprimirá la respuesta utilizando gzip. HTTP 1.1 200 OK Content-Encoding: gzip kk3s(e?3.sn2isn19fkjnasd... 50Kb gzip 3.2.2 gzip Servidor
  114. A tener en cuenta •Navegadores MUY antiguos no soportan gzip.

    (~12 años) • Netscape <6 • Internet Explorer <5.5 (Julio 2000) • Opera <5 (Enero 2000) • Firefox <0.9.5 (Octubre 2001) •Solo comprimir texto (html, xml, css, js...) • Imágenes, audio y video suelen estar comprimidos utilizando codecs más eficientes y resulta una perdida de tiempo y cpu intentar recomprimirlos. •El 90% del tráfico de internet se genera utilizando navegadores que soportan gzip (Yahoo!) gzip 3.2.2
  115. CDN: Content delivery network •Objetivos principales • Distribuir contenido de

    la manera más eficiente posible a poder ser desde localizaciones geográficamente cercanas al cliente para reducir la latencia. • Reducir tráfico de nuestros servidores web distribuyendo el trafico a otros servidores. • Disminuir el coste. •Amazon S3 • $0.095 por GB Almacenado. • $0.004 por cada 10.000 requests. • $0.120 por GB transferido •Distribuir un video de 50Mb a 100K personas (~5Tb) • $0 (Hosting) + $0.04 (requests) + $585 (transferencia) CDN 3.2.3
  116. Cliente Servidor Canal Cachear, Delegar, Indexar varnish, redis, cron, batch...

    Reducir request ( número y tamaño ) Minify, sprites, gzip, cdn... Cachear + Optimizar Cache, dns lookups, redirects, etags... Optimización 3
  117. Speeding up your website 1. CSS y JS en ficheros

    externos 2. CSS al comienzo 3. JS al final 4. Entre 2 y 4 hostnames http://developer.yahoo.com/performance/rules.html 1 A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy. “
  118. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  119. $ Servidor Web Aplicación Base de datos ✓ ⚠ SENCILLO

    ❌ ✓ OK PARA EMPEZAR TERMINA SIENDO POCO SPOF SSL *
  120. $ Servidor Web Aplicación ✓ ⚠ SENCILLO ❌ ✓ PUEDE

    LLEVARTE LEJOS TERMINA SIENDO POCO SPOF $ Base de datos ⚠SPOF SSL *
  121. $ Servidor Web Aplicación ✓ ⚠ SENCILLO ❌ ✓ PUEDE

    LLEVARTE LEJOS TERMINA SIENDO POCO SPOF $ Base de datos ⚠SPOF x2 SSL *
  122. $ Servidor Web Aplicación ⚠SPOF $ Base de datos ⚠SPOF

    $ Servidor Web Aplicación ⚠SPOF DNS ROUND ROBIN :( SSL * SSL *
  123. $ Servidor Web Aplicación ⚠SPOF $ Base de datos ⚠SPOF

    $ Servidor Web Aplicación ⚠SPOF DNS ROUND ROBIN :( SSL * SSL *
  124. $ Servidor Web HAProxy ⚠SPOF $ Base de datos ⚠SPOF

    ⚠SPOF $ Servidor Web Aplicación ⚠SPOF $ Servidor Web Aplicación SSL *
  125. $ Servidor Web HAProxy ⚠SPOF $ Base de datos ⚠SPOF

    $ Servidor Web Aplicación $ Servidor Web Aplicación SSL *
  126. $ Servidor Web HAProxy ⚠SPOF $ Base de datos ⚠SPOF

    $ Servidor Web Aplicación $ Servidor Web Aplicación SSL * ???? Host $host; X-Real-IP $remote_addr; X-Forwarded-Proto $scheme;
  127. HAProxy 4.2 Balanceador TCP/HTTP Es uno de los balanceadores de

    carga más utilizados. Se caracteriza por ser muy eficiente tanto en CPU como en RAM y es famoso por su estabilidad. • Permite balancear tanto tráfico TCP como a un más alto nivel tráfico HTTP. • Nos permite realizar health-check de los servidores backend. • Podemos activar y desactivar servidores manualmente. • Dispone de varios criterios para asignar servidores: Random, Round-robin, Least connection, source, uri, url-parameter etc...
  128. global log 127.0.0.1 local0 notice maxconn 4096 user haproxy group

    haproxy defaults log global mode http option httplog option dontlognull option redispatch retries 3 contimeout 5000 clitimeout 50000 srvtimeout 50000 stats enable stats auth USER:PASSWORD backend allservers mode http server web1 192.168.0.11:80 check server web2 192.168.0.12:80 check server web3 192.168.0.13:80 check ... balance roundrobin option httpchk HEAD /test/ option forwardfor ... haproxy.cfg
  129. $ Servidor Web HAProxy ⚠SPOF $ Base de datos ⚠SPOF

    $ Servidor Web Aplicación $ Servidor Web Aplicación SSL *
  130. High availability 4.3 Load Balancer nginx haproxy Web #1 nginx

    app Web #2 nginx app Web #3 nginx app ⏶ Web #1 33% Web #2 33% Web #3 33% ✓ ✓ ✓ 4up example.com
  131. High availability 4.3 Web #1 nginx app Web #2 nginx

    app Web #3 nginx app ⏶ Web #1 50% Web #2 50% Web #3 0% ✓ ⚠ ✓ 4up example.com ⚠ Load Balancer nginx haproxy
  132. High availability 4.3 Web #1 nginx app Web #2 nginx

    app Web #3 nginx app ⏶ Web #1 100% Web #2 0% Web #3 0% ✓ ⚠ ⚠ 4up example.com ⚠ ⚠ Load Balancer nginx haproxy
  133. Load Balancer nginx haproxy High availability 4.3 Web #1 nginx

    app Web #2 nginx app Web #3 nginx app ⏶ Web #1 33% Web #2 33% Web #3 33% ✓ ✓ ✓ 5down example.com ⚠
  134. :(

  135. High availability 4.3 Problema Necesitamos hacer que nuestro balanceador no

    sea un un SPOF, Single point of failure. • En caso de fallo no podemos cambiar la configuración del DNS ya que conllevaría tiempo propagar el cambio. • No podemos poner otra capa de balanceadores por encima del balanceador ya que tendríamos el mismo problema. • Hagamos lo que hagamos ha de ser rápido para evitar downtime en la medida de lo posible.
  136. Heartbeat ♥ Capa de comunicación Básicamente es un “bus” que

    nos asegura que todos los mensajes enviados se envían a todos los miembros del bus y se asegura de que todo el mundo esté de acuerdo sobre quien está o no está conectado.
  137. Pacemaker 8 Agente Se encarga de arrancar y parar servicios

    en función de reglas que nosotros establezcamos. De igual manera, se cerciora de que estos servicios solo se ejecuten en uno de los servidores.
  138. Configuración $ cat /etc/ha.d/ha.cf keepalive 2 deadtime 15 warntime 5

    initdead 120 udpport 694 ucast eth0 123.123.123.123 auto_failback on node ha-1.example.com node ha-2.example.com use_logd yes crm respawn Heartbeat 4.3 Instalación $ apt-get install heartbeat Comprobar nodos cada dos segundos. Dar un nodo por muerto a los 15s. Alertar pasados 5 segundos. Máximo tiempo de espera en arranque. Puerto. IP. Failback automático al nodo primario. Nodo #1. Nodo #2. Enable log. Arrancar Pacemaker al arranque del cluster. Hemos de configurar hearbeat en ambos nodos 9
  139. Configuración $ cat /etc/heartbeat/authkeys auth 1 1 sha1 SECRET $

    chmod 600 /etc/heartbeat/authkeys Heartbeat 4.3 Hemos de configurar hearbeat en ambos nodos 9 Arranque $ service heartbeat start Estado $ service heartbeat status heartbeat OK [pid 2332 et al] is running on ha-1.example.com [ha-1.example.com]...
  140. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  141. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  142. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  143. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  144. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  145. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  146. Configuración $ crm configure edit node $id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ha-1.example.com node $id="yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

    ha-2.example.com primitive ip1 ocf:heartbeat:IPaddr2 \ params ip="123.123.123.123" nic="eth2" \ op monitor interval="5s" primitive ip1arp ocf:heartbeat:SendArp \ params ip="123.123.123.123" nic="eth2" group HAServices ip1 ip1arp \ meta target-role="Started" order ip-before-arp inf: ip1:start ip1arp:start property $id="cib-bootstrap-options" \ dc-version="xxxxxxxxxxxxxxxx" \ cluster-infrastructure="Heartbeat" \ expected-quorum-votes="1" \ stonith-enabled="false" \ no-quorum-policy="ignore" rsc_defaults $id="rsc-options" \ resource-stickiness="100" Pacemaker 4.3 Instalación $ apt-get install pacemaker
  147. $ Servidor Web HAProxy $ Base de datos ⚠SPOF $

    Servidor Web Aplicación $ Servidor Web Aplicación SSL * $ Servidor Web HAProxy SSL *
  148. $ Servidor Web HAProxy $ Base de datos ⚠SPOF $

    Servidor Web Aplicación $ Servidor Web Aplicación SSL * $ Servidor Web HAProxy SSL * $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación ????
  149. $ Servidor Web HAProxy $ Base de datos Master $

    Servidor Web Aplicación $ Servidor Web Aplicación SSL * $ Servidor Web HAProxy SSL * $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación W W W W W $ Base de datos Read Only
  150. $ Servidor Web HAProxy $ Base de datos Master $

    Servidor Web Aplicación $ Servidor Web Aplicación SSL * $ Servidor Web HAProxy SSL * $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación R R R R R $ Base de datos Read Only
  151. Y aún más lejos? Llegados a este punto deberíamos de

    tener a varias personas trabajando en esto a tiempo completo... pero el resultado podría parecerse algo como.... :
  152. $ Servidor Web HAProxy SSL * $ Servidor Web HAProxy

    SSL * DNS ROUND ROBIN $ Servidor Web HAProxy SSL * $ Servidor Web HAProxy SSL * $ Servidor Web HAProxy SSL * $ Servidor Web HAProxy SSL * $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación $ Servidor Web Aplicación Multi Master DB $ Slave n n n n $ Master $ Master $ Slave $ Slave $ Slave $ Slave $ Slave $ Slave $ Slave + +
  153. Servidores Web 4.4 ¿Cuál elijo? Existen docenas de servidores web,

    cada empresa suele elegir uno en función de las necesidades y features de cada uno. Nosotros utilizamos nginx dada la sencillez de configuración, la estabilidad, los grandísimos resultados que siempre alcanza en los tests de carga y en particular porque ya hemos trabajado con él y lo conocemos. En realidad nginx lo utilizamos como reverse proxy tanto en los balanceadores de carga como en los servidores web, así como para hacer “spoon-feeding”.
  154. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL ??????? 9
  155. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL ??????? 9
  156. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL ??????? 9
  157. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G ??????? 9
  158. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G ??????? 9
  159. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G ??????? 9
  160. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G ??????? 9
  161. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G ??????? 9
  162. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE ??????? 9
  163. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  164. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  165. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  166. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  167. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  168. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  169. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario 3G 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS ??????? 9
  170. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario ADSL 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS nginx LAN ; INTERNET ; 1Gb/s
  171. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario ADSL 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS nginx LAN ; INTERNET ; 1Gb/s 2.5Mb/s
  172. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario ADSL 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS nginx LAN ; INTERNET ; 1Gb/s 236Kb/s
  173. $ Proceso #1 $ Proceso #2 $ Proceso #3 $

    Proceso #4 6 Usuario ADSL 6 Usuario ADSL 6 Usuario 3G 6 Usuario EDGE 6 Usuario GPRS nginx LAN ; INTERNET ; 1Gb/s 60Kb/s
  174. ✉ Emails La mayoría de los servicios online necesitan enviar

    emails a sus usuarios. El número de emails que has de enviar crece mucho más rápido de lo que esperas...
  175. Amazon SES 4.4 ¿Qué es Amazon SES? Servicio cloud de

    Amazon que nos permite enviar grandes cantidades de emails sin tener que disponer de una infraestructura para tales efectos. ¿Y porqué no un smtp inhouse? El tiempo es oro y el día sólo tiene 24 horas. • Pequeñas empresas que no disponen de personal de sistemas pueden ahorrarse muchos dolores de cabeza (y ganar otros) externalizando servicios como este . • Grandes empresas que necesitan enviar millones de emails en épocas concretas y no desean sobre escalar sus sistemas para estas situaciones puntuales. • El coste es muy competitivo: 0.10 $ por cada 1000 emails. Actualmente enviamos alrededor de 1M de emails al mes, lo cual nos cuesta ~£64.
  176. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  177. https://github.com/blog/1241-deploying-at-github Deploying is a big part of the lives of

    most GitHub employees. We don't have a release manager and there are no set weekly deploys. Developers and designers are responsible for shipping new stuff themselves as soon as it's ready. This means that deploying needs to be as smooth and safe a process as possible. “
  178. $ $ $ $ $ $ $ $ $ $

    $ $ server #1 server #3 server #11 server #12 server #2 server #4 server #5 server #6 server #7 server #8 server #9 server #10 $ $ server #11 server #12 $ $ $ $ $ $ $ $ $ $ $ $ server #1B server #3B server #11B server #12B server #2B server #4B server #5B server #6B server #7B server #8B server #9B server #10B $ $ server #11B server #12B staging live
  179. $ $ $ $ $ $ $ $ $ $

    $ $ server #1B server #3B server #11B server #12B server #2B server #4B server #5B server #6B server #7B server #8B server #9B server #10B $ $ server #11B server #12B live
  180. $ $ $ $ $ $ $ $ $ $

    $ $ server #1B server #3B server #11B server #12B server #2B server #4B server #5B server #6B server #7B server #8B server #9B server #10B $ $ server #11B server #12B live activar modo mantenimiento (503) desplegar nuevo código purgar cachés reiniciar servicios minimizar javascript minimizar css generar sprites ... desactivar modo mantenimiento
  181. Streamlining SSH scripts fabric from fabric.api import run def host_type():

    run('uname -s') fabfile.py $ fab -H localhost,linuxbox host_type [localhost] run: uname -s [localhost] out: Darwin [linuxbox] run: uname -s [linuxbox] out: Linux Done. Disconnecting from localhost... done. Disconnecting from linuxbox... done.
  182. Agrupación de hosts en roles fabric env.roledefs = { 'test':

    ['test-web-1.example.com', 'test-web-2.example.com'], 'test-db': ['test-db-1.example.com', 'test-db-2.example.com'], 'test-ha': ['test-ha-1.example.com', 'test-ha-2.example.com'], 'www': ['www-web-1.example.com', 'www-web-2.example.com'], 'www-db': ['www-db-1.example.com', 'www-db-2.example.com'], 'www-ha': ['www-ha-1.example.com', 'www-ha-2.example.com'], } $ fab deploy -R test $ fab deploy -R www
  183. Helpers de interacción fabric confirm(question, default=True) abort(msg) error(message, func=None, exception=None,

    stdout=None, stderr=None) green(text, bold=False) red(text, bold=False) indent(text, spaces=4, strip=False)
  184. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  185. La seguridad es un tema extenso y delicado. Os invitamos

    a profundizar en cada uno de los aspectos antes de ponerlos en práctica. Los siguientes son sólo ejemplos y pueden contener errores. ⚠
  186. *iptables No lo son todo, pero sin lugar a dudas

    son un buen comienzo para evitarnos problemas.
  187. Funcionamiento iptables INPUT TRAFFIC FILTER NAT MANGLE PREROUTING PREROUTING FORWARD

    FORWARD POSTROUTING POSTROUTING INPUT INPUT LOCAL OUTPUT OUTPUT OUTPUT Forwarding process Local process ROUTING OUTPUT TRAFFIC
  188. Funcionamiento iptables INPUT TRAFFIC FILTER NAT MANGLE PREROUTING PREROUTING FORWARD

    FORWARD POSTROUTING POSTROUTING INPUT INPUT LOCAL OUTPUT OUTPUT OUTPUT Forwarding process Local process ROUTING OUTPUT TRAFFIC Tablas Cadenas
  189. Funcionamiento iptables INPUT TRAFFIC FILTER NAT MANGLE PREROUTING PREROUTING FORWARD

    FORWARD POSTROUTING POSTROUTING INPUT INPUT LOCAL OUTPUT OUTPUT OUTPUT Forwarding process Local process ROUTING OUTPUT TRAFFIC
  190. Tablas predefinidas  > ; FILTER. NAT. MANGLE. Tabla responsable

    del filtrado de paquetes. Todos los paquetes pasan por esta tabla. Tabla responsable de la reescritura de direcciones y/o puertos. El primer paquete de cada conexión pasa por esta tabla. Tabla responsable de ajustar opciones de paquetes (e.j) QOS. Todos los paquetes pasan por esta tabla.
  191. Tablas predefinidas  > ; FILTER. NAT. MANGLE. Tabla responsable

    del filtrado de paquetes. Todos los paquetes pasan por esta tabla. Tabla responsable de la reescritura de direcciones y/o puertos. El primer paquete de cada conexión pasa por esta tabla. Tabla responsable de ajustar opciones de paquetes (e.j) QOS. Todos los paquetes pasan por esta tabla.
  192. >FILTER. Tabla responsable del filtrado de paquetes. ☰INPUT ☰OUTPUT ☰FORWARD

    Todos los paquetes destinados a este sistema atraviesan esta cadena. Todos los paquetes creados por este sistema atraviesan esta cadena. Todos los paquetes que pasan por este sistema atraviesan esta cadena. El destino de cada una de las reglas dentro de las cadenas puede ser: ACCEPT, DROP, QUEUE, o RETURN (entre otros)
  193. >FILTER. Tabla responsable del filtrado de paquetes. ☰INPUT ☰OUTPUT ☰FORWARD

    Todos los paquetes destinados a este sistema atraviesan esta cadena. Todos los paquetes creados por este sistema atraviesan esta cadena. Todos los paquetes que pasan por este sistema atraviesan esta cadena. El destino de cada una de las reglas dentro de las cadenas puede ser: ACCEPT, DROP, QUEUE, o RETURN (entre otros)
  194. >FILTER:INPUT Cadena responsable del filtrado de paquetes de entrada. *filter

    :INPUT DROP [0:0] :OUTPUT ACCEPT [0:0] :FORWARD DROP [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -m state --state INVALID -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -s $IP/32 -d $IP/32 -p tcp --dport 80 -j ACCEPT
  195. fail2ban 6.2 Fail2ban nos permite bloquear ataques de fuerza bruta

    contra servicios como ssh, mail, http etc... • Muy sencillo de instalar y configurar. • Una buena contramedida activa. • Su funcionamiento se basa en leer los logs generados por estos servicios utilizando expresiones regulares. • Además de bloquear el trafico entrante desde estas fuentes se pueden desplegar otras medidas o enviar notificaciones. !h#p://fail2ban.org
  196. SSH root@... 6.3 Desactivar la cuenta de root es una

    de las primeras medidas a tomar al configurar un servidor. • Si disponemos de un servicio como fail2ban estaremos impidiendo en cierta medida que nadie tenga éxito al realizar un ataque de fuerza bruta. • Si por alguna razón el servicio está caído tendríamos nuestra cuenta de root expuesta. • Es muy recomendable no permitir conexiones ssh utilizando root. • Una vez en el sistema podemos identificarnos como root o utilizar sudo. PermitRootLogin no /etc/ssh/sshd_config
  197. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  198. munin 7.3 Ventajas • Muy sencillo de instalar y configurar.

    • Fácil de crear nuevas gráficas usando cualquier lenguaje de scripting. • Uso mínimo de recursos. • Un muy buen punto de partida. Desventajas • Sólo tres vistas por cada gráfica (diaria, semanal, anual) • Gráficas generadas cada ~5m. !h#p://munin9monitoring.org
  199. but... What’s next? Llegado el momento las métricas se convierten

    en críticas para analizar no solo la salud del sistema, si no la del negocio. ;
  200. graphite server web server db server ! carbon graphite tcp

    2003 diamond statsd udp 8125 diamond statsd udp 8125 diamond statsd udp 8125 tcp 80 ☁
  201. graphite server web server db server ! carbon graphite tcp

    2003 diamond statsd udp 8125 diamond statsd udp 8125 diamond statsd udp 8125 tcp 80 logs logs ☁
  202. graphite server web server db server ! carbon graphite tcp

    2003 diamond statsd udp 8125 diamond statsd udp 8125 diamond statsd udp 8125 tcp 80 app logs logs ☁
  203. graphite 7.4 No sólo datos... conocimiento! Descubrir que la carga

    de un servidor es 9.3 lo fines de semana a las 3am es útil pero... ¿cual es la causa? ¿Que otros síntomas hay? ¿Algún otro servidor se ve afectado? ¿Qué estaba haciendo el servidor? ¿Cuantos procesos teníamos en marcha? ¿Qué tamaño tenía la cola de emails? ¿Hace cuando que hicimos el último deploy?...
  204. graphite 7.4 from pystatsd import Client sc = Client('127.0.0.1', 8125)

    sc.increment('streetlife.emails.immediate.sent') Python echo "streetlife.emails.immediate.sent:1|c" | nc -w 1 -u 127.0.0.1 8125 Bash Son sólo paquetes UDP. Dado que añadir estadísticas consiste en enviar un simple paquete UDP a nuestro servidor de statsd, podemos hacerlo desde cualquier sitio! Nuestra aplicación, un script en bash ... Fire-and-forget!
  205. pingdom 7.6 Yo mi me conmigo... Es muy embarazoso darse

    cuenta que tu web se ha caído porque te lo diga un cliente. Hay docenas de servicios como pingdom que se dedican a testear tu web desde múltiples localizaciones. Features interesantes: • Monitorizar estado y tiempo de respuesta de páginas clave. • Comprobar tiempos de respuesta desde la otra parte del mundo. • Notificaciones SMS. • Uptime reports.
  206. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  207. $ server #1 $ ssh user1@server1 $ apt-get install paquete_x

    $ server #2 $ ssh user2@server2 $ apt-get install paquete_x
  208. $ server #1 $ ssh user1@server1 $ apt-get install paquete_x

    $ server #2 $ ssh user2@server2 $ apt-get install paquete_x $ server #3 $ ssh user3@server3 $ apt-get install paquete_x
  209. $ ssh user1@server1 $ apt-get install paquete_x $ server #1

    $ server #2 $ server #3 $ server #4 $ ssh user1@server1 $ apt-get install paquete_x $ ssh user3@server3 $ apt-get install paquete_z $ ssh user4@server4 $ apt-get install paquete_z
  210. $ ssh user1@server1 $ apt-get install paquete_x $ server #1

    $ server #2 $ server #3 $ server #4 $ ssh user1@server1 $ apt-get install paquete_x $ ssh user3@server3 $ apt-get install paquete_z $ ssh user4@server4 $ apt-get install paquete_z
  211. $ ssh user1@server1 $ apt-get install paquete_x $ server #1

    $ server #2 $ server #3 $ server #4 $ ssh user1@server1 $ apt-get install paquete_x $ ssh user3@server3 $ apt-get install paquete_z $ ssh user4@server4 $ apt-get install paquete_z
  212. $ $ $ $ $ $$$ $$$$ $ $ server

    #1 server #3 server #11 server #12 server #2 server #4 server #5 server #6 server #7 server #8 server #9 server #10 server #13 server #14
  213. $ $ $ $ $ $ $ $ $ $

    $ $ server #1 server #3 server #11 server #12 server #2 server #4 server #5 server #6 server #7 server #8 server #9 server #10 $ $ server #11 server #12 $ $ $ $ $ $ $ $ $ $ $ $ server #1B server #3B server #11B server #12B server #2B server #4B server #5B server #6B server #7B server #8B server #9B server #10B $ $ server #11B server #12B live staging
  214. $ $ $ $ $ $ $ $ $ $

    $ $ server #1 server #3 server #11 server #12 server #2 server #4 server #5 server #6 server #7 server #8 server #9 server #10 $ $ server #11 server #12 $ $ $ $ $ $ $ $ $ $ $ $ server #1B server #3B server #11B server #12B server #2B server #4B server #5B server #6B server #7B server #8B server #9B server #10B $ $ server #11B server #12B live staging $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_ $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x $ ssh user1@server1 $ apt-get install paquete_x
  215. Shit hapens happens... a lot. ⚠Repetition leads to boredom, boredom

    to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored.
  216. Provisioning 8.1 Automatizar la configuración y mantenimiento de tantos servidores

    cómo necesitemos. • Generar plantillas que nos permitan generar nuevas máquinas sin mucho esfuerzo y de manera automatizada. • Solucionar casos de catástrofe total ya que podemos regenerar nuestra arquitectura en otro datacenter sin problemas. • Todo del código que automatice este proceso se convierte en último termino en una excelente documentación. • “Code as Infrastructure”
  217. Puppet 8.2 Puppet es junto a Chef uno de los

    más utilizados. • Nos permite automatizar la configuración de servidores UNIX y Windows. • El lenguaje que se utiliza puede ser tanto Ruby como un lenguaje declarativo propio de Puppet en el que se definen tanto recursos del sistema como el estado de los mismos. • Servicios, usuarios, paquetes, ficheros... • Puppet extrae del sistema información como CPUs, memoria, discos direcciones IP etc... y compila nuestras plantillas junto a esta información. • Puede ejecutarse en modo arquitectura con un servicio central encargado de compilar las plantillas o en modo “solo-mode” en el cual se compilan las plantillas en cada servidor.
  218. Puppet 8.2 Una de las principales características de Puppet frente

    a otros sistemas de configuración es que es idempotente. Por ejemplo, podemos ejecutarlo cada 30 minutos y cerciorarnos de que todo está tal y como lo hemos definido. Esta es una gran ventaja dado que además de servirnos como bootstrap para nuevas máquinas, puppet nos permite administrar nuestras máquinas a lo largo de todo su ciclo de vida desde la creación mantenimiento y migración.
  219. file file { '/etc/nginx/nginx.conf': source => 'modules/nginx/nginx.conf', owner => 'root',

    group => 'root', mode => '640', require => Package['nginx'], notify => Service['nginx'] } ????
  220. file file { '/etc/nginx/nginx.conf': source => 'modules/nginx/nginx.conf', owner => 'root',

    group => 'root', mode => '640', require => Package['nginx'], notify => Service['nginx'] } ????
  221. service service { 'nginx': ensure => running, enable => true,

    hasstatus => true, hasrestart => true, }
  222. user, group user { 'tom': ensure => present, shell =>

    '/bin/bash', home => '/home/tom', managehome => true, } group { 'friends': ensure => present }
  223. nodes node 'web.example.com' inherits web_node { include munin include python

    user { 'tom': ensure => present, shell => '/bin/bash', home => '/home/tom', managehome => true, } ... }
  224. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  225. Características • Wrapper de virtualbox para crear y destruir máquinas

    desde la linea de comandos. • Permite crear “instancias” base para crear máquinas desde un estado concreto en cuestión de segundos. • Integración con Puppet y Chef entre otros. • Gracias a vagrant y puppet podemos lograr que todos los miembros del equipo dispongan del mismo setup en local sin mucho quebradero de cabeza. • La puesta en marcha de nuevos empleados se reduce a minutos en vez de días. • Gracias a la sencillez de uso podemos crear distintos setup en cuestión de minutos y comprobar su funcionamiento. • Funciona en todas las plataformas: Linux, OSX y Windows. Vagrant 9.1
  226. Añadir un box Vagrant 9.1 $ vagrant box add ubuntu-precise

    http://bit.ly/ubuntu-precise Crear una nueva instancia $ vagrant init ubuntu-precise Arrancar nuestra nueva máquina virtual $ vagrant up !h#p://vagrantbox.es $ vagrant ssh
  227. Vagrant::Config.run do |config| config.vm.define :web do |web| web.vm.box = "ubuntu-precise-64"

    web.vm.box_url = "http://bit.ly/ubuntu-precise" web.vm.host_name = "dev.example.com" web.vm.network :hostonly, "33.33.33.20" web.vm.forward_port(22, 2023) web.vm.forward_port(80, 8081) web.vm.share_folder("code", "/home/vagrant/code", "./code", :nfs => true) end config.vm.define :db do |db| db.vm.box = "ubuntu-precise-64" db.vm.box_url = "http://bit.ly/ubuntu-precise" db.vm.host_name = "dev-db.example.com" db.vm.network :hostonly, "33.33.33.21" db.vm.forward_port(22, 2024) db.vm.forward_port(5432, 5432) end end Múltiples boxes
  228. $ vagrant up web [web] VM already created. Booting if

    it's not already running... [web] Clearing any previously set forwarded ports... [web] Fixed port collision for 22 => 2222. Now on port 2202. [web] Forwarding ports... [web] -- 22 => 2023 (adapter 1) [web] -- 80 => 8081 (adapter 1) [web] Exporting NFS shared folders... [vagrant] Preparing to edit /etc/exports. Administrator privileges will be required... [web] Creating shared folders metadata... [web] Clearing any previously set network interfaces... [web] Preparing network interfaces based on configuration... [web] Booting VM... [web] Waiting for VM to boot. This can take a few minutes. [web] VM booted and ready for use! [web] Configuring and enabling network interfaces... [web] Setting host name... [web] Mounting shared folders... [web] -- v-root: /vagrant [web] -- manifests: /tmp/vagrant-puppet/manifests [web] -- v-pp-m0: /tmp/vagrant-puppet/modules-0 [web] Mounting NFS shared folders... [web] Running provisioner: Vagrant::Provisioners::Puppet... [web] Running Puppet with /tmp/vagrant-puppet/manifests/site.pp... stdin: is not a tty notice: Finished catalog run in 1.70 seconds vagrant up
  229. Chrome Plugins 9.4 Hay docenas de plugins que pueden hacer

    nuestro día a día mucho más sencillo. Estos son algunos de los que encontramos más interesantes, además del inspector que Chrome tiene integrado.
  230. dev 1 ops 2 env 3 browser http optimización arquitectura

    despliegue seguridad monitorización provisionamiento herramientas buenas prácticas
  231. CI: Jenkins 10.2 Características Servicio que nos permite automatizar (entre

    otras cosas) la ejecución de tests, compilación de documentación, generar reports de test coverage... Ejecuciones • Periódicamente • Por cada commit al repositorio. Configuración • Requiere de un poco de práctica pero una vez configurado no necesita mucho mantenimiento.
  232. Hipchat/IRC 10.3 La comunicación entre los empleados es muy importante

    (sobre todo cuando no siempre todo el mundo está trabajando desde la misma oficina). Ventajas • Histórico de todas las conversaciones. • Facilidad para compartir rápidamente ficheros, capturas de pantalla etc... • 0 Configuración y entrada amable para no techies. • Salas por departamentos, equipos etc... • Gaticos. • Notificaciones de deploy, mantenimiento etc...
  233. Recursos http://www.flickr.com/photos/marceldouwedekker/ http://pygments.org/ http://entypo.com/ Fuentes http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/ http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/ http://pyvideo.org/video/1677/how-the-internet-works http://es.wikipedia.org/wiki/Hypertext_Transfer_Protocol http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

    http://en.wikipedia.org/wiki/MIME_type http://silex.sensiolabs.org/doc/cookbook/json_request_body.html http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-1 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4 http://en.wikipedia.org/wiki/HTTP_cookie http://developer.yahoo.com/performance/rules.html http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/x64.html http://www.varnish-cache.org/docs/3.0/ http://haproxy.1wt.eu/download/1.5/doc/configuration.txt http://ontwik.com/python/django-deployment-workshop-by-jacob-kaplan-moss/ http://glue.readthedocs.org/en/latest/ http://library.linode.com/ http://code.flickr.net/2008/10/27/counting-timing/ http://codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything/ http://codeascraft.etsy.com/2010/12/08/track-every-release/ http://plusbryan.com/my-first-5-minutes-on-a-server-or-essential-security-for-linux-servers http://docs.vagrantup.com/v2/