Graphite: gran recurs per gràficar sistemes

després de un parell de caps de setmana aprenent el potencial del Grpahite i aprofitant que he descobert el Omnigraffle també m’he animat a fer uns dibuixets.

En aquest post recopilaré les comandes i configuracions aplicades per montar un lab en el macbook, on l’objectiu ha estat conèixer cadascun dels components que ens proporciona el Grpahite per a tal d’escalar-ho i també d’aconseguir una mica de alta disponibilitat.

Mostraré 3 escenaris i comentaré les configuracions, on anirà creixent la complexitat alhora que tindrem el montatge preparat per recollir/graficar més quantitat de dades de forma més segura, ja enfoncant-ho per entorns de producció.

Les eines que he fet servir han estat Vagrant+VirtualBox per a virtualizat i Ubuntu 13.04 LTS en cadascun dels nodes virtualitzats.

Evidentment, tot el que he practicat i après ha estat llegint les següents fonts:
https://launchpad.net/graphite
http://graphite.wikidot.com/installation
http://bitprophet.org/blog/2013/03/07/graphite/

Comencem per el escenari més sencill, on montem una maquina virtual Ubuntu a sobre el virtual Box amb Vagrant, on us pasaré les comandes utilitzades per a la instalació base.

	
wget https://launchpad.net/graphite/0.9/0.9.10/+download/check-dependencies.py
python check-dependencies.py
apt-get update
apt-get upgrade
apt-get update
apt-get -y install python-cairo python-django python-django-tagging python-memcache python-ldap python-zope python-twisted python-txamqp
python check-dependencies.py
apt-get -y install git vim 

wget https://launchpad.net/graphite/0.9/0.9.10/+download/whisper-0.9.10.tar.gz
tar xvfz whisper-0.9.10.tar.gz
cd whisper-0.9.10/
python setup.py install
cd ..
wget https://launchpad.net/graphite/0.9/0.9.10/+download/carbon-0.9.10.tar.gz
tar xvfz carbon-0.9.10.tar.gz
cd carbon-0.9.10/
python setup.py install
cd ..
wget https://launchpad.net/graphite/0.9/0.9.10/+download/graphite-web-0.9.10.tar.gz
tar xvfz graphite-web-0.9.10.tar.gz
cd graphite-web-0.9.10/
python setup.py install
cd ..

apt-get install libapache2-mod-wsgi
cd /opt/graphite/conf
cp carbon.conf.example carbon.conf
vim carbon.conf
cp storage-schemas.conf.example storage-schemas.conf
vim storage-schemas.conf
/opt/graphite/bin/carbon-cache.py start
cp /opt/graphite/webapp/graphite/local_settings.py.example /opt/graphite/webapp/graphite/local_settings.py
vim /opt/graphite/webapp/graphite/local_settings.py
rm /etc/apache2/sites-enabled/000-default
cd /opt/graphite
cp ./examples/example-graphite-vhost.conf /etc/apache2/sites-enabled/
chown -R www-data webapp
chgrp www-data storage
chmod g+w storage
su - www-data
 cd /opt/graphite
 PYTHONPATH=`pwd`/webapp:`pwd`/whisper python ./webapp/graphite/manage.py syncdb
cp /opt/graphite/conf/graphite.wsgi.example /opt/graphite/conf/graphite.wsgi
chgrp www-data /opt/graphite/storage/log/webapp
chmod g+w /opt/graphite/storage/log/webapp
/etc/init.d/apache2 restart

L’escenari que obtenir és el segment i detallem per sobre cadascuna de les peces:
scenari1

diamon.py: Python script que recull dades del sistema que volem graficar. Més info a aquí. Aquest dimoni enviará les dades en format plà al port 2003/tcp del carbon-cache.py amb el format: “NOM_DADE VALOR_DADA TIMESTAMP”. També ho pot enviar al port 2004/tcp si volem optimitzar l’enviament.
carbon-cache.py: Python Script que recull les dades tcp o udp, va emmagatzemant les dades en RAM i va volcant les dades al filesystem. La granularitat i la retenció de dades són definides a aquí.
Fitxer de dades WHISPER: En el sistema de fitxers tindrem un fitxer per a cada tipu de dada, amb extensió WSP
Una webapp python serà la encarregada de partir dels fitxers WHISPER permetré graficar-los i obetnir els reports.

El carbon-cache.py és el component més important, per una banda, a ell li direm com guardarem les dades i per una altra també defineix com s’escala tota la solució, ja que si volem més capacitat haurem de posar més carbon-cache.py (1 per vCPU) i un carbon-relay.py per sobre que vagi distribuint l’entrada de dades.
TIP: En el cas de voler fer sharding de dades, ho hauriem de definir a aquí.

A l’hore de agregar dades, ho tenim en 3 formes diferents:
– Les guardem totes les dades granulades en els fitxers WSP i en la webapp graphite serà on les pintem agregades utilitzant funcions i el gran amic wilcard “*”.
– Fem un agregat de dades en el carbon-cache.py a l’hora de emmagatzemar-ho a disc en el fitxer WSP, per defecte, quant tenim varies dades per a un mateix “instant” de temps, carbon-cache utilitza la funció de mitjana amb les dades entrants i només guarda un resultat. Podem canviar la funció de agregació i jugant amb els patrons en el carbon-cache.py, això ho especifiquem en el fitxer storage-aggregations.conf.
– Per sobre del carbon-cache.py hi posem un altre python script carbon-aggregator.py on anirà agregant les dades rebudes del collectors i les enviarà al carbon-cache.

Ara ja estem en condicions d’entendre el seguent resum:
summary

El segon escenari, duplicarem el numero de nodes i afegirem el carbon-relay.py en cadascun d’ells. En aquest hi definirem un factor de replicació de 2 i enviarem les dades el corresponent carbon-cache.py i al carbon-relay de l’altre node. Obtindrem el següent escenari:
HAcreuat

En la següent captura teniu els dos webapps on veiem que grafiquen dades dels 2 collectors:
Captura de pantalla 2014-04-26 a les 10.35.46

Finalment, l’ultime escenari que tenim es afegir un 3 node on únicament hi montarem un carbon-relay.py i serà ell qui rebi tot el trafic d’entrada i qui apliqui un factor de replicació 2, on passarà el trafic als carbon-relay.py que hi tenim en cada node. A més, duplicarem en cada node el numero de carbon-cache.py. En el fitxer relay-rules.conf definirem quines dades enviarem a cadascun del cabon-caches.py de cada node.

hafull

Per concluir, us paso el fitxer de Vagrant on teniu definides les 3 VMs per si algú el vol aprofitar.

❯ cat Vagrantfile
Vagrant::Config.run do |config|
    config.vm.define :graphiterelay do |graphiterelay_config|
        graphiterelay_config.vm.box = "graphiterelay"
        graphiterelay_config.vm.box_url = "package.box"
        graphiterelay_config.vm.forward_port 80,8000
        graphiterelay_config.vm.forward_port 8888,8888
        graphiterelay_config.vm.forward_port 443,44300
        graphiterelay_config.vm.network :hostonly, "192.168.50.2", :netmask => "255.255.255.0"
    end
    config.vm.define :graphite do |graphite_config|
	graphite_config.vm.box = "graphite"
	graphite_config.vm.box_url = "/Users/mcortinas/Boxes/ubuntu-precise12042-x64-vbox43.box"
        graphite_config.vm.forward_port 80,8001
        graphite_config.vm.forward_port 443,44301
	graphite_config.vm.forward_port 8888,18888
	graphite_config.vm.network :hostonly, "192.168.50.4", :netmask => "255.255.255.0"
    end
    config.vm.define :graphite2 do |graphite2_config|
        graphite2_config.vm.box = "graphite2"
        graphite2_config.vm.box_url = "package.box"
        graphite2_config.vm.forward_port 80,8002
	graphite2_config.vm.forward_port 8888,28888
        graphite2_config.vm.forward_port 443,44302
	graphite2_config.vm.network :hostonly, "192.168.50.5", :netmask => "255.255.255.0"
    end
end

Kibana ens ajuda amb els logs de AWS Cloudfront i WAF Akamai

L’anàlisis dels logs en qualsevol plataforma és molt important ja que ens permet veure quin és el comportament de cadascun dels components, alhora, ens permet des de corregir error, preveure averies a millorar el producte. De totes les solucions que he tingut la sort de probar, Splunk és la que més m’ha agradat. L’unic inconvenient d’utilitzar l’Splunk és el seu preu.

Degut al alt cost de l’Splunk i aprofitant que l’empresa on treballo necessita analitzar els logs de les CDNs de AWS Cloudfront i Akamai, vaig aprofitar per probar Kibana+Elastcisearch+Logstash. L’objectiu d’aquest post és mostrar el potencial d’aquesta combinació, una solució més econòmica que el gran tot poderos Splunk.

Comencem amb els logs de Akmaai, aquí us paso el format de log que volem analitzar, extret de la documentació oficial:

waf_logformat

apache_logformat

El filtre de logstash que he implementat és :

filter {
    grok {
      type => "esw3c_waf"
      match => { "message" => "%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] (?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest}) %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{QS:cookies} \"%{WORD:WafPolicy}\|%{DATA:WafAlertRules}\|%{DATA:WafDenyRules}\"" }
    }

    date {
      type => "esw3c_waf"
      match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
      locale => "en"
    }

}

Pel que fa als logs de AWS Cloudfront, el format del log esta documentat en aquest , però basicament és:

#Fields: date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes 
07/01/2012 01:13:11 FRA2 182 192.0.2.10 GET d111111abcdef8.cloudfront.net /view/my/file.html 200 www.displaymyfiles.com Mozilla/4.0%20(compatible;%20MSIE%205.0b1;%20Mac_PowerPC) - zip=98101 RefreshHit MRVMF7KydIvxMWfJIglgwHQwZsbG2IhRJ07sn9AkKUFSHS9EXAMPLE== d111111abcdef8.cloudfront.net http -

A més, logstash té implementat un input contra S3, ideal per a aquest cas.
Per la part del filtre, l’expressió és la seguent:

filter {
    grok {
    type => "aws"
    pattern => "%{DATE_EU:date}\t%{TIME:time}\t%{WORD:x-edge-location}\t(?:%{NUMBER:sc-bytes}|-)\t%{IPORHOST:c-ip}\t%{WORD:cs-method}\t%{HOSTNAME:cs-host}\t%{NOTSPACE:cs-uri-stem}\t%{NUMBER:sc-status}\t%{GREEDYDATA:referrer}\t%{GREEDYDATA:User-Agent}\t%{GREEDYDATA:cs-uri-stem}\t%{GREEDYDATA:cookies}\t%{WORD:x-edge-result-type}\t%{NOTSPACE:x-edge-request-id}\t%{HOSTNAME:x-host-header}\t%{URIPROTO:cs-protocol}\t%{INT:cs-bytes}"
}
mutate {
    type => "aws"
        add_field => [ "listener_timestamp", "%{date} %{time}" ]
    }
date {
      type => "aws"
      match => [ "listener_timestamp", "yy-MM-dd HH:mm:ss" ]
    }
}

Per cert, recomenar-vos activar el LifeCycle en el Bucket de S3 per a configurar un purgat de logs, creix ràpid (evidentment, el creixement també depen del vostre tràfic).

Un cop definit com farem la importació passem a comentar on guardarem les dades, ho farem en el Elasticsearch 1.0 aprofitant que ha sortit recentment. Vull destarcar 2 pluguins que als sysadmins els agradara conèixer, el pluguin HEAD i MARVEL.

Captura de pantalla del pluguin HEAD, on hem fet un index per dia/cdn
ElasticHead

Captura de pantalla del pluguin MARVEL
Marvel

Abans de pasar a la part de pintar les dades, us paso dos links amb les GROKS disponibles i una eina per a contruir-les
Llista de patrons GROK disponibles
Eina per construir les configuracions

Per acabar, per a pintar totes aquestes dades utilitzarem la aplicació de Kibana, una aplicació javascript que utilitza les dades del elaticsearch per a poder crear informes, gràfiques i filtres acurats.

Per començar he fet 2 dashboards molt simples, per una banda el de WAF de Akamai i per una altra el de Cloudfront.

Dashboard de Cloudfront:
CloudfrontDashboard

Dashboard de Akamai:
AkamaiDashboard

varnish-cache, un molt bon aliat per a la web

Ja fa un parell d’anys que faig servir el varnish cache i és un molt bon aliat de qualsevol plataforma web per descarregar als servidors http (apache, nginx, lighthttpd, etc… ) i al backend, ja sigui per aplicacions amb poc tràfic com per aplicacions/plataformes d’alt rendiment, on pot ser un CLAU aliat.

Per això, en aquest post enumenarem les raons principals d’implantar el varnish, citarem els processos i posarem 4 exemples de configuracions amb diferents proposits.

Bueno, començaré enumerant les 3 funcionalitats principals:
– Accelerador de continguts web, minimitzant considerablement els temps mitjans de resposta dels continguts dinamics d’un site.
– Alliberar de càrrega el backend, des dels servidors web i sobretot a les bases de dades, sql i nosql.
– Permetre servir continguts “caducats” en cas que la plataforma tingui problemes de rendiment.

Altres funcionalitats més avançades que podem fer amb Varnish es,
– Si treballeu amb CDNs pot fer el paper d’amortidor en moments de canvis bruscos de tràfic, per exemple, un campanya amb molt èxit, una noticia important, etc…
– Securitzar el website, per segons quines parts de la web podem exigir que les peticions haguin de complir uns determinats requeriments. Això també ho pot fer el apache, però aixi el podem alliberar d’aquestes tasques.
– En plataformes d’alt rendiment, si treballeu amb CDNs, per bloquejar l’accés a determinades parts de les webs que no es puguin processar per averia en el sistema.

Segur que podeu trobar altres funcionalitats, aquestes són les que he utilitzat.

La filosofia del Varnish es emmagatzemar a memòria volàtil tots els cantinguts “cachejables” i estalviar de cicles de proces i cicles d’espera d’entrada i sortida, es a dir, l’equiliri IO-CPU-RAM es veurà afectat així: disminuim IO, disminuim us de CPU, increment ús de memoria, on és molt important dimensionar bé la memòria que utilitzarem.

Un dels principals inconvenients dels Varnish és el HTTPS, encara que té el sentit. Varnish és un accelerador de continguts HTTP que vol disminuir el temps de resposta, el httpS és el contrari, requereix de temps de proces per a tal d’assegurar la seguretat. Conclusió, Varnish no es capaç i no ho serà mai de servir contignut per HTTPS. Només el podrem fer servir per aquelles parts del website que no siguin segures. També ho podeu utilitzar en parts de la web segures si poseu un nginx per davant, en aquest altre post teniu explicat millor aquesta solució.

D’altra banda, la corba d’aprenentatge del varnish es considerable, de fet, un graph em va ajudar a entendre totes les transicions possibles, es a dir, és el tipic aliat que si el compliquem molt es pot tornar en enemic. De fet, el varnish són 2 procesos un pare i un fill (fork), on el pare fa el paper de gestió i compila les configuracion escrites amb llenguatge VCL i el fill és qui realment fa realment les funcions descrites en la configuracio VCL. En aquest link ho explica detalladament.

Es a dir, la clau del varnish, és escriure un VCL amb allò que realment necessitem que faci. Aqui us deixo un graph que vaig decidir fer un cop vaig llegir la documentació oficial del varnish d’aquest link.
Varnish_subroutines_Graph

Seguidament posarem 3 exemples de fitxers basics de VCL i comentarem la seva finalitat:

Exemple 1

backend default {
  .host = "127.0.0.1";
  .port = "8080";
  .max_connections = 40;
  .first_byte_timeout = 180s;
  .between_bytes_timeout = 180s;
}

sub vcl_recv {
      return(pass);
}

Aquesta configuració l’únic que voliem és limitar la quantitat de connexions(max_connections) que li passarem al un apache en local, en aquest cap no cachejem res.

Exemple 2

backend default {
  .host = "127.0.0.1";
  .port = "8080";
  .max_connections = 200;
  .connect_timeout = 180s;
  .first_byte_timeout = 180s;
  .between_bytes_timeout = 180s;
  .probe = {
    .url = "/healthcheck.php";
    .timeout = 100 ms;
    .interval = 1s;
    .window = 10;
    .threshold = 8;
  }
}

sub vcl_recv {
  if (req.http.Host == "setup.domain.com")
  {
    set req.grace = 30s;
    return(lookup);
  }
  else
  {
   return(pass);
  }
}

sub vcl_fetch {
  set beresp.grace = 1h;
}

En aquest exemple només cachejem les peticions del domini “setup.domain.com”, domini intern de la plataforma que serveix les configuracions de l’aplicació. Ademés, volem que si el backend no respon, seguiran sen vàlids durant 1 hora. Això ho conseguim en les tres últimes linies de codi. El meu company Tomas té un article on exemplifica molt bé aquest comportament. Una de les coses més interessants del article de Tomàs es diferenciar les dues situacions en les que aquest parametre es important.
– No hi ha cap backend disponible, per tant servim contingut antic.
– Hi ha backends disponibles, i un fil ja ha demanat nou contingut. Mentre aquest nou contingut arriba des del backend, el varnish continua servint l’antic a la resta de fils.

Exemple 3

sub vcl_recv {
…
        if (req.url ~ ".*remindmethepassword.*" && !req.http.User-Agent) {
            error 403 "Forbidden";
        }
…
        return(pass);
}

En el exemple anterior, podem aferir-hi regles que augmentent la seguretat, per exemple, en les peticions que tinguin remindmethepassword en la URL necessitaran tenir el User-Agent, sino retornem un 403.

Exemple 4

backend default {
  .host = "127.0.0.1";
  .port = "8080";
  .max_connections = 200;
  .connect_timeout = 180s;
  .first_byte_timeout = 180s;
  .between_bytes_timeout = 180s;
  .probe = {
    .url = "/healthcheck.php";
    .timeout = 10 ms;
    .interval = 5s;
    .window = 5;
    .threshold = 3;
  }
}

sub vcl_error {
}

sub vcl_recv {
     if (req.restarts == 0) {
       if (req.http.x-forwarded-for) {
           set req.http.X-Forwarded-For =
               req.http.X-Forwarded-For + ", " + client.ip;
       } else {
           set req.http.X-Forwarded-For = client.ip;
       }
     }
     if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "PUT" &&
       req.request != "POST" &&
       req.request != "TRACE" &&
       req.request != "OPTIONS" &&
       req.request != "DELETE") {
         /* Non-RFC2616 or CONNECT which is weird. */
         return (pipe);
     }
     if (req.request != "GET" && req.request != "HEAD" && req.request != "POST" ) {
         /* We only deal with GET and HEAD by default */
         return (pass);
     }
   set req.grace = 30s;
    return(lookup);
}

sub vcl_fetch {
     if (beresp.ttl <= 0s ||
         beresp.http.Vary == "*") {
               return (hit_for_pass);
     }
 if(beresp.ttl > 0s){  unset beresp.http.Set-Cookie;}

  set beresp.grace = 1h;
  return(deliver);
}

En aquest exemple ja comença a ser més complert:
– limitat a 200 connexions, a més peticions, retornem 503.
– accepted petitions GET, HEAD, PUT, POST, TRACE, OPTIONS, DELETE.
– cachejem GET, POST, HEAD segons les capceleres HTTP que emet el backend
– en el moment en que anem a buscar un objecte en la cache, eliminem les capçeleres Set-Cookie
– tindrem 1 hora els elements en la cache, en cas que el backend estigui caigut o no respongui

Finalment, el ideal seria tenir ben segmentada la plana web amb les diferents seccions i tenir identificades les url’s de cadascuna d’elles facilitant així:
– La propia aplicació generi les capçeleres HTTP adecuades especificant quant de temps serà vàlid el contingut, segons quines seccións o accions tindrem uns temps de caducitat diferents
– La propia aplicació permite caducar/invalidar el contingut en el varnish en les situacions que ho necessitin.
– Securitzar les parts de la web que ho requereixin jugant amb les capçeleres

openSSL, recopilem comandes i eines web per securitzar

Tots tart o d’hora ens trobem amb la necessitat d’haber de securitzar comunicacions, i moltes vegades no tens a má la comanda openssl per segons quins casos, és per això que m’he decidit per recopilar-les.

– Per crear petición de certificar (CSR) i clau no signada, demana info per command line:

openssl req -nodes -new -keyout cortinasval.key.pem -out cortinasval.csr.pem
openssl req -nodes -new -keyout cortinasval.key.pem -out cortinasval.csr.pem rsa:2048 

– Per crear petición de certificar (CSR) a partir de clau, demana info per command line:

openssl req -nodes -new -key cortinasval.key.pem -out cortinasval.csr.pem

– Mostra la clau fingerprint d’un clau:

openssl x509 -subject -dates -fingerprint -in cortinasval.key.pem

– Generem clau de 4096 bits

openssl genrsa -out cortinasval.key.pem 4096

– Mostrem informació d’una solicitud de firma (CSR)

openssl req -text -noout -in cortinasval.csr.pem

– Mostrem informació d’un certificat generat

openssl x509 -in cortinasval.crt.pem -noout -text

– Creant fitxers PEM per als servidors

cat cortinasval.key.pem cortinasval.crt.pem cortinasval.dhp.pem > cortinasval.pem

– Firmar e-mails

openssl smine -sign -in msg.txt -text -out msg.encrypted -signer cortinasval.crt.pem -inkey cortinasval.key.pem

– Crear fitxer PKCS12

openssl pkcs12 -export -in cortinasval.crt.pem -inkey cortinasval.key.pem -out fitxer.p12 -name "Marc Cortinas"

– Mostrar certificats utilitzats en la comunicació a un socket

openssl s_client -showcerts -connect marc.cortinasval.cat:443 -CApath /etc/pki/tls/certs

Si volem crear una entitat certificadora ens hem d’assegurar que existeixin els fitxers index.txt(buit) i el serial(posat a 01), a mes, crearem directoris private i network. Editem el fitxer openssl.cnf i configurem default_days_certificate i private_key, finalment posem la cantitat de bits que utilitzarem per a la key (1024..2048)

– Per crear certificat CA

openssl req -new -x509 -days 3650 -keyout private/cortinasval-CA.key.pem -out ./cortinasval-CA.crt.pem 

– Exportar el certificat CA al format DER

openssl x509 -in cortinasval-CA.crt.pem -outform der -out cortinasval-CA.crt

– Revokem un certificat

openssl ca -revoke cortinasval.crt.pem

– Generem la llista de Revocacio de certificats

openssl ca -gencrl -out crl/cortinaslval-CA.crl

– Firmem la petició de certificat (CSR)

openssl ca -out cortinasval.crt.pem -in cortinaslval.req.pem

– Creem el parametre Diffie-Hoffman per l’actual CA

openssl dhparam -out cortinasval-CA.dhp.pem 1536

– Creem certificat auto-signat a partir d’una clau

openssl req -new -x509 -key cortinasval.key.pem -out cortinasval.crt.pem

– Encriptar un fitxer sencill

openssl enc -bf -A -in fitxer_de_test.txt

– Desencriptar un fitxer sencill

openssl enc -bf -d -A -in fitxer_de_test.txt

– Calcul de claus sha1

 openssl speed sha1

Pels servidors Webs que volguem fer ús del httpS, cada proveidor d’entitats certificadores te el seu manual, deixo aquí els 2 que he hagut d’instalar:
Thawte
Startssl

Eines utils per obtener información del nivel de seguretat:
Thhwte tool
SSL Labs

Quins conceptes hem de tenir clar?
– Tamany de Bits utilitzats a l’hora de crear el fitxers .pem
– SAN, noms de dominos acceptats pels certifictats, poden ser N noms, i tambe portar wildcard.

Balancejador HTTP/S econòmic: Nginx+Haproxy+Pacemaker

Destacades

Seguidament us explicaré com es pot montar un balancejador httpS molt econòmic i molt eficient, el qual s’ha implementat tan en entorns productius com no productius, la motivació inicial del qual va ser centralitzar el balanceig dels diferents entorns d’integració continua d’una aplicació web. En entorns productius també l’he implementat després de fer varies probes de rendiment amb el “ab” i el “siege” .

L’únic requeriment que hem d’asumir és allotjar tot tràfic dels diferents entorns en subdominis d’un domini (p.e.example.com), on podem tenir int01.example.com, int02.example.com, test01.example.com, test02.example.com, pre.example.com, etc..

Anàlogament, en els entorns de producció, podem fer la mateixa discriminació diferenciant el tràfic pels paisos(es.example.com,fr.example.com), plataformes(m.example.com), tipus de contingut(static.example.com).

Els objectius que em vaig marcar van ser:

  • Baix cost econòmic: utilitzarem programari de codi obert des dels operatius fins als dimonis: CentOS, Nginx, Haproxy, Pacemaker, Corosync.
  • Alta disponibilitat de maquinari i programari: a nivell de maquinari ho montarem en una infraestructura virtualitzada amb varis nodes físics i implemtarem el pacemaker+corosync per a tenir alta disponibilitat en els dimonis.
  • Centralitzar la negociació SSL de tota la plataforma en un punt inicial i alliberar càrrega SSL del reste de la plataforma.
  • Permetre més flexibilitat i control en els balancejos de cadascún dels entorns: haproxy permet fa possible controlar en un pool de balanceig si un frontal hi està activat segons el seu nivell de càrrega o si te connexió contra la base de dades, per exemple.
  • Tenir una plataforma securitzada, requeriment essencial sobretot en entorns productius.
  • Els dimonis que utilitzarem serà Nginx, Haproxy, Pacemaker i Corosync, tot programari lliure on abarata el cost considerablement.

    En el següent esquema es veu clarament l’arquitectura de tot el montatge.

    fisicalLB

    El comento breument, no entraré en detall en tot, em centro en lo important d’aquest post. Els navegadors dels usuaris fan les peticions a les empreses que fan de CDN, després aquestes peticions van a parar en la nostra plataforma on filtrarem el tràfic amb un firewall. Un cop les peticions són filtrades van a parar un nginx. La finalitat del nginx es discriminar el tràfic segons el entorn i centralitzar totes les negociacions SSL del tràfic HTTPS. Seguidament, les peticions passen a un haproxy on aquest balanceja entre els diferents frontals de cadascun dels entorns.

    Per tal de securitzar-ho tot, definirem 3 VLAN’s, dmz, frontend i backend. Tot el tràfic és filtrat pel firewall, el tràfic sortint, el entrant i el tràfic entre zones. En la DMZ posarem 2 maquines virtuals CentOs on tindrem els serveis de Nginx i Haproxy en actiu-passiu utlitzant pacemaker-corosync. En el frontend tenim els frontals de cadascun dels entorns i en el backend tenim les dades, mysql, cassandras, mongos, nfs, cifs, etc….

    Per exemplificar-ho millor, ens centrarem només en un entorn, int01.example.com.

    Primerament en la DMZ montarem una 2 màquines virtuals on hi tindrem 2 ip flotants, una per el nginx i l’altre pel haproxy. Jo ho he implemetat en una infraestructura virtualitzada vmware però també es poden montar solucions més econòmiques com XenServer, KVM, etc… Evidentment, sigui quina sigui la solució de virtualització, hem d’assegurar-nos que les màquines virtuales sempre estàn corrent en màquines físiques diferents.

    Les peticions entraran en la ip flotant del nginx, el nginx té dues funcions, centralitzar la negociació SSL i discriminar el tràfic per entorns. En el tràfic HTTPS afegirem una capçalera HTTP “X-forwarded-proto: https”, on l’apache la recollirà i activarà la variable HTTPS emmascarant-li a la aplicació. El tipus de certificat que afegirem en el nginx serà un certificat signat per una entitat certificadora oficial on el Common-Name que utilitzarem serà de tipus wildcard, es a dir, per aquest exemple, “*.example.com”, això ens facilitza molt la gestió del certificats i ens dona molta facilitat de gestió. En entorns de producció ho dimensionem assignant els valors correctes de worker_processes i worker_connections tenint en compte la formula: max clients = worker_processes * worker_connections/4.

    Seguidament les peticions passen al haproxy on aquest balanceja entre els diferents frontals de cadascun del entorn. El haproxy ens permet estriar l’algorisme de balanceig, jo acostumo a utilitzar Round Robin. A més, podem prefixar els rangs de IPs dels frontals que hi hauran en cadascun dels entorns, així podem desplegar més frontals en el cas que sigui necessari sense haber de reinicilitzar el dimoni.
    Haproxy fara una petició a un php que hi ha en cadascun dels frontals on retorna un “OK” si no està swapejant, no té molta càrrega i té conectivitat en les bases de dades. Cal remarcar que haproxy també ens permet realitzar balancejos “sticky” tan en aplicacions JAVA com PHP, depenentment d’una capçalara HTTP, habitualment les capçaleres JSESSIONID i PHPSESSID respectivament. (en apps ASP teniem ASPSESSIONID). En entorns de producció fixarem la variable maxconn tenim en compte que cada petició consumeix 17kb.

    Finalment les peticions arriben als frontals on primerament passen pel varnish i les peticions que no siguin cachejables arribaran finalment al apache, crec que aquests dos dimonis es mereixen un post especial per ells dos, que ja tinc en el backlog del blog.

    En el següent diagrama clarifica tota l’arquitectura:

    Diagrama Lògic

    Diagrama Lògic

    Seguidament posaré les configuracions més importants, Nginx, Haproxy, Pacemaker:

    Parametres del Nginx

    ....
    upstream http-example-int01 {
        server lb2-vip.example.com:8080;
        keepalive 16;
    }
    server {
            listen lb1-vip.example.com:80;
        server_name int01.example.com ~^.*-int01\.example\.com$;
    
            location / {
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header Host $host;
                    proxy_pass http://http-example-int01/;
                    proxy_redirect off;
            }
    }
    server {
            listen lb1-vip.example.com:443 ssl;
        server_name int01.example.com ~^.*-int01\.example\.com$;
    
            ssl on;
            ssl_certificate /etc/nginx/ssl/crt/concat.pem;
            ssl_certificate_key /etc/nginx/ssl/key/example.key;
    
            location / {
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto https;
                    proxy_set_header Host $host;
                    proxy_pass http://http-example-int01/;
                    proxy_redirect off;
            }
    }
    ....
    

    Parametres del Haproxy

    ...
    frontend example-int01 lb2-vip.grpprod.com:8080
        default_backend example-int01
    backend  example-int01
            option forwardfor
            option httpchk GET /healthcheck.php
            http-check expect string OK
            server  web01 x.y.z.w:80 check inter 2000 fall 3
            server  web02 x.y.z.w:80 check inter 2000 fall 3
            server  web03 x.y.z.w:80 check inter 2000 fall 3
            server  web04 x.y.z.w:80 check inter 2000 fall 3
            server  web05 x.y.z.w:80 check inter 2000 fall 3
    ...
    

    Parametres del Apache

    
     ServerName int01.example.com
        DocumentRoot "/srv/www/example/fa-front/public"
    
       <Directory "/srv/www/example/fa-front/public">
          Options -Indexes FollowSymLinks
          AllowOverride None
          Allow from All
          Order Allow,Deny
          RewriteEngine On
          RewriteCond %{HTTP:X-Forwarded-Proto} https
          RewriteRule .* - [E=HTTPS:on]
    
          RewriteCond %{REQUEST_FILENAME} -s [OR]
          RewriteCond %{REQUEST_FILENAME} -l [OR]
          RewriteCond %{REQUEST_FILENAME} -d
          RewriteRule ^.*$ - [NC,L]
          RewriteRule ^.*$ index.php [NC,L]
    
       SetEnv APPLICATION_ENV int01
       DirectoryIndex index.php
    
       LogFormat "%v %{Host}i %h %l %u %t \"%r\" %>s %b %{User-agent}i" marc.int01
       CustomLog /var/log/httpd/cloud-example-front.log example
    
    

    Parametres del Pacemaker

    node balance01
    node balance02
    primitive nginx lsb:nginx \
            op monitor interval="1s" \
            meta target-role="Started
    primitive haproxy lsb:haproxy \
            op monitor interval="1s" \
            meta target-role="Started"
    primitive lb1-vip ocf:heartbeat:IPaddr2 \
            params ip="x.x.x.x" iflabel="nginx-vip" cidr_netmask="32" \
            op monitor interval="1s"
    primitive lb2-vip ocf:heartbeat:IPaddr2 \
            params ip="y.y.y.y" iflabel="haproxy-vip" cidr_netmask="32" \
            op monitor interval="1s"
    group haproxy_cluster lb2-vip haproxy \
            meta target-role="Started"
    group nginx_cluster lb1-vip  nginx \
            meta target-role="Started"
    property $id="cib-bootstrap-options" \
            dc-version="1.1.7-6.el6-148fccfd5985c5590cc601123c6c16e966b85d14" \
            cluster-infrastructure="openais" \
            expected-quorum-votes="2" \
            stonith-enabled="false" \
            last-lrm-refresh="1355137974" \
            no-quorum-policy="ignore"
    rsc_defaults $id="rsc-options" \
            resource-stickiness="100"
    

    Tmux ha guanyat!

    Parlem de terminals de consola! Parlem de TMUX!!!
    Fa ja uns mesos que estem treballant en el departament amb aquest multiplexor de terminals i estem tant contents amb ell que s’ha guanyat un post!

    Encara recordo amb nostàlgia quant vem descobrir l’screen, eina que vem explotar en els servidors per

  • llençar processos que sabem que tenen una llarga durada, aqui tenim d’aliats el “&>>” i el time ( /usr/bin/time –format=”%E %S %U %P” –output=”logfile”)
  • llençar processos crítics on volem minimitzar els riscos de deixar-ho a mitges per algun tall de llum en el nostre laptop
  • llençar processos de forma desatesa que volem que es comportin com un dimoni, util quan et demanen llençar script com si fos un dimoni a mode urgent.
  • llençar processos on puguin fer seguiment als companys, útil per el processos que duran varis torns d’operadors
  • però com va dir un colega, l’screen està “depre” ( de deprecated! està passat de moda! ), amb tota la raó del món! ja veureu…

    D’una altra banda, Terminator(Linux) i iTerm(Mac) han estat les consoles utilitzades per realitzar varies tasques a la vegades en diferents servidors, per fer desplegaments de codi, canvis de configuracions, apagar focs, etc… Mitjançant les pestanyes pots tindre varies consoles connectades a diferents entorns o grups de servidors diferents, a més, cadascuna de les pestanyes les pots dividir en panells i executar les mateixes commandes o scripts alhora, MOLT útil!!!

    Doncs si aquestes funcionalitats del iTerm/Terminator ens han estat MOLT útils, imagineu-vos combinat amb el screen, i n’obtenim el TMUX!!. Ja fa uns quants caps de setmana que vaig passar una tarda per apendre les opcions i preparant-me la configuració a mida, i va ser MOLT productiu, ho recomano a qualsevol sysadmin. Haig de reconèixer que al principi vaig tenir una mica de reticiència però ara ho agraeixo.

    Descric el que més valoro:

  • tenim pestanyes per agrupar per roles/entorns els servidor on estic connectat
  • cadascuna de les pestanyes les podem dividir en panells
  • podem enviar comandes a tots els panells alhora d’una mateixa pestanya
  • podem redimensionar els panells fàcilment
  • podem desplaçar-nos pels diferents panells i/o pestanyes amb comoditat
  • NO necessitem de les X11, impresionant!
  • pots definir el buffer de cadascun del panell, recomano perdre uns moments per definir un gran buffer, sempre ho acabem utilitzant en algun moment
  • podem fer ús de plantilles, definint les pestanyes i les mides que obrirem i inclus automatitzar-ho
  • podem personalitzar quins són la combinació de tecles utilitzades per a fer ús del tmux
  • Adjunto el meu perfil del tmux en aquest post, on recalcaré les que trobo més interessants.
    Fitxer per descarregar: tmux.conf
    Path: $HOME/.tmux.conf

    # Avisa on fa perpellugues el nom de la pestanya on algun dels seus panells ha tingut activitat
    set -g visual-activity on
    # Per a cada panell guardem 10000 linies de buffer
    set -g buffer-limit 10000
    # C^B+r per recarregar en el tmux canvis en aquestes configuracion (aixo per nota!)
    unbind r
    bind r source-file ~/.tmux.conf  \; display "Reloaded!"
    #C^B+a :(All) per escriure en tots els panells de la pestanya
    unbind a
    bind a setw synchronize-panes on
    # C^B+o :(One) per escriure nomes en panell seleccionat
    unbind o
    bind o setw synchronize-panes off
    # Els indexos de panells i pestanyes comencen per 1, en comptes de 0 que és el per defecte
    set -g base-index 1
    setw -g pane-base-index 1
    # Personalitzant la barra d'estat
    # Powerline symbols: ⮂ ⮃ ⮀ ⮁ ⭤
    set -g status-utf8 on
    set -g status-left-length 32
    set -g status-right-length 150
    set -g status-interval 2
    
    set -g status-left '#[fg=colour15,bg=colour238,bold] #S #[fg=colour238,bg=colour234,nobold]⮀'
    set -g status-right '#[fg=colour245]⮃ %R ⮃ %d %b #[fg=colour254,bg=colour234,nobold]⮂#[fg=colour16,bg=colour254,bold] #h '
    set -g window-status-format "#[fg=white,bg=colour234] #I #W "
    set -g window-status-current-format "#[fg=colour234,bg=colour39]⮀#[fg=colour16,bg=colour39,noreverse,bold] #I ⮁ #W #F #[fg=colour39,bg=colour234,nobold]⮀"
    

    Aqui defineixo una plantilla del tmux per facilitar l’ús, molt útil a l’hora d’apagar focs.
    tmux_magento.sh
    El seguent gif mostra la execució de la plantilla que us he penjat, on hem connecto a tots els frontals d’un mateix role(magento), 8 frontals. La plantilla no deixa de ser un shell script on cada linia mofica el tmux on estem. De fet, per fer-lo funcionar, ÉS NECESSARI estar dins una pestanya del tmux i tenir els indexos dels panells configurats a 1, en comptes de 0 com té per defecte el tmux.

    tmux_magento

    Com podeu veure en el gif anterior, jo estic acostumat a connectar-me des d’un tmux a moltes consoles tty de varis servidors per SSH2. Un altre forme de treballar seria connectar-me a instancies de tmux en cadascun dels servidors a través d’un fitxer socket, en comptes de connectar-me a la consola, ideal per a compartir sessions remotes alhora entre varis operadors.

    Per finalitzar, les fonts consultades:
    Zooming Tmux Panes
    Simple Remote Pairing with Wemux
    Splitting terminal with tmux
    Manual del Tmux

    Projects Links:
    Tmux Project
    Wemux Project

    WordPress en Raspberry Pi

    Primer post del blog!! Tot just acabo de instalar el wordpress i vaig a recopilar tots els pasos.
    En la RaspberryPi he instalat com a operatiu un debian amb els daemons nginx, php-fpm i mysql per a fer correr el wordpress. Enumero els pasos:

      • Instalo berryboot en la targeta SD, on instalo el debian en la raspberry, aqui més info
      • Faig un “apt-get update” per actualitzar les fonts dels repositoris i instalo el meu editor preferit.
      • Instalo tots els dimonis:
    $sudo apt-get install nginx php5-fpm php5-cgi php5-cli php5-common php5-curl php5-gd php5-mcrypt php5-mysql mysql-server
    
    • Configuro el php-fpm amb el nginx, per utilizarem un file unix per comunicar la interpretació del  php amb el nginx que el servirà, en conclusió, definirem el virtualhost de nginx i settejarem una variable del php

    File: /etc/nginx/sites-available/marc.cortinasval.cat

    server {
            listen   80; ## listen for ipv4; this line is default and implied
            root /usr/share/nginx/www;
            index index.php;
            server_name marc.cortinasval.cat;
            location / {
                    rewrite  ^/?$  /blog/  redirect;
                    try_files $uri $uri/ /index.php;
            }
            location /blog/ {
                    try_files $uri $uri/ /blog/index.php?$args;
            }
            location ~ \.php$ {
                    fastcgi_split_path_info ^(.+\.php)(/.+)$;
                    fastcgi_pass unix:/var/run/php5-fpm.sock;
                    fastcgi_index index.php;
                    include fastcgi_params;
            }
            location = /favicon.ico {
                    log_not_found off;
                    access_log off;
            }
            location = /robots.txt {
                    allow all;
                    log_not_found off;
                    access_log off;
            }
            location ~ /\.ht {
                    deny all;
            }
            location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                    expires max;
                    log_not_found off;
            }
    }
    

    Ens asegurem que el socket unix definit en el fastcgi_pass del nginx correspon al del php-fpm

    $ grep listen /etc/php5/fpm/pool.d/www.conf
    listen = /var/run/php5-fpm.sock
    

    Finalment canviarem el parametre del cgi.fix_pathinfo a 0 en el file /etc/php5/fpm/php.ini

    $grep cgi.fix_pathinfo /etc/php5/fpm/php.ini
    cgi.fix_pathinfo=0
    
    • Instalo wordpress, per una banda els fitxers php de blog i per una altra preparem la base de dades de mysql que utilitzara i configurem la cadena de conexió de la aplicació.

    Baixem la aplicacio i la posem on toca

    $ cd /usr/share/nginx/www/
    $ wget http://wordpress.org/latest.zip
    $ unzip latest.zip
    $ mv wordpress blog
    $ rm latest.zip
    

    Preparem la base de dades en mysql, des del client del mysql

    mysql> CREATE DATABASE wordpress;
    Query OK, 1 row affected (6.58 sec)
    mysql> GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"localhost"IDENTIFIED BY "wordpress";
    Query OK, 0 rows affected (0.01 sec)
    mysql> flush privileges;
    Query OK, 0 rows affected (0.02 sec)
    mysql> exit;
    Bye
    

    Configurem la cadena de conexio de la aplicació

    cp wp-config-sample.php wp-config.php
    vim wp-config.php
    [\sourcecode]
    
    File /usr/share/nginx/www/blog/wp-config.php
    
    [sourcecode]
    /** The name of the database for WordPress */
    define('DB_NAME', 'wordpress');
    /** MySQL database username */
    define('DB_USER', 'wordpress');
    /** MySQL database password */
    define('DB_PASSWORD', 'wordpress');
    /** MySQL hostname */
    define('DB_HOST', 'localhost');
    

    Corregim permisos i reiniciem dimonis

    $sudo chown -R www-data.www-data /usr/share/nginx/www/
    $sudo service nginx restart 
    $sudo service php5-fpm restart
    

    Accedem via web on configurarem el nom del blog i el nom i password del usuari que administrarà el blog, en aquest pas serà quant es crearà la estructura de dades en el mysql.

    Configuro el permanent link del wordpress, aixo serveix per a tenir url’s més amistoses, com per exemple:  https://marc.cortinasval.cat/index.php/2013/03/wordpress-en-raspberry-pi
    Per aconseguir-ho, primer ens asegurem que tenim les seguents linies en el virtualhost de nginx i després anem a settings–>permalinks i configurem el format.
    File: /etc/nginx/sites-available/marc.cortinasval.cat

    ...
            location /blog/ {
                    try_files $uri $uri/ /blog/index.php?$args;
            }
    ...
    
    • Afegeixo i configuro els pluguins de wordpress, llisto aquí els que més m’han molat:

    SyntaxHighlighter Evolved
    WP to Twitter
    NextScripts: Social Networks Auto-Poster
    Author Spotlight (Widget)
    ExtraWatch Live Stats and Visitor Counter FREE
    Google Analytics
    Google Analytics for WordPress
    Social Login for wordpress
    User Photo

    • Poso un minim de categories i creo un menu amb aquestes categories
    • Finalment em baixo un thema i poso el menu en el tema
    • Poso el witget de delicious

    Escric aquest primer post i ja tinc el blog preparat per a recopilar més info!!!!

    Afinem RHEL/CentOs per a l’NGINX+HAPROXY en entorns de producció

    Per una banda, l’Nginx es un servidor WEB molt lleuger capaç de gestionar gran quantitat de connexions concurrents amb una eficaç gestió dels recursos, jo l’he utilitzat com a servidor proxy on he balancejat el tràfic de diferents aplicacions, tan en entorns productius com en entorns de desenvolupament.

    D’una altra banda utilitzarem el HAPROXY com a balancejador, ja que és un dels programaris més potents, lleugers i flexibles a l’hora de balancejar tràfic, poden implementar-ho com a balancejador HTTP o TCP, en el meu cas, HTTP amb balanceig enganxós. Per a aquest dimoni només he hagut d’afinar valors com tune.bufsize i tune.maxrewrite

    En un entorn productiu cal afinar la plataforma per a tindre’ls preparats per a que ens permeti un bon rendiment, l’objectiu del post es tenir ben recopilada tota la informació que he utilitzat. Per la xarxa hi han molta documentació sobre aquest propòsit, aquí únicament els recopilarem per a tenir-ho ben recol·lectat, al final del post hi llisto les fonts.

    CentOs/RHEL es la plataforma on ho he muntat, on el nginx únicament fa la funció de “reverse proxy” de diferents sites, descartant les funcionalitats de balanceig i de cache, on les he implementat amb HAProxy i Varnish-cache que ja he explicat en un altre post, aquí amb vull centrar en afinar-ho i llistar els petits problemes que m’he trobat/corregit.

    Per tal d’afinar-ho, segmentem 3 configuracions diferents:

    • Paràmetres del nucli del sistema operatiu
    • Límits del sistema Operatiu
    • Configuració del nginx

    Paràmetres del nucli del sistema operatiu

    Valor per defecte i aplicat:

    sysctl -w net.ipv4.tcp_congestion_control = cubic
    

    Algorisme de gestió dels trafic TCP, en el paràmetre net.ipv4.tcp_available_congestion_control podem saber quines opcions tenim carregades en el kernel de linux
    En CentOs6 tenim aquestes opcions: cubic reno, en el següent enllaç ho explica
    http://kaivanov.blogspot.com.es/2010/09/linux-tcp-tuning.html

    • reno: Traditional TCP used by almost all other OSes. (default)
    • cubic: CUBIC-TCP (NOTE: There is a cubic bug in the Linux 2.6.18 kernel used by Redhat Enterprise Linux 5.3 and Scientific Linux 5.3. Use 2.6.18.2 or higher!)
    • bic: BIC-TCP
    • htcp: Hamilton TCP
    • vegas: TCP Vegas
    • westwood: optimized for lossy networks

    Valor per defecte i aplicat:

    sysctl -w net.ipv4.tcp_window_scaling = 1
    

    Auto-escalat de la mida de la finestra de recepció TCP utilitzat, la finestra més gran pot ocupar 65,535 bytes. 1 ho activem i 0 ho desactivem.

    Valor per defecte:

    sysctl -w net.ipv4.ip_local_port_range="32768 61000"
    

    Valor per aplicat:

    sysctl -w net.ipv4.ip_local_port_range="2000 65000"
    

    Defineix el conjunt de ports locals que fa servir el SO per connexions les connexions TCP i UDP

    Valor per defecte:

    sysctl -w net.ipv4.tcp_max_syn_backlog="2048"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_max_syn_backlog="204800"
    

    Numero màxim de peticions per les connexions rebudes que encara no ha rebut el ACK del emissor, per defecte és 1024 i en sistemes de menys de 128Mb li assignem 128. Si el servidor pateix sobrecàrrega intenta incrementar aquest valor.

    Valor per defecte:

    sysctl -w net.core.somaxconn="128""
    

    Valor per aplicat:

    sysctl -w net.core.somaxconn="12800"
    

    Numero màxim de connexions que estan passant de LISTEN a ESTABLISHED, si es supera aquest número de connexions establertes el sistema les rebutja.

    Valor per defecte:

    sysctl -w net.ipv4.tcp_max_tw_buckets="262144"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_max_tw_buckets="524284"
    

    Numero màxim de connexions en estat TIME_WAIT, quant el superem, el sistema elimina els sockets i envia un avís. Aquest limit només s’utilitza per AVISAR de atacs DDOS. Aquest valor no s’acostuma a baixar sinó a incrementar proporcionalment amb la memòria, si les condicions de xarxa aixi ho requereixen.

    Valor per defecte:

    sysctl -w net.core.rmem_default="229376"
    

    Valor per aplicat:

    sysctl -w net.core.rmem_default="262142"
    

    Mida de la memòria asignada per defecte en la recepció pels socket

    Valor per defecte:

    sysctl -w net.core.rmem_max="131071"
    

    Valor per aplicat:

    sysctl -w net.core.rmem_max="524284"
    

    Mida màxima de memòria assignada per defecte en la recepció pels socket, aquest valor ha de ser superior al net.core.rmem_default
    Alerta! En RHEL compleix aquesta ultima recomanació però en CentOS6 no ho segueix

    Valor per defecte:

    sysctl -w net.core.wmem_default="229376"
    

    Valor per aplicat:

    sysctl -w net.core.wmem_default="262142
    

    Mida de memòria asignada per defecte en l’enviament pels socket

    Valor per defecte:

    sysctl -w net.core.wmem_max="131071"
    

    Valor per aplicat:

    sysctl -w net.core.wmem_max="524284"
    

    Mida màxima de memòria assignada per defecte en la emissió pels socket, aquest valor ha de ser superior al net.core.rmem_default
    Alerta! En RHEL compleix aquesta ultima recomanació però en CentOS6 no ho segueix

    Valor per defecte i aplicat:

    sysctl -w net.ipv4.tcp_rmem="4096 87380 4194304"
    

    Paràmetres de auto configuració TCP en la recepció de dades: El primer valor es la mida mínima de memòria utilitzat per a cada connexió TCP. El segon valor especifica la mida PER DEFECTE de buffer en la recepció per a cadascun dels socket. Aquest valor sobreescriu el /proc/sys/net/core/rmem_default utilitzat en altres protocols(!=TCP). El tercer i ultim valor especifica la mida màxima de memòria per la recepció de dades per a cadascun de les connexions TCP.

    Valor per defecte i aplicat:

    sysctl -w net.ipv4.tcp_wmem="4096 65536 4194304"
    

    Parametres de auto configuració TCP en la emissió: Aquests tres valors indiquen quin es l’espai de memòria assignat a cada socket en l’enviament de dades. El primer es la mida mínima, el segon la mida per defecte i el tercer la mida màxim del buffer reservat per a l’enviament de dades.

    Valor per defecte:

    sysctl -w net.ipv4.tcp_mem="753888 1005184 1507776"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_mem="753888 1005184 4194304"
    

    Paràmetres de auto configuració TCP: Defineix com el sistema operatiu gestion l’ús de la memòria per a les connexions TCP. El primer valor especifica el umbral mínim. Per sota d’aquest valor el SO no va cap canvi de gestió de la memòria pels diferents socket TCP. El segons valor indica la mida per defecte permès per a 1a connexió TCP, el tercer valor ens indica la mida màxima de memòria utilitzat per les connexions TCP, si el SO consumeix més memòria per a les connexions TCP comença a fer DROPS de les noves connexions.

    Valor per defecte i aplicat:

    sysctl -w fs.file-max="793779"
    

    Defineix el número màxim de descriptors de fitxers que gestiona el SO (Recordem que tant els sockets com els fitxers son descriptors de fitxers en entorns Linux/Unix)

    Valor per defecte:

    sysctl -w net.ipv4.tcp_tw_reuse="0"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_tw_reuse="1"
    

    Permetre reutilitzar els sockets que estan en TIME_WAIT quant es segur des del punt de vista del protocol. Non hauria de ser modificat sense la supervisió d’un expert 😉

    Valor per defecte:

    sysctl -w net.ipv4.tcp_tw_recycle="0"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_tw_recycle="1"
    

    Permetre la rapida reutilització de sockets en TIME_WAIT. Activant aquesta opcio no es recomenada si estas fent NAT. En canvi amb el HAPROXY es molt recomenable per baixar CONSIDERABLEMENT el numero de connexions en TIME_WAIT. Adjunto una captura de graphite on podem veure el canvi només aplicant aquesta variable.
    haproxy

    Valor per defecte:

    sysctl -w net.ipv4.tcp_max_orphans="262144"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_max_orphans="30000"
    

    Número màxim de TCP sockets orfans que no estan connectats a cap proces. Quant aquest numero s’excedeix, les connexions orfanes es resetejant i es notifica amb una alerta. Aquest limit existeix nomes per prevenir atacs de denegament de servei. Decrementar aquest valor no es aconsellable. Les condicions de xarxa poden requerir que incrementis el numero de orfans permesos, cadascun dels orfans poden ocupar aproximadament 64k de memoria NO-SWAPEJABLE. El valor per defecte es igual que el parametre NR_FILE del kernel, en 262144 en RHEL6/CentOS6, ajustat a la memoria del sistema.

    Valor per defecte:

    sysctl -w net.ipv4.tcp_synack_retries="5"
    

    Valor per aplicat:

    sysctl -w net.ipv4.tcp_synack_retries="3"
    

    Número màxim de vegades que un segment SYN/ACK per a una connexio TCP passiva sera retransmitit. Aquest numero no pot excedir de 255.

    Límits del sistema Operatiu
    Amb concordança amb el últim paràmetre explicat en l’apartat anterior, hem de ampliar el numero de descriptors de fitxers que permetem realitzar al usuari que instancia el nginx, afegint les línies següents al fitxer /etc/security/limits.conf

    nginx       soft    nofile   10000
    nginx       hard    nofile   30000
    

    Configuració del nginx
    No menys important que les configuracions de sistema són la configuració del nginx.

    Primerament cal dimensionar la memòria i la CPU del sistema. Cal dimensionar assignant els valors correctes de worker_processes i worker_connections tenint en compte la formula: max clients = worker_processes * worker_connections/4. En el meu cas tenim més de 1200 connexions concurrents on tinc una maquina amb 8 vCPUs i 8GB de RAM, on he assignat:

    worker_processes  8;
    events {
        worker_connections  1024;
    }
    

    Seguidament segons el tipus d’aplicacions que estiguem balancejant amb l’nginx, tenint en compte el número i el tipus d’aplicacions, les connexions concurrents que requereixen, la mida tant de les capçaleres com del cos, tant de les peticions com de les respostes, caldrà afinar els següents paràmetres.

    ## Size Limits
      client_body_buffer_size     128K;
      client_header_buffer_size   8k;
      client_max_body_size          1M;
      large_client_header_buffers 8 32k;
    ## Timeouts
      client_body_timeout   60;
      client_header_timeout 60;
      expires               24h;
      keepalive_timeout     60 60;
      send_timeout          60;
      proxy_connect_timeout 60s; 
      proxy_read_timeout 120s;
      proxy_send_timeout 120s
    ## TCP options
      tcp_nodelay on;
      tcp_nopush  on;
    ## Proxy options
      proxy_buffering           on;
      proxy_buffers 16 16k;
      proxy_buffer_size 32k;
    ##Fix header too big http://forum.nginx.org/read.php?2,188352
      fastcgi_buffers 16 16k;
      fastcgi_buffer_size 32k;
    

    Aquests paràmetres els utilitzo per a publicar aplicacions PHP i contingut estàtic on es connecten tot tipus de navegadors tan estacions de treball, ordinadors portàtils, dispositius mòbils com tabletes des de diferents proveïdors ADSL, 2G, 3G, 4G, WiMax, FTH, etc…. Remarco que no utilitzo la funció de cache del nginx.
    Seguidament faig esmena de 2 problemes que m’he trobat amb les nostres aplicacions.

    Per part del Nginx, si volem augmentar les mides de la capçalera que reben del frontal a més de 16kb, també s’ha de parametritzar el parametres fastcgi_buffers i fastcgi_buffer_size tal com ho reporten en el foro aquest link, no li vaig trobar logica però va ser aplicar-ho i desapareixer.

    Per part del Haproxy també hi han limitacions del tamany del buffsize, en Centos/RHEL els paquets compilats del repositori yum estan tots a 16kb, en el foro de HAPROXY trobem com recompilar-ho
    Molt útil per corregir aquest tipus de errors:

    echo show errors | socat stdio unix-connect:<path-to-socket>
    

    Les principals fonts que he seguit són:

    http://linux.die.net/man/7/tcp
    http://dak1n1.com/blog/12-nginx-performance-tuning
    http://www.cyberciti.biz/faq/rhel-linux-install-nginx-as-reverse-proxy-load-balancer/
    http://www.cyberciti.biz/faq/linux-unix-nginx-too-many-open-files
    http://www.exceliance.fr/sites/default/files/biblio/art-2006-making_applications_scalable_with_lb.pdf
    http://comments.gmane.org/gmane.comp.web.haproxy/11145

    blog personal amb domini .CAT propi, distribució i hospedatge per menys de 7€/any

    Avui és un dia trist professionalment parlant perquè el passat divendres en Tomas Nuñez, company de feina amb qui m’ho he passat molt bé durant els darrers 2 anys, va finalitzar el contracte i ha marxat al Canada a començar una nova experiència  aprofito el post per desitjar-li tota la bona sort en la seva nova aventura on estic convençut que s’ho passarà molt bé!

    A més, també cal remarcar que la motivació inicial de trastejar tot l’esmentat en aquest post va néixer sopant amb els ex-companys de la EGB, on un d’ells, l’Estanis Plantada, un geògraf viatger apassionat de la bicicleta vol fer montar-se un site per anar publicant les seves experiències.

    Dit això, vaig per feina, en aquest post us explicaré com publicar un blog (en el meu cas el que tenia en la RaspberryPi) en el “cloud” (Amazon) on l’hi traurem un millor rendiment per menys de 8€ el primer any, no entraré molt en detall tècnic, únicament el que és important és tenir recopilades TOTES les funcionalitats implementades amb un cost molt baix, alhora, recopilo els links de les diferents fonts que he anat coneixent i jugant. Per a cada punt teniu el link de les fonts consultades on he tret la informació.

      • Registre de domini

    En poc menys d’uns mesos els dominis .puntCAT han baixat molt el seu preu, vaig repassar els registradors i el més econòmic va ser CDMON que per 6.95€. Els amics de Google han llençat als EUA, Canada i ha algun país més el projecte GYBO, on pots conseguir gratis el primer any el registre de un 1 domini amb TLD del tipus .ORG .COM .CA .IN, després val 5$/mes.

      • Distribució i securització del blog gràcies a la CDN de CloudFlare

    Si volem minitzar el trafic entre el usuari final i el hosting que tindrem en Amazon, podem activar gratuitament la funcionalitat de CDN de Cloudfare, a més, també hi afegim un petit control de seguretat. L’unic inconvenient és que la versió gratuita no soporta la distribució de continguts utilitzant el protocol segur HTTPS.

    Muntem un node virtual en Amazon EC2 on hi posarem el blog (en el meu cas he migrat el blog de la RaspberryPi), aquí és on els tècnics posem més de la nostre part :). A més, cal remarcar que tindrem control total d’una maquina virtual en 1 dels CPD’s, molt útil per qualsevol tècnic que ho munti on ho aprofitarà per trastejar i implementar altres eines (ja podeu estar segurs). A destacar! tenim gratis fins a un volum de 30GB en Amazon S3! (podem muntar un owncloud i ja tenim més que GoogleDrive i Dropbox!)

    Doncs tot això ho tenim muntat en poc més d’unes hores on només hi hem invertit menys de 7€!

    Publicant Jira per httpS

    Si mai heu de publicar la aplicació de ticketing de l’empresa a internet, aqui us deixo un petit how-to de com ho he fet amb el JIRA.

    Els objectius, per variar, son principalment tenir alta disponibilitat i securitzar la publicació. Per aquest motiu ho podem fer com a minim amb 2 VLAN’s, frontend i backend, on en el frontend posarem un nginx i en el backend posarem la aplicació de JIRA.

    En el frontend posarem un servidor nginx que farà de proxypass cap el backend, en ell delegarem la negociació SSL del httpS. Aquest servidor nginx el posarem a sobre d’una plataforma virtualitzada on hi aplicarem HA, a més, podem afegir tenir un actiu-passiu utilitzant pacemaker o keepalived. Finalment hi posarem un filtrat per accedir a la part de administració de la aplicació.

    En el backend hi tindrem el servidor JIRA, on aqui la alta disponibilitat només la hem aplicat a nivell de màquina virtual, ja que la aplicació JIRA no està preparada per tenir-la clusteritzada.

    Finalment us deixo els fitxers de configuració, el del virtualhost del nginx:

    server {
        listen x.y.z.w:80;
        server_name jira.example.com;
        rewrite        ^ https://$server_name$request_uri? permanent;
    }
    server {
        listen x.y.z.w:443 ssl;
        server_name jira.example.com;
        ssl on;
        ssl_certificate /etc/nginx/ssl/crt/concat.pem;
        ssl_certificate_key /etc/nginx/ssl/key/example.key;
        location / {
            client_max_body_size 10M;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header Host $host;
            proxy_pass http://http-jira/;
            proxy_redirect off;
        }
        include security_jira.conf;
    }
    

    Per tal de securitzar l’accés a la part de administració del Jira, us adjunto el fitxer security_jira.conf

    Finalment en el servidor de java-standalone hem de indicar que el les url’s les ha de montar amb el https, indicant el nom de domini i el port el cual faran les seguents peticions:

    scheme="https"
    proxyName="jira.example.com"
    proxyPort="443"
    

    Quedarà el fitxer així:

    ...
        <Service name="Catalina">
            <Connector port="8080"
                       maxThreads="150"
                       minSpareThreads="25"
                       maxSpareThreads="75"
                       connectionTimeout="20000"
                       enableLookups="false"
                       maxHttpHeaderSize="8192"
                       protocol="HTTP/1.1"
                       useBodyEncodingForURI="true"
                       redirectPort="8443"
                       acceptCount="100"
                       disableUploadTimeout="true"
                       scheme="https"
                       proxyName="jira.example.com"
                       proxyPort="443"
    />
    ....
    

    A disfrutar!