Provisioning di grandi monoliti con Vagrant

Il post di oggi vorrei usarlo per tenere traccia di alcune metodologie che sto usando per il provisioning di stack pesanti e che richiedono tempi lunghissimi.

Il software interessato rientra nella categoria del “monolite”. Lo stack monolitico è una sorta di amico enorme e per portarlo in giro bisogna prendere determinate precauzioni.

È tipo Zangief…

hqdefault

Per il raggiungimento del risultato finale, ovvero il bootstrap di ambienti completi, sto implementando un giro di provisioning fatto da cookbook Chef, script shell e Rubygem custom.

Alcuni ostacoli del progetto:

  1. Per un provisioning completo ci vogliono più di 3 ore
  2. La fase di installazione e configurazione è composta da centinaia di esecuzioni di script, chiamate a servizi REST e numerosi riavvii di servizi systemd. Tutto deve essere rigorosamente idempotente.
  3. Gli errori durante il provisioning sono da evitare assolutamente. Ripartire nel mezzo dell’installazione non è mai come partire da zero.

La scelta del provisioner e per cosa usarlo

Di base, a meno che non ci siano vincoli progettuali, siamo in grado di fare quasi tutto con i più importanti configuration management tool come Chef, Puppet e Ansible.

È importante capire cosa far fare al provisioner e cosa no. Alcune operazioni che sono specifiche per il mio ambiente di laboratorio le metto tranquillamente in blocchi shell script (che alla fine è anch’esso un provisioner di Vagrant)

 
 $script = <<-SCRIPT echo I am provisioning... date > /etc/vagrant_provisioned_at
 SCRIPT

Vagrant.configure("2") do |config|
 config.vm.provision "shell", inline: $script
 end

Per usare o meno un proxy può essere utile una semplice variabile d’ambiente.

if ENV['NO_CUSTOMER_PROXY']
 config.vm.provision 'shell',
 inline: '> /etc/profile.d/proxy.sh'
 config.vm.provision 'shell',
 inline: '> /etc/environment'
 else
 config.proxy.http = 'http://CUSTOMER.PROXY.LOCAL:8080'
 config.proxy.https = 'http://CUSTOMER.PROXY.LOCAL:8080'
 config.proxy.no_proxy = ''
 end

 

Roadmap delle box

Il punto è che non vogliamo fare e rifare il lunghissimo provisioning tutte le volte ma poter “debuggare” stati diversi della macchina.
Per esempio, nel caso esistano i seguenti possibili stati:

  1. macchina con prerequisiti installati, aggiornamenti OS e personalizzazioni.
  2. macchina con monolite installato.
  3. macchina con monolite configurato.
  4. macchina con applicazioni del monolite configurate.

Rifare tutto da zero può richiedere parecchio tempo per cui ho utilizzato il “package” di Vagrant…

vagrant package --base $id --output os_ok.box; vagrant box os_ok.box
vagrant package --base $id --output monolite_ok.box; vagrant box add monolite_ok.box
vagrant package --base $id --output monolite_configurato.box; vagrant box monolite_configurato.box
vagrant package --base $id --output monolite_con_applicazioni_configurate.box; vagrant box add monolite_con_applicazioni_configurate.box

All’occorrenza, nel Vagrantfile e nel bocco relativo alla vm, ho usato la box che mi serviva in determinato punto.

Archivi pesanti in /vagrant

Durante il provisioning ho avuto bisogno di scaricare da locazioni remote archivi anche di grandi dimensioni.

Questo durante le prove  non è performante per cui i puntamenti, dei ruoli Chef nel mio caso,  sono tutti verso src: “file:////vagrant/foo.tar.gz”. Naturalmente è opportuno dichiararli nel .gitignore.

Ciao

Advertisements

il mio ultimo libro…

Nel tempo libero ho iniziato a scrivere libri e uno di questi ho pensato di pubblicarlo…

Il protagonista di Skynet (così ho chiamato il libro) è un giovane hacker romano che si troverà a dover combattere un potere occulto che cerca di danneggiare Roma fin dai tempi della sua fondazione.

Si troverà faccia a faccia con le temibili sorelle della Toga Nigra, ovvero delle combattenti molto arrabbiate per il Ratto delle Sabine e che negli anni sono diventate le attuali suore.

Si, il racconto parla di suore hacker e combattimenti alla Matrix.

Ho optato per alcuni luoghi di internet dove condividere il libro

  1. su Github
  2. come ebook su Amazon
  3. come pdf

68190-skynet-il-perche-a-roma-non-funzionano-le-cose

Saluti!

DevopsTribe fase 1

Ho passato settimane a pensare quale nuovo nome dare al blog e alla fine ho scelto DevopsTribe.

Non è stata una scelta facile vista l’enorme quantità di spunti che mi proponevo da solo. Il nome è importante perchè ti serve nel momento in cui condividi a qualcuno il tuo blog.

Tipo…

Hey ti passo il mio blog, titolohackeroso.com (è rischioso avere la parola hacker nell’indirizzo… Fa troppo bimbo cibernetico indaco).

Hey ti passo il mio blog, comegestiresistemi.com (tipo wiki-how o qualcosa di aranzulliano… non ci piace).

Hey ti passo il mio blog, .com (serve un dominio di secondo livello).

Hey ti passo il mio blog, devops$qualcosa.it (questo mi piace. Faccio robe devops per cui ci sta).

Rimaneva quindi da definire il $qualcosa da attaccare a devops.

devops.it? (già preso..)
devopsattack.it (pare tipo ArtAttack, meglio di no)

head.jpg

devopsbofh.it (un nome, una contraddizione. Le operation agili contro la vecchia ma saggia scuola BOFH)

devopsparty.it (meglio un rave party che un party di smanettoni)

Alla fine ho scelto “tribe”.

Tribe come le mitiche Korg Electribe ES1 mkII e Korg Electribe EA1

…e tribe come la community che non può mancare intorno alle tematiche su cui lavoro.

Tribe anche come RomeDevopsTribe che è un meetup e prossimamente mi piacerebbe organizzare e vedere in attività!

Bella

Cos’è che fa di un Devops un Devops, signor Lebowski?

Vorrei parlare dei principi base del Devops che negli ultimi 5 anni ho potuto assimilare lungo il cammino.
Questo perchè dovevo preparare delle noiosissime slide. Mi serviva uno scopo, e un post sul blog ci sta tutto.

Inoltre, ho preso il dominio ziopinguino.it e sto pensando di migrare tutto il blog lì…

Quali sono i caratteri distintivi dell’area Devops?
Quali sono gli stereotipi e le considerazioni ricorrenti tipiche degli ambiti innovativi a cavallo tra buzzword e vera innovazione?

Cos’è che fa di un devops un devops, signor Lebowski?

Essere una BaaS? Buzzword as a service?

Lo era sicuramente all’inizio una buzzword, ma ora non più.
Lo è se si legge solo nei blog di Devops, se non si è potuto toccarne con mano i benefici e i risultati.

Nei contesti dove c’è stata una vera rivoluzione, la parola “Devops” descrive perfettamente figure professionali che svolgono attività di collegamento tra i gruppi di sviluppo e le operation. Queste attività si individuano nella forma di integrazioni di sistemi, sviluppo di piccoli tool e pubbliche relazioni (quando dai supporto…).

I Devops seguono tutta la catena di montaggio partendo dal codice fino al delivery e monitoring delle applicazioni.

Sono sistemisti che scrivono del buon codice, o programmatori che si muovono agili sulla shell.
Giocano con molte tecnologie e spesso trovano la parola chiave corretta su Google che gli risolve la giornata.

Stare attento a quando dici “alla vecchia maniera”?

Nell’IT non è previsto l’utilizzo di espressioni come “ai tempi miei” o “come si faceva un tempo”.

Un paio di scarpe fatto alla vecchia maniera è resistente e di qualità, ma un sistema fatto così, pur essendo stabile, verrebbe inevitabilmente visto come “anziano”.

Saggio in quanto anziano, ma con la barba bianca e lunga al posto dei baffetti hipster.
Non entro in merito sulla correttezza di tale giudizio, ma è innegabile dire che in molti contesti ciò accade.

Molte delle cose fatte un tempo funzionano egregiamente anche oggi e comunque le usiamo volentieri.

Dirò solo una cosa “Bash Rocks!”.

bash-logo-web

A volte però il cambiamento è fortemente consigliato.

Ad esempio, non è possibile sostituire un configuration management tool come Chef o Puppet con dello shell scripting. Concetti come idempotenza e auto-discovery richiedono comunque un effort nella loro realizzazione. E’ meglio quindi usare strumenti supportati da una community, piuttosto che scrivere componenti di cui poche persone mantengono la memoria storica.

Essere preparato su GIT?

Non può mancare una conoscenza approfondita di Git.
Servirà quando uno sviluppatore ti chiederà aiuto o quando prenderai in giro il tuo amico perchè lavora dove ancora distribuiscono il codice e le nuove release su aeroplanini di carta. Sull’ala destra c’è il messaggio di commit e su quella sinistra la versione. Se l’aeroplanino ritorna indietro per via di forti correnti contrarie hai fatto rollback.

Il pattern di “infrastructure as code” non può mancare e quindi serve “versionare”.

E’ importante sapere che lavoriamo in un ambiente deterministico e che possiamo pilotare piattaforme tramite codice.

Così “ciao ciao” documentazione, si legga il playbook di Ansible o il cookbook Chef (tutto questo in mondo immaginario…il “documentone” verrà sempre chiesto, però ultimamente sono sceso a compromessi per cui anche un bel markdown fatto bene può andare)

Ho imparato che tutto il lavoro svolto deve essere portabile. Un modulo Puppet o un cookbook Chef deve essere chiaro e leggibile. Sembra scontato ma non lo è.
Spesso automatismi e meccanismi agili all’interno delle nostre infrastrutture risiedono solo nella nostra conoscenza perchè le abbiamo sviluppate noi. Questo è poco Devops, perchè diventa comunque un silos. Un “agile silos”.

Scegliere i tool con senso critico?

Il landscape dei tool Devops è enorme.
E’ costellato di programmi che fanno a volte la stessa cosa e che competono a suon di stellette su github e loghi accattivanti.

Alcuni di essi sono veramente utili ed è divertente contribuire alle loro community. Altri vengono proposti “a cazzo di cane” in conversazioni di gruppo dove il tema parrebbe essere “spariamo a nomi a caso”.

Una specie di cyber flusso di coscienza << kubernetes! Prometheus!! Openshift!! Spark!! Mesos! Puppy Linux!! >>

Comunque… un Devops, come sceglie i tool da usare nell’opensource?

Evitare sicuramente di giudicare solo in base alla popolarità.

Se tale software viene utilizzato e contemporaneamente lo si reputa mediocre, si dovrebbe contribuire con quello che pensiamo possa portare un miglioramento.

L’opensource del resto è un qualcosa di tutti, potrebbe in un futuro prossimo diventare un bene di tutti. Forse il paragone è esagerato, ma migliorare il software contruibuendo è come pulire una strada per il bene della comunità, perchè hai necessità di percorrerla e se la percorri imprecando sembri un predicatore matto.

Condividere il knowledge, abbattere i silos e fare team?

Assolutamente si. Senza questi tre elementi probabilmente il mio lavoro sarebbe molto noioso. Sono punti fondamentali.

Mi viene in mente un modo di dire che ho coniato qualche minuto fa per cui non ne certifico la concretezza e neanche un senso logico: se detieni l’ownership di una procedura noiosa, non detieni l’ownership del tempo lavorativo mentre la fai.

Intendo che se ci è richiesto di intervenire solo perchè conosciamo una procedura che noi e solo pochi eletti siamo in grado di eseguire siamo distanti anni luce dalle metodologie Devops.

Non siamo owner di quel tempo che impieghiamo a concludere il task perchè qualcuno prima di noi ha deciso quanto sarebbe dovuto durare scrivendo passo passo un documento procedurale.

E’ compito di un Devops, a mio parere, arrivare al risultato scegliendo la soluzione più smart possibile.

Ecco tutto questo però dimenticatelo il venerdì pomeriggio… ben venga il noioso, il ripetivo e pure il “se funziona non lo toccare”.

E pure il “eh vecchio mio, mi ricordo quando mettevamo il notepad in cluster…”.

unnamed high-availabilityunnamed.png

Be pushy With Chef from Ruby application using “Foodpusher” gem.

Hi guys,

recently for some work tasks I needed to interact with Chef Push Jobs not from knife command line tool but through ruby code…

Screen Shot 2017-08-14 at 11.43.02

For this reason, I decided to write a Ruby gem and I hope it will be useful for the Chef community 🙂

You can find code and instructions here https://github.com/lucky-sideburn/foodpusher.

Below some code, just to have a look about how to use of this gem.

Let’s say you want push chef-client execution on client01.local and chef-server.

require 'chef/knife'
require 'chef/knife/foodpusher'

job = { 'command' => 'chef-client',
        'nodes' => ['client01.local', 'chef-server'],
        'quorum' => 1,
        'capture_output' => false,
        'env' => {} }

Chef::Config.chef_server_url = 'https://chef.devops.foobar.lan/organizations/chef'
Chef::Config.client_key = '/vagrant/chef-server.local/.chef/chef.pem'
Chef::Config.node_name = 'chef'
Chef::Config.ssl_verify_mode = :verify_none
pusher = FoodPusher.new(job)

# Start Job
myjob = pusher.start
puts "Job uri #{myjob}"
status = (pusher.status myjob)['status']

# Check Job Status
while status == 'running'
  status = (pusher.status myjob)['status']
  puts status
  sleep 1
end

# Check Node Status
(pusher.node_status job['nodes']).each do |result|
  puts result
end

Launch the script and that’s the output

Job uri {"uri"=>"https://chef.devops.foobar.lan/organizations/chef/pushy/jobs/336d0bf2dc771d3127dffead469381b5"}
running
running
running
running
running
complete
{"node_name"=>"client01.local", "status"=>"online", "availability"=>"available"}
{"node_name"=>"chef-server", "status"=>"online", "availability"=>"available"}

Thanks!

 

Test Kitchen – overview sul testing di infrastrutture

Ultimamente mi tocca, con molto piacere, rispolverare un pò di argomenti passati sulla parte di test di infrastrutture tramite Chef.

Al posto di scrivermi il solito spiegone in markdown direi che un post ci sta tutto 🙂

Iniziamo con scegliere il framework

5924439

e il DSL da utilizzare per i nostri test.

InSpecLogo

Userò InSpec. Riporto il link della documentazione dove sono elencati vari costrutti e metodi da utilizzare.

In .kitchen.yml, all’interno del cookbook, selezioniamo il verifier

verifier:
  name: inspec

Il file da editare è test/smoke/default/default_test.rb.

Di seguito un pò di test fatti per verificare il ruolo di base di alcuni server

  • Controllo di un nameserver in /etc/resolv.conf
describe file('/etc/resolv.conf') do
  its('content') { should match(/^nameserver\ 8.8.8.8$/) }
end
  • Controllo NTP
[
 /^server\ ntp1.inrim.it.*/,
 /^server\ ntp2.inrim.it.*/
].each do |ntp|
 describe file('/etc/ntp.conf') do
 its('content') { should match(ntp) }
 end
end
  • Selinux è disabilitato?
describe command('getenforce') do
 it { should exist }
 its('matcher') { should eq 'Permissive' }
end

Ora lanciamo ‘kitchen verify’ e verifichiamo il risultato dei test

File /etc/resolv.conf
 ✔ content should match /^nameserver\ 8.8.8.8$/
 File /etc/resolv.conf
 ✔ content should match /^nameserver\ 8.8.4.4$/
 File /etc/ntp.conf
 ✔ content should match /^server\ ntp1.inrim.it.*/
 File /etc/ntp.conf
 ✔ content should match /^server\ ntp2.inrim.it.*/

Test Summary: 4 successful, 0 failures, 0 skipped