AZ Network Specialist

Per ISP che vogliono appoggiarsi a servizi di alta qualità
Per ISP che vogliono raggiungere nuovi obiettivi

AirTunes Con Linux

In un passato in cui utilizzavo un iMac come dispositivo desktop principale, acquistai una base Apple AirPort Express configurandola semplicemente come client della rete WiFi esistente in casa con un duplice scopo: collegare via Ethernet la mia nuova televisione in modo da sfruttare le caratteristiche “da mediacenter”, e collegarla tramite cavo audio all’Home Theatre per riprodurre in streaming le tracce audio di iTunes.

Francamente questa seconda funzionalità non l’ho mai sfruttata più di tanto, per cui quando ho deciso di abbandonare MacOS per avere Linux anche sul desktop, non ho mai approfondito come far funzionare lo streaming… ma recentemente mi sono preso la briga di trovare una soluzione.

Facendo qualche ricerca, ho scoperto che il sistema sonoro PulseAudio installato di default su Gnome, offre questa funzionalità integrata per cui sembrava cosa abbastanza semplice far funzionare tutto l’insieme: secondo teoria, andando in “Impostazioni audio” avrei dovuto vedere l’AirPort all’interno della scheda “Uscita” come dispositivo su cui riprodurre l’audio… ma ovviamente non era presente.

Il mio primo dubbio riguardava proprio PulseAudio: il protocollo di comunicazione che Apple chiama “AirTunes” in realtà si chiama “RAOP” e in alcune distribuzioni (ad es. Ubuntu) serve un plugin di PuseAudio per abilitarlo. Al contrario, su Arch Linux (la distro che uso sul desktop), il plugin RAOP è compilato all’interno di PulseAudio per cui non c’è nulla da installare.

La colpa è di qualcosa d’altro.

La colpa, infatti, era la mancanza di un altro componente: la compatibilità con il sistema Bonjour di Apple che consente “l’annuncio in rete” dei dispositivi. La compatibilità su Linux con il protocollo Bonjour è fornita dal demone Avahi, installato di default su buona parte delle distribuzioni. Una volta abilitato, il dispositivo AirPort è apparso magicamente nella lista dei dispositivi audio in uscita di PulseAudio.

Sembrava tutto fatto, però cercando di far emettere qualche suono al mio Home Theatre non si sentiva nulla… e il PulseAudio crashava inesorabilmente.

A questo punto ho riavviato PulseAudio in modalità debug per capire dove stesse il problema: dai messaggi ho visto che l’AirPort si annunciava con l’IP APIPA di classe 169.X.X.X al posto dell’IP della mia LAN casalinga (192.168.0.X per la cronaca) per cui il server PulseAudio non trovava il dispositivo e andava in crash. Francamente non capisco perchè l’AirPort si annuncia con quell’IP (o perchè il server PulseAudio vede solo quell’IP): nella mia rete c’è un server DHCP configurato per assegnare un IPv4 statico all’AirPort e, inoltre, gira un demone Radvd che assegna all’AirPort un indirizzo IPv6 statico.

Tra l’altro, in tutta sincerità, una volta abilitato il demone Avahi sul mio desktop, ho visto un aumento dei pacchetti di rete considerevole che, per come sono fatto, non mi è piaciuto.

Bene, visto che l’Avahi non mi soddisfa, che alternative abbiamo?

L’alternativa più semplice (e le cose semplici che funzionano a me piacciono particolarmente) è settare manualmente la periferica PulseAudio attraverso uno script da lanciare all’avvio della sessione Gnome:

1
2
#!/bin/bash
/usr/bin/pactl load-module module-raop-sink server=192.168.0.x

Grazie a questo semplice script, il sistema PulseAudio aggiungerà il device AirPort come “RAOP sink ‘192.168.0.x’”… e ora l’audio funziona.

Ho avuto un ultima difficoltà con il mio player preferito: Audacios.

Di default, Audacios usa come plugin di uscita Alsa e la qualità dell’audio in streaming sull’AirPort è a dir poco oscena! Basta settare come Plugin di uscita PulseAudio e come profondità di bit 32 per avere un audio di qualità anche sullo stereo.

La Mia Nuova Configurazione Cloud

Dall’inizio della mia esperienza con OpenNebula, ho provato parecchie soluzioni di storage, ma solo ora ho trovato una combinazione che soddisfa le mie esigenze di velocità, sicurezza e contenimento dei costi.

Innanzi tutto: non esiste mai la soluzione perfetta, ma esistono soluzioni diverse ciascuna delle quali si adatta meglio a risolvere un determinato problema. Nel mio caso, trattandosi di un cloud privato, l’esigenza principale è quella di avere una soluzione sufficientemente performate ma contnedo i costi.

Nel mio cloud privato, ho 5 server KVM che ospitano un totale di 20-30 VM: alcune sono stressanti solo per la CPU (mail scanner, DNS, ecc.), altre purtroppo generano molto traffico I/O (MySQL server per LAMP, Syslog server, ecc.): le seconde sono il problema, perche le soluzioni precedentemente adottate non hanno soddisfatto adeguatamente richieste di I/O.

La mia prima soluzione è stata quella di creare uno storage server che esportasse una partizione (c)LVM via AoE (che ha un overhead inferiore rispetto ad iSCSI): il carico di lavoro sul server era davvero elevato e la velocità di I/O non troppo veloce. Ok, ho imparato la lezione: se devi avere uno storage condiviso, non usare un server economico, ma usane uno ottimizzato per lo storage con dischi ad alta velocità, controller potenti con una buona dose di cache, LAN a 10GB… or semplicemente, compra una SAN FC ;-)

Il mio secondo test è stato con uno storage basato su MooseFS: qui ho ottenuto risultati contrastanti. Ho un cliente che è davvero soddisfatto delle prestaizione e ha all’attivo un cloud con 10 storage server e 10 Hypervisor XEN; nel mio private cloud, con solo 3 storage server (un master e 2 chunk) l’I/O è lento come nella prima soluzione: nessun beneficio dall’uso di due server in bilanciamentoe 2 porte LAN ad 1 Gb in bonding è un altro collo di bottiglia. La lezione che ho imparato qui: per avere uno storage cluster dalle prestazioni soddisfacenti è necessario usare parecchi server.

Il mio terzo ed ultimo setup che vi racconto ora è… non usare un solo storage condiviso, ma distribuirlo sui server HyperVisor.

Partiamo da una considerazione: i miei “vecchi” HyperVisor sono dei Dell R410 dotati di 2 CPU quad-core e 32 GB Ram; se riuscissi a far stare in un cabinet Rack da 1U, 2 Motherboard Mini-ITX con una CPU Core i7 (non esattamente come la CPU Xeon dell’R410 ma non troppo distante) e 16 GB Ram… avrei la stessa potenza di calcolo, nello stesso spazio divisa su due server. E se riuscissi a farci stare anche 2 dischi SATA ad alta velocità come i WD Velociraptor per le VM e due dischi SSD per il SO, potrei usare DRBD in modalità Attivo/Attivo con cLVM o GFS2 per avere uno storage in HA dalle prestazioni accettabili per le VMs instanziate in questo “double-server”.

Ora ho 4 mini-itx double server ciascuno con questa configurazione; in OpenNebula, ogni double-server viene visto come un “cluster” separato e il disco DRBD è il datastore associato al cluster.

Ovviamente non posso migrare una VM tra due cluster diversi, ma al momento questa soluzione risponde bene alle mie esigenze di velocità, il costo di ogni “double-server” è inferiore rispetto ad un vero server ad 1U e il consumo di energia elettrica nel datacenter è diminuito.

Sostituzione Storage Server

Come accenntato in questo articolo, stiamo per iniziare la progressiva sostituzione dei server più obsoleti (e quindi più esosi in termini di consumo elettrico) con apparecchi di nuova concezione basati su architettura Mini-ITX/Sandy Bridge più performanti e a basso consumo.

Lo scopo di questa iniziativa è di rendere il datacenter più ecosostenibile diminuendo drasticamente il consumo di elettricità sia per i server, sia per gli impianti di smaltimento del calore prodotto.

Nella settimana dal 4 al 10 marzo, saranno sostituiti i primi due apparecchi per cui potrebbero verificarsi brevi interruzioni di servizio durante lo spostamento delle VM interessate sui nuovi server.

Ci scusiamo anticipatamente per gli eventuali piccoli disservizi.

Alla Fine Non Ho Resistito

Come al solito dimostro di cedere alla voglia di cambiamento: cambio distribuzioni sul mio PC e motori del mio sito web, con la stessa frequenza con cu mi cambio i maglioni!
Ebbene, alla fine non ho resistito al richiamo della moda del momento: ecco spostato il mio blog sulla piattaforma Octopress.

Purtroppo (anzi per fortuna) i crescenti impegni non mi consentono di mantenere con la dovuta attenzione la piattaforma di blog realizzata a fine 2012 in Rails: le funzionalità aggiuntive quali l’integrazione con il CRM latitano per mancanza di tempo, l’importazione dei contenuti dal vecchio blog ancora di più…
A questo punto era necessaria una scelta razionale e non di cuore: abbandonare una piattaforma autocostruita per una di pubblico dominio che mantenesse le prerogative di leggerezza e funzionalità che non ho più trovato in Wordpress. In questo modo spero di avere più tempo per curare di più i contenuti piuttosto della forma.

Ammetto di non aver lavorato molto sulla grafica in quanto ho deciso di utilizzare il tema di default di Octopress che mi è sempre piaciuto molto sia per leggibiltà che per leggerezza; spero che questa nuova versione del sito piaccia anche a tutti voi!

Ma cos’è Octopress?
Octopress è un vecchio modo di fare siti, che però si addice bene alle necessità di velocità e semplicità dell’Internet moderno: a differenza dei CMS tradizionali che elaborano la singola pagina ad ogni richiesta, con Octopress si elabora tutto il contenuto del sito in locale una sola volta e si carica sul server il codice html già pronto. Si spostano quindi i tempi necessari per l’elaborazione delle pagine sul computer dell’autore del blog, sollevando i server da questo compito… a tutto beneficio della velocità del sito.
In pratica con Octopress si hanno a disposizione dei comandi scritti in Ruby che servono per “compilare” il blog. Difatti, sostanzialmente, si realizzano i contenuti del blog in locale con il linguaggio markdown e poi si lanciano i comandi di Octopress per trasformare i file markdown in file html statici. Ovviamente si hanno a disposizione temi, che non sono altro che dei semplici fogli di stile .css collegati alle pagine html: è attraverso questi css che il sito risuta gradevole esteticamente ed è “responsive”, quindi visualizzabile correttamente anche su dispositivi mobili con schermo ridotto.

CentOS E Il Boot Senza Scheda Video

Anticipo in questo Post che sto seriamente valutando la tecnologia Mini-ITX in accoppiata con CPU Sandy Bridge anche per i server del Datacenter: questo per sostituire i server più anziani con apparecchi dal consumo molto più basso.

In quest’ottica ho acquistato un primo kit “da sperimentazione” giusto per capire la fattibilità del progetto: nella lista della spesa c’era il cabinet 1U capace di ospitare due schede madri, le due schede madri in formato Mini-ITX, la RAM, i dischi e, ovviamente, le due CPU.

Ammetto la mia ignoranza in termini di CPU Sandy Bridge, per cui ho fatto un acquisto poco oculato guardando esclusivamente al fattore economico a discapito delle prestazioni. Il primo errore è stato quello di scegliere una CPU di classe i5 a non i7: anche se il clock e il numero di core è identico, le CPU i5 non sono dotate di HyperThreading per cui in ambienti virtualizzati si hanno a disposizione solo 4 CPU virtuali al posto di 8. E’ vero, le prestazioni usando l’HT in ambienti virtualizzati sono frutto di parecchie ambiguità, però tra non avercelo e avercelo disabilitato, preferisco la seconda.

Il secondo errore riguarda il modello di CPU: ho acquistato la I5-3350P che, rispetto alla I5-3350 (senza P) è più economica di qualche euro… e ha pure una “P” in più: a prima vista un affare! In realtà ho scoperto a posteriori che le CPU marcate con la lettera “P” sono quelle la cui sezione grafica non ha passato i test di qualità, per cui viene disabilitata da Intel… ergo, la sezione grafica delle schede Mini-ITX non è funzionante perchè la CPU non è dotata della sezione grafica e si rende necessario l’acquisto di una scheda video esterna.

A me la cosa poco importa: una volta instaalato il Sistema Operativo, la sezione video non mi serve più perchè accederò ai server sempre e solo via ssh. Quindi provvedo a “saccheggiare” una scheda da un altro PC e installo Linux.

Visto che prevedo di utilizzare CLVM e non ho molto tempo da perdere, lascio da parte la mia fidata Debian e procedo ad installare CentOS 6.3. L’instaalazione procede senza problemi e, una volta configurati gli IP e riavviato il server qualche volta per sicurezza, spengo e rimuovo la scheda video… ed ecco che il server non riparte più! Per capire cosa succede provo a rimuovere l’Hard Disk e a far partire il server (senza scheda video) con il CD di avvio di Arch: riesco a risalire all’indirizzo IP rilasciato dal mio server DHCP, faccio partire “alla cieca” il demone SSH e vedo che da qui tutto funziona regolarmente: insomma, è CentOS che vuole una scheda video per partire! Dopo qualche ora di prove, sono riuscito a capire che il “colpevole” è grub, per cui ho modificato la configurazione per far si che si avvi utilizzando l’output su seriale.

default=0
timeout=5
#splashimage=(hd0,0)/grub/splash.xpm.gz
serial --unit=0 --speed=9600 --parity=no --stop=1
terminal --timeout=2 serial

Capita Anche Ai Migliori…

L’incubo di ogni programmatore si è verificato anche con il framework Rails: sono state riscontrate due vulnerabilità (CVE-2013-0155 e CVE-2013-0156) che espongono il noto framework al pericolo di SQL Injection.

L’SQL Injection è il noto tipo di attacco ai siti web attraverso il quale è possibile accedere al database SQL utilizzato da un sito web attraverso una modifica dei parametri della richiesta alla URL.

Per risolvere questo problema, è stato rilasciato un aggiornamento per tutte le release di Rails normalmente utilizzate. Le versioni di Rails aggiornate che risolvono i due bug sono: 3.2.11, 3.1.10, 3.0.19 e 2.3.15.

E’ altamente consigliato di aggiornare Rails all’ultima versione il più in fretta possibile.

I Pulsanti G+ E Facebook Like vs. La Validazione W3C

Nella realizzazione di siti web è importante rispettare gli standard HTML dettati dal W3C: questo sito, ad esempio, è stato realizzato seguendo gli standard dell’HTML5 e rispetta fedelmente le regole Rispettare gli standard del W3C, permette di avere un sito web che è sfruttabile in tutte le situazioni: ad esempio lo rende usufruibile ai browser per non vedenti, può essere visualizzato su browser diversi o su piattaforme diverse (PC, PDA, SmartPhone…). Lato SEO, è provato che una pagina web che rispetta gli standard riesce ad ottenere un ranking migliore rispetto ad una pagina che non li rispetta: sia ben chiaro, gli spider dei motori di ricerca non eseguono alcun controllo, ma il rispetto degli standard permette allo spider di “capire meglio” il contenuto della pagina. Ad esempio una immagine senza l’attributo “alt”, oltre a non rispettare gli standard, risulta incomprensibile ad un motore di ricerca.

Nella fase di controllo del sito, mi sono imbattuto in un problema di non immediata soluzione: per rendere il sito “social”, ciascun articolo è corredato dai pulsanti per segnalarlo ai social network più comuni: Twitter, Facebook, Linkedin e Google+. I pulsanti di Facebook e Google+, però, utilizzano una sintassi non compatibile con lo standard W3C. Ad esempio, il codice per Google+ “standard” è:

<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<g:plusone size="medium" href="http://www.azns.it"></g:plusone>

Mentre quello per il pulsante “Like” di Facebook è:

<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script>
<fb:like href="" layout="button_count" send="true" show_faces="false" width="450" font=""></fb:like>

Il problema è nei tag @g:pluszone@ e @fb:like@ che non sono riconosciuti dallo standard W3C, ma sono necessari per far apparire i pulsanti: come fare per superare la validazione?

Il trucco è abbastanza semplice: ultilizzo Javascript per chiedere al browser di inserire il codice di Google+ e Facebook, senza inserirlo direttamente nella pagina. Questo comporta un leggero rallentamento in quanto il browser deve eseguire l’istruzione, ma la pagina supera senza problemi il controllo del validatore di W3C. Questo il nuovo codice:

<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script>
<script type="text/javascript">
  document.write('<g:plusone size="medium" href="http://www.azns.it"></g:plusone>');
  document.write('<fb:like href="" layout="button_count" send="true" show_faces="false" width="450" font=""></fb:like>');
</script>

Geolocalizzazione Dei Contenuti in Ruby on Rails

Nella realizzazione di questo sito, ci siamo prefissati l’obiettivo di realizzare un blog bilingue, onde poterci affacciare anche all’utenza extra-italiana. Rails ha integrata una interfaccia per la localizzazione dei contenuti in grado di gestire le traduzioni attraverso dei file in formato yml; nel nostro caso, per rendere ancora più semplice la gestione delle traduzioni dei contenuti semistatici, abbiamo deciso di utilizzare l’ottimo localeapp. Oltre alla traduzione dei contenuti semistatici, gestiamo anche la traduzione dei contenuti dinamici (gli articoli del blog) utilizzando due diversi campi nel database. Attraverso questa infrastruttura, un visitatore può decidere se vedere il sito localizzato in italiano oppure in inglese semplicemente accedendo all’indirizzo corretto oppure scegliendolo dal menu popup in alto a sinistra (il simbolo della bandiera). Tutto ciò premesso, quale lingua vede il visitatore che accede all’indirizzo standard www.azns.it? Inizialmente abbiamo optato per una impostazione statica del “default locale” in italiano, dopodichè abbiamo deciso di intraprendere una strada diversa: proporre i contenuti del sito localizzati in italiano, solo per i visitatori provenienti dalla rete italiana. Ecco come abbiamo fatto:

Installazione delle estensioni necessarie

Per gestire la geolocalizzazione, abbiamo usato la gemma GeoIP Abbiamo installato la gemma aggiungendo la seguente riga al file gemfile

gem 'geoip'

Quindi abbiamo scaricato i database degli indirizzi IP da maxmind e lo abbiamo scompattato all’interno della directory /public

Codice per la geolocalizzazione

Tutto il codice necessario per la localizzazione si trova all’interno del file application-controller.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale

  def set_locale
    I18n.locale = extract_locale_from_subdomain || geolocalization #I18n.default_locale
  end

  # Get locale code from request subdomain (like http://it.application.local:3000)
  # You have to put something like:
  #   127.0.0.1 gr.application.local
  # in your /etc/hosts file to try this out locally
  def extract_locale_from_subdomain
    parsed_locale = request.subdomains.first
    unless parsed_locale.nil?
      I18n.available_locales.include?(parsed_locale.to_sym) ? parsed_locale : nil
    else
      nil
    end
  end

  def geolocalization
    c = GeoIP.new('public/GeoIP.dat').country(request.remote_ip)
    if c.country_code3=='ITA'
      'it'
    else
      'en'
    end
  end
end

Commentiamo insieme il codice qui sopra Ad ogni visualizzazione, viene lanciata la funzione set_locale.

Questa funzione setta la variabile di sistema I18n.locale che è quella che viene utilizzata per capire qual è la lingua di visualizzazione del sito: lo fa lanciando la funzione extract_locale_from_subdomain che ritorna “it” oppure “en” se l’utente ha scelto una particolare visualizzazione, oppure nil se l’utente ha scelto una lingua non supportata oppure se sta accendendo alla URL standard “www” (oppure al dominio di secondo livello).

Nel caso in cui questa seconda funzione restituisca nil, normalmente si usa ||I18n.default_locale per settare il locale al valore standard dichiarato nel file di configurazione dell’applicazione Rails; noi invece lanciamo una terza funzione, geolocalization.

Questa funzione estrae tutti i dati relativi allo stato di appartenenza dell’IP del visitatore con c = GeoIP.new('public/GeoIP.dat').country(request.remote_ip) e restituisce “it” se si trova in Italia, “en” se si trova all’estero.

La funzione, al momento, è compatibile solo con indirizzi IPv4, in quanto il database pubblico di IPv6 è attualmente incompatibile con la gemma geoip. Pertanto, se state navigando attraverso un indirizzo IPv6, vedrete questo sito in inglese.

L’architettura Di Instagram

Ecco il primo vero articolo del nuovo blog, online in maniera definitiva da oggi pomeriggio!

In realtà sono stato sollecitato da un amico a valutare un articolo interessante da lui scovato riguardante la descrizione dell’infrastruttura utilizzata da instagram. Dopo averlo letto con attenzione, gli ho riposto via email commentandolo punto per punto, alchè mi ha proposto di pubblicare i miei commenti sul mio blog.Lo faccio volentieri, anonimizzando le parti sensibili che riguardano il progetto che sta realizzando.

Lessons learned:
  1. Keep it very simple
  2. Don’t re-invent the wheel
  3. Go with proven and solid technologies when you can.

Nessun commento, corretto.

3 Engineers.

Nel senso che non ne servono 3000 come per Facebook: ne bastano 3 per far girare tutto instagram… Io guardo le cose dal basso e la mia opinione è che 3 è una quantità corretta, 2 resta comunque un numero adeguato per molti progetti, 1 solo amministratore di sistema è troppo poco. In tutte le situazioni in cui lavoro cerco sempre di coinvolgere una persona interna all’azienda in modo che ci sia almeno “un mio backup” in caso di forza maggiore.

Amazon shop. They use many of Amazon’s services. With only 3 engineers so don’t have the time to look at self hosting.

Qui sono dubbioso, ma solo per motivi puramente economici. In USA la tecnologia cloud è molto competitiva perchè hanno costi per la banda Internet molto bassi mentre i costi per il consumo energetico sono identici a quelli Europei, quindi in proporzione molto elevati; in Europa non abbiamo la stessa qualità di banda e i costi per questo componente sono più elevati, quindi la proporzione tra banda e costo dell’energia elettrica è molto inferiore. Questo porta ad avere una maggiore economicità per le offerte cloud americane rispetto alle corrispondenti offerte di housing; al contrario, in Europa, le offerte di housing sono più allettanti rispetto ad un cloud anche se la qualità di banda non è paragonabile, per cui questa è una regola certamente valida per le startup che hanno base/utenze in USA, mentre per noi deve essere valutata attentamente. Resta il fatto che tutte le ex-startup americane, Twitter e Facebook per citare un paio di nomi, una volta giunte ad una dimensione importante, hanno deciso di abbandonare Amazon e migrare verso ambienti self-hosting, segno che l’economicità del cloud si ha solo sotto una soglia di utilizzo ben determinata.

100+ EC2 instances total for various purposes.

Giusto: meglio tante piccoli istanze che due grossi serveroni con tutto dentro. La separazione delle istanze è il metodo migliore per separare gli ambienti ed essere sicuri che tutti convivano felicemente (diciamolo anche agli Israeliani e ai Palestinesi…)

Ubuntu Linux 11.04 (“Natty Narwhal”). Solid, other Ubuntu versions froze on them.

Nessuna guerra di religione sulle distribuzioni: ciascuna ha le sue caratteristiche e bisogna conoscerle per scegliere quella più adatta: - le RedHat based (tra cui CentOS e Fedora), sono “vecchie per scelta”: si sceglie una versione master (ad es. CentOS 6 in questo momento) e si saprà che in tutte le release successive (6.1, 6.2, 6.3…) si avrà sempre la stessa versione di ogni pacchetto (ad es. PHP 5.3.3) e saranno applicate solo delle patch create da RedHat per correggere eventuali errori. Quindi si ha una grande solidità in fase di gestione del sistema (aggiornamenti ecc.), ma se si vuole “qualcosa di più” si è con le mani legate. Anche un aggiornamento di master version (passare dalla CentOS 5 alla 6) è praticamente impossibile. - le Debian based (tra cui la citata Ubuntu) sono solide, hanno un gestore dei pacchetti maglifico (aptitude), ma bisogna prestare moltissima attenzione in fase di aggiornamento perchè sono legate solo alla versione del pacchetto e gli aggiornamenti di sistema seguono quelli del pacchetto senza un sistema di patch interno. Ad esempio su Debian 6 ora si ha PHP 5.3.4, ma con il passare del tempo sarà aggiornato alla versione 5.3.5 poi 5.3.6 e così via. Non si passerà mai alla versione 5.4 a meno di un cambio di versione di Debian (dalla 6 alla futura 7) cosa che, al contrario delle RedHat based, è possibile fare. Normalmente, per esperienza, le Debian based hanno anche meno overhead rispetto alle RedHat based. Personalmente, sui miei server, uso Debian wheezing che è la versione “testing” di Debian su cui si basa Ubuntu: Debian è magari un po’ più ruvida rispetto ad Ubuntu ma qui è solo una questione di gusti personali: i pacchetti sono identici. - le rolling release (Gentoo, Arch, Debian sid) sono distribuzioni senza versione perchè seguono costantemente gli aggiornamenti di un pacchetto. Quindi è possibile che un aggiornamento di sistema porti PHP dalla versione 5.3 alla 5.4 ma anche alla 6.0! Bello per chi vuole avere sempre l’ultima versione ma poco adatte per i server: personalmente sul mio PC uso Arch Linux nella versione testing, ben conscio che se dopo un aggiornamento non mi parte più il PC me la sono cercata (ma non è mai successo).

Amazon’s Elastic Load Balancer routes requests and 3 nginx instances sit behind the ELB.

Ritengo utile provare nginx al posto di apache come web server per i contenuti statici: io mi trovo benissimo! Nel caso di una realtà che non utilizza i servizi Amazon, non si potrà avere ELB di fronte alle istanze di Nginx, anche perchè nella maggior parte dei casi dubito fortemente che saranno necessarie più istanze di nginx; in qualsiasi caso nulla vieterà in futuro di usare una istanza dedicata di Nginx o di HAproxy per avere le stesse funzionalità di ELB (ELB è basato su HAproxy) di fronte ad X istanze di Nginx.

SSL terminates at the ELB, which lessens the CPU load on nginx.

Giusto: le istanze di ELB sono create su server con schede hardware dedicate alla gestione del criptaggio SSL, quindi delegare ad ELB la gestione del protocollo HTTPs scarica notevolmente i server che stanno alla base e permette di ottenere prestazioni più elevate.

Amazon’s Route53 for the DNS.

Non è possibile migrare indirizzi IP tra diverse zone di Amazon, per cui è come se fossero fornitori separati (ma se Amazon non paga la bolletta della corrente, va giù tutto e fine del film) ed è necessario un sistema in grado di gestire l’alta affidabilità tramite DNS.

25+ Django application servers on High-CPU Extra-Large machines.

Loro usano Phyton con Framework Django, in molti casi italiani si usa PHP. PHP, ad onor del vero, è un linguaggio di scripting molto semplice però non ha prestazioni elevatissime; personalmente Python mi fa venire l’orticaria, ma è una questione di gusti perchè in realtà è un linguaggio molto diffuso: ad esempio tutti gli script di RedHat sono realizzati in Python. Personalmente qualche anno fa mi sono avvicinato al mondo Ruby che è davvero affascinate: prestazioni paragonabili a Python, ma un linguaggio estremamente orientato agli oggetti (ad esempio un semplice ciclo “for i=1 to 20” si traduce in “(1..20).each do |i|” dove (1..20) è un oggetto ed each è un metodo dell’oggetto!) e un framework (Rails) che impone la metodologia MVC (Model View Controller) in modo da avere un codice ordinato e mantenibile facilmente in un team di persone. Sinceramente, se ora dovessi decidere quale linguaggio studiare per sostituire PHP, mi metterei a lavorare su Scala con il framework Lift: è un linguaggio derivato da Java, quindi il codice viene compilato ed eseguito direttamente e non compilato “in diretta” dal WSGI server: tutto ciò a beneficio delle prestazioni. Inoltre, cosa che mi attira, oltre alla programmazione procedurale e a quella ad oggetti, supporta la programmazione funzionale che permette di sfruttare in maniera pesante il multithreading delle CPU più moderne parallelizzando i processi.

Traffic is CPU-bound rather than memory-bound, so High-CPU Extra-Large machines are a good balance of memory and CPU.

Questa è una caratteristica del progetto Instagram: i filtri per le foto fanno la maggior parte del lavoro e stressano più la CPU che la RAM. Resta inteso che ogni processo ha le sue caratteristiche e quindi questi aspetti devono essere valutati caso per caso.

Gunicorn as their WSGI server. Apache harder to configure and more CPU intensive.

Come per tutti i web server, Apache server può servire nativamente solo i contenuti statici, però Apache ha la caratteristica “unica” di poter usare un suo sistema di moduli interni per lanciare gli script esterni (ad es. mod_php, mod_python e mod_ruby per altri linguaggi); in alternativa può lavorare come tutti gli gli altri web server (ad es. il già citato Nginx) reindirizzando ad un socket esterno ciò che non riesce a servire direttamente. Qui entra in gioco il server WSGI (che è gunicorn per Instagram), cioè quel pezzo di software che fa da “tramite” tra il web server ed il codice Python. Nel caso di ruby, il server WSGI più veloce è Unicorn, mentre per PHP possiamo decidere se usare ilo “vecchio” FastCGI oppure SuPHP oppure, infine, PHP-FPM che è un componente interno di PHP (dalla versione 5.3 in poi) e quindi è quello qualitativamente migliore e più efficiente.

Fabric is used to execute commands in parallel on all machines. A deploy takes only seconds.

Fabric è un sistema per eseguire processi in background per Python usando una connessione SSH; ha la possibilità di lanciare lo stesso comando in contemporanea su più server permettendo il parallel processing. Per Ruby esistono soluzioni analoghe, ma mi piace citare EventMachine in cui non si usa SSH per inviare un comando ad un server remoto, ma si ragiona ad “eventi”. Per PHP sinceramente non è necessario un modulo come fabric: si può arrivare allo stesso risultato con il comado exec “ssh server -c comando”, però si può usare RabbitMQ per avere un sistema di code e comunicazione tra server analogo a quello di EventMachine.

PostgreSQL (users, photo metadata, tags, etc) runs on 12 Quadruple Extra-Large memory instances.

Ok loro usano PostgreSQL per gestire i dati, non MySQL. Loro usano 12 server in replica: le basi dati relazionali si dimostrano sempre uno dei componenti più complessi e pesanti di un sistema.

Twelve PostgreSQL replicas run in a different availability zone.

Anche con MySQL è possibile portare repliche al di fuori del datacenter. Certo che il numero di 12 coincide in entrambi i punti precedenti, quindi immagino che stiamo parlando degli stessi server e quindi che Instagram abbia un totale di 12 server ciascuno istanziato in una istanza 4xExtra-Large sparsi di differenti availability zone.

PostgreSQL instances run in a master-replica setup using Streaming Replication. EBS is used for snapshotting, to take frequent backups.

Sia PostgreSQL sia MySQL possono avere repliche in modalità master-slave, però in entrambi i casi non sono autonomi a gestire eventuali guasti. Ci vuole un software esterno che controlli la funzionalità dei server, che escluda eventuali nodi morti o fuori sincronia e che promuova a master un nodo slave in caso di morte del master. Nel caso di Instagram, hanno usato repmgr per gestire questa cosa, nel caso di MySQL si può usare mysql-mmm.

EBS is deployed in a software RAID configuration. Uses mdadm to get decent IO.

Immagino, poveretti… EBS non è proprio un mostro di velocità I/O per cui usano due dischi in mirror software su ciascuna VM per parallelizzare l’output locale dei dati.

All of their working set is stored memory. EBS doesn’t support enough disk seeks per second.

Ecco la riprova: cache di tutto il database in RAM usando il sistema di cache e buffering interno a Linux perchè EBS non raggiunge velocità di I/O adeguate.

Vmtouch (portable file system cache diagnostics) is used to manage what data is in memory, especially when failing over from one machine to another, where there is no active memory profile already.

Vmtouch è un tool per gestire la cache di linux usata al punto precedente.

XFS as the file system. Used to get consistent snapshots by freezing and unfreezing the RAID arrays when snapshotting.

Aia, qui non mi trovo d’accordo. XFS è il Filesystem più veloce che abbia mai provato, ma ho sperimentato anche blocchi, perdite di dati, incoerenze… No: se parto dal presupposto che uso la cache per tutto, mi “paro il c…” con un filesystem più stabile anche se un po’ più lento come ext4.

Pgbouncer is used pool connections to PostgreSQL.

E per MySQL esiste mysql-proxy.

Several terabytes of photos are stored on Amazon S3.

Ok, le foto non stanno su filesystem locale ma su S3. Penso che alla fine, concettualmente, sia il classico esempio in cui è corretto non reinventare la ruota. Non gestire direttamente lo storage dei file ma tenerli “sul cloud” semplifica notevolmente la vita.

Amazon CloudFront as the CDN.

Certo, questa è l’interfaccia tra S3 e il web.

Redis powers their main feed, activity feed, sessions system, and other services.
Redis runs on several Quadruple Extra-Large Memory instances. Occasionally shard across instances.
Redis runs in a master-replica setup. Replicas constantly save to disk. EBS snapshots backup the DB dumps. Dumping on the DB on the master was too taxing.

Loro usano Redis che è uno storage “noSQL” per i contenuti che cambiano velocemente, in quanto la struttura dati di Postgres non riuscirebbe a stargli dietro. Questa è un’ulteriore testimonianza che tutto non può fare tutto e intestardirsi con una base dati SQL per contenuti che cambiano velocemente (ma anche il contrario come mettersi a creare un gestionale su una base dati Redis o MongoDB solo perchè va di moda) non è una scelta corretta.

Apache Solr powers the geo-search API. Like the simple JSON interface.

Solr è un motore di ricerca interno, probabilmente lo integrano con Apache Hadoop in modo che il secondo acquisisca i dati e crei gli indici che utilizza Solr: i due prodotti sono complementari e spesso sono usati in combinazione.

6 memcached instances for caching. Connect using pylibmc & libmemcached. Amazon Elastic Cache service isn’t any cheaper.

memcached è un sistema di cache condiviso tra più server; è compatibile con tutti i linguaggi di programmazione, anche PHP. Loro dicono che AEC non è economico, a mio avviso nemmeno EBS ed EC2 lo sono…

Gearman is used to: asynchronously share photos to Twitter, Facebook, etc; notifying real-time subscribers of a new photo posted; feed fan-out.

Francamente non capisco perchè usino gearman che è un doppione di fabric, a maggior ragione se hanno pure un sistema Hadoop alla base di Solr (ma questa è solo una mia congettura). Sicuramente hanno reputato che è preferibile isolare ciascuna funzionalità in diversi gruppi di istanze e quindi, a quel punto, tanto vale utilizzare il sistema che più si avvicina a risolvere ciascuna specifica funzione.

200 Python workers consume tasks off the Gearman task queue.

Beve, però questo Gearman!

Pyapns (Apple Push Notification Service) handles over a billion push notifications. Rock solid.

Per comunicare direttamente con i client Apple

Munin to graph metrics across the system and alert on problems. Write many custom plugins using Python-Munin to graph, signups per minute, photos posted per second, etc.

Munin è un tool di monitoraggio e generazione di grafici come cacti o nagios (che preferisco)

Pingdom for external monitoring of the service.

Giusto, lo uso anch’io: è inutile controllare che dentro alla rete funzioni tutto se poi cade il gateway che ti collega ad Internet :-)

PagerDuty for handling notifications and incidents.

Questo è un servizio di alert che si integra con Pingdom, ma anche con munin e nagios: se si rompe qualcosa, oltre all’email può arrivare un SMS o una telefonata. Francamente ce ne sono molti, ma questo sembra davvero facile da integrare per cui lo valuterò.

Sentry for Python error reporting.

Anche questo è un servizio che come Pingdom uso anch’io ($9 mese) e permette di gestire gli errori sul sito: quando ad un utente arriva un errore di qualsiasi tipo, questo sistema raccoglie tutti i dati per cui il programmatore ha una chiara idea di eventuali bug.