Inserisci Infobox

Puppet: Centralizzare e automatizzare le configurazioni dei sistemi

Puppet è un potente strumento di system automation che permette la gestione centralizzata di una infrastruttura di sistemi Unix.

Introduzione a Puppet
Autore: al - Ultimo Aggiornamento: 2010-06-24 09:51:32 - Data di creazione: 2010-06-24 09:31:27
Tipo Infobox: DESCRIPTION - Skill: 4- ADVANCED

Puppet è un software opensource, scritto in Ruby, che permette la gestione automatizzata e centralizzata di un'infrastruttura di sistemi Linux e Unix, essendo disponibile per tutte le principali distribuzioni Linux, le diverse varianti di BSD oltre che Solaris e AIX.

Con Puppet è possibile gestire praticamente ogni risorsa di un sistema: programmi da insallare, servizi da avviare, file di configurazione con contenuti diversi a seconda di diverse logiche, utenti, cron jobs, mount point, esecuzione di comandi specifici ecc.
Praticamente permette di automatizzare ogni attività sistemistica cambiando di fatto il modo con sui si opera su sun server.

Puppet è un sistema client-server, il client viene lanciato (come comando singolo o servizio) sul sistema da configurare e si connette al server (il Puppet Master) sulla porta 8140 TCP da cui recupera il profilo di configurazioni associato al suo hostname.
Sul server sono configurate in file chiamai manifest, con estensione .pp tutte le risorse che sono associate agli host gestiti.
Il traffico di rete è criptato, previo scambio di certificati x509 fra client e server che ne garantisce l'autenticità e integrezza.

I pacchetti di Puppet sono disponibili nelle principali distribuzioni Linux nei repository principali (Ubuntu , Debian) o in repository extra come EPEL per RedHat Enterprise Linux.
Se si deve installare il client, basta usare il pacchetto puppet ed eventualmente avviare l'omonimo servizio, sul server va installato anche il pacchetto puppet-server e avviato il servizio pupppetmaster.
Per entrambi i file di configurazione è /etc/puppet/puppet.conf, dove sono presenti diverse sezioni relative al comportamento di client e server.
I log passano per syslog (in /var/log/messages o /var/log/syslog), mentre vari file (certificati, backup, file di stato, estensioni) vengono depositati in /var/lib/puppet.

La logica di Puppet è di definire lo stato di un sistema e fare in modo che questo sia tale ogni volta che il client Puppet viene eseguito.
La prima volta che lo si esegue, quindi, vengono installati pacchetti, avviati servizi, modificati file di configurazione secondo quanto definito sul PuppetMaster e le volte successive, in teoria, se non sono intervenute modifiche manuali sul sitema, o cambiamenti delle configurazioni sul master, non dovrebbe cambiare nulla.
Questo è un concetto importante per il sistemista e  un vero e proprio cambio di paradigma sul suo modo di operare: in un sistema gestito con Puppet non si devono modificare a mano i file che Puppet gestisce, perchè questi vengono rimodificati la prima volta che questo viene eseguito.
E, visto che nelle condizioni ideali, Puppet gestisce tutte le risorse di un sistema (non è obbligatorio che sia così, ma è comunque consigliabile), di fatto, salvo in casi di emergenza, un sistemista non dovrà mai intervenire a mano sui suoi server.

Se da un lato tutto questo può risultare laborioso e in qualche modo "innaturale" nella gestione dall'altro comporta una serie di vantaggi clamorosi:
- Si può configurare il profilo di un server ed applicarlo a decine o centinaia di host, tutti uguali, tutti allineati, tutti configurati con la stessa logica.
- La procedura di setup e configurazione di un sistema è riproducibile: non è più necessaria quella arcana alchimia manuale con cui a volte ci si ritrova a gestire dei sistemi che poi non si sanno più reinstallare.
- E' facile e quasi intrinseco prevedere per ogni host il suo corrispettivo di sviluppo, collaudo e produzione, non avendo limiti nel numero di ambienti previsti e avendo la certezza di avere i sistemi fra di loro allineati.
- I manifest di puppet sono generalmente gestiti con un sistema di versioning (git, subversion, cvs vanno tutti bene), questo comporta automaticamente una gestione formale, reversibile, documentata e tracciata delle modifiche fatte sui sistemi.

Il risultato è che, già in infrastrutture di qualche decine di host, Puppet diventa uno strumento unico e insostituibile per una gestione rapida ed efficace del parco macchine, lo sforzo inizlae di definizione delle sue configurazioni viene ampiamente ripagato nel tempo con tempi di gestione e setup dei sistemi enormemente ridotti.
Insomma, con Puppet ci si può dedicare al miglioramento e l'affinamento della propria infrastruttura risparmiando il tempo speso in attività ordinarie ripetitive e noiose.

Installazione di Puppet 0.25
Autore: al - Ultimo Aggiornamento: 2010-06-24 11:09:00 - Data di creazione: 2010-06-24 11:06:51
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

La versione 0.25 di Puppet rappresenta un significativo passo evolutivo nella storia del programma e, al momento, è la versione stabile più recente ed è quella raccomandabile.
Vediamo come installarla su diverse distribuzioni.

REDHAT 5 / CENTOS 5
Puppet viene fornito nel repository EPEL, che può essere installato con:
rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm

Quindi installare Puppet con:
yum install -y puppet

REDHAT 6
Analogamente sulla nuova versione di RedHat enterprise Linux (e distribuzioni derivate) si installa prima EPEL:
rpm -Uvh http://download.fedora.redhat.com/pub/epel/beta/6/i386/epel-release-6-1.noarch.rpm

e poi Puppet:
yum install -y puppet

UBUNTU 8.04 LTS
Su questa versione di Ubuntu è raccomandabile l'uso del backport repo di Stephane Graber:
echo "deb http://ppa.launchpad.net/stgraber/puppet/ubuntu hardy main" >> /etc/apt/sources.list.d/puppet.list
e dopo aver importato la relativa chiave::
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E7716B13

si può procedere con l'installazione:
apt-get update
apt-get install -y puppet


UBUNTU 10.04 LTS
Sulla nuova LTS di Ubuntu Puppet 0.25 è disponibile nei repository ufficiali, per cui basta:
apt-get update
apt-get install -y puppet


DEBIAN 5
Su Debian 5 (lenny) si deve utilizzare il backports repo:
echo "deb http://www.backports.org/debian lenny-backports main contrib non-free" >> /etc/apt/sources.list.d/backports.list
poi vanno installate le relative chiavi usare per firmare i pacchetti:
apt-get update
apt-get install -y debian-backports-keyring


e quindi si può procedere con l'installazione:
apt-get update
apt-get -t lenny-backports install -y puppet

DEBIAN 4
Su Debian 4 (etch) si possono PROVARE i lenny-backports repo:
echo "deb http://www.backports.org/debian lenny-backports main contrib non-free" >> /etc/apt/sources.list.d/backports.list
e poi, ancora:
apt-get update
apt-get install -y debian-backports-keyring
apt-get update
apt-get -t lenny-backports install -y puppet


SLES 11
Su Suse Enterprise Linux 11 Puppet 0.24 è fornito di default, ma per usare la versione 0.25 si deve usare un repository alternativo:
wget http://download.opensuse.org/repositories/system:/management/SLE_11/system:management.repo -O "/etc/zypp/repos.d/system:management.repo"

E' poi possibile installare Puppet con:
zypper install -y puppet

Facter
Autore: al - Ultimo Aggiornamento: 2010-06-24 10:21:51 - Data di creazione: 2010-06-24 10:21:24
Tipo Infobox: STDOUT - Skill: 4- ADVANCED

Facter è un programma, fornito con il pacchetto di Puppet che raccoglie diverse informazioni locali che vengono comunicate al PuppetMaster come coppie di variabili-valore e che possono essere utilizzate per la generazione delle risorse da applicare al sistema.
E' possibile creare dei fact custom che assegnano a nuove variabili l'output di comandi arbitrari.

[[email protected] ~]# facter
architecture => i386
domain => localdomain
facterversion => 1.5.7
fqdn => localhost.localdomain
hardwareisa => i686
hardwaremodel => i686
hostname => localhost
id => root
interfaces => eth0,sit0
ipaddress => 10.42.100.102
ipaddress_eth0 => 10.42.100.102
is_virtual => false
kernel => Linux
kernelmajversion => 2.6
kernelrelease => 2.6.18-164.el5
kernelversion => 2.6.18
lsbdistcodename => Final
lsbdistdescription => CentOS release 5.4 (Final)
lsbdistid => CentOS
lsbdistrelease => 5.4
lsbmajdistrelease => 5
lsbrelease => :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch
macaddress => 08:00:27:9B:FA:88
macaddress_eth0 => 08:00:27:9B:FA:88
manufacturer => innotek GmbH
memoryfree => 400.38 MB
memorysize => 503.27 MB
netmask => 255.255.255.0
netmask_eth0 => 255.255.255.0
network_eth0 => 10.42.100.0
operatingsystem => CentOS
operatingsystemrelease => 5.4
path => /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
physicalprocessorcount => 1
processor0 => Intel(R) Core(TM)2 Quad CPU    Q8200  @ 2.33GHz
processorcount => 1
productname => VirtualBox
ps => ps -ef
puppetversion => 0.25.4
rubysitedir => /usr/lib/ruby/site_ruby/1.8
rubyversion => 1.8.5
selinux => true
selinux_enforced => true
selinux_mode => targeted
selinux_policyversion => 21
serialnumber => 0
sshdsakey => AAAAB3NzaC1kc3MAAACBAIVRrNtnQ3E5WdWoqeym5auOIugVYgRgOLzgRlALGU8xF6sFGAhakybA0IHqqz4bgzluGOC81MCjW0R3an3F0Qeal5v7/WEwP8XZeEvpiuW3QhynR0BpA5mxNzlz3Aof8g/6GvBkQOvrDUpqekOmOI+or+bBWipO/RiIynBPAclDAAAAFQDfMoj8yzBrDiWQnX5TvCNumxi6ewAAAIB4xzUl8vWezDTeBnBX0hSoQFWptIlbhkMf4aRz/3LYLjsCpTX4oY3qYbRL7kmHZTAr1KKSUDONzYFNt+CEAiCprZ9RLcV07nGI+blFF6cjCXfZSZ4a2Hth70JJG6d1u49zjZXihqqPOkJZEUxrxinR+1stzRr2CvyjfIkf9dgDMQAAAIBzE/4wB7eKx+qd3is5zShe7mBmF9RmIv34uXiV+uHUdSxI6+QOh+y5ZytKSKSssAlSpF8VsyxGrNUrguZ7z9LOH/juCNrQgKIiQ4jNFIBmMXrrFB0Yvn8BNCyEt17Lc1YzI+JZz5H2H7wQD2vGXXxTWtWiqwkn8ibd3ygqYXc/zg==
sshrsakey => AAAAB3NzaC1yc2EAAAABIwAAAQEA3TCEVSRTEZYJLu2jxSGZqEBRknIUB8wyh/omAki32ptd84H3t39BSWuovYksUhy89uLQq6QUNRbfom5jWXupY+Dhocphgg7ObbQ877rRc1a2sDurz3zwHbAKs1JcmbQOpU647nCsRTB+/uFhvwwWSzBAuTe4amUjx2Hb0dxP5peqdrZPe805zahakli4h12Ll/NTbSxt+12U4r6o2u6DJ/iNlzIZnPvrqDKvcGnFM4t8Nhe8AoThyaAFgco7eMWVkpiYamcmseMrimqbEkoGP48EQhQuvm3B7TVPhei5JpgxyEiwu7+p7Zw8k1MsA7c+2ZM2LU7wYcu+SVbvoW5vEw==
swapfree => 1023.99 MB
swapsize => 1023.99 MB
timezone => CEST
uniqueid => 007f0100
uptime => 1 min
uptime_days => 0
uptime_hours => 0
uptime_seconds => 100
virtual => physical

Documentazione e risorse su Puppet
Autore: al - Ultimo Aggiornamento: 2010-06-24 11:51:04 - Data di creazione: 2010-03-29 19:22:34
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

Esistono diverse risorse con informazioni e documentazione su Puppet oltre a siti che forniscono moduli Puppet che possono essere riutilizzati.

La documentazione ufficiale di Puppet è accessibile su http://docs.puppetlabs.com/http://reductivelabs.com/trac/puppet ed esiste un Wiki pubblico all'indirizzo: .  
E' inoltre possibile vedere la documentazione in locale con il comando puppetdoc.  

Il più importante aggregatore di informazioni (news e blog posts) su Puppet è http://planetpuppet.org

La community di Puppet, molto attiva e competente, si ritrova nella mailing list Puppet-Users e in quella, più orientata allo sviluppo, Puppet-Developers oltre che nel canale irc #puppet su Freenet.

E' inoltre disponibile il libro "Pulling Strings with Puppet" di James  Turnbull, ISBN 978-1590599785.

Fonte preziosa di informazioni sono i moduli esistenti resi pubblici da rispettivi autori. Puppet Forge è il sito ufficiale che li raccoglie.

L'autore di questo articolo ha realizzato Example42.com sito con informazioni e moduli Puppet.

Principi di configurazione di Puppet
Autore: al - Ultimo Aggiornamento: 2011-03-21 18:06:38 - Data di creazione: 2011-03-21 17:53:15
Tipo Infobox: DESCRIPTION - Skill: 5- SENIOR

Quando il puppet client si collega al PuppetMaster, quest'ultimo verifica se l'hostname del client esiste fra i nodi che lui conosce e compila e restituisce un catalog con l'elenco delle risorse che sono gestite sul client e che il client stesso provvederà ad applicare.    

L'elenco dei nodi gestiti dal PuppetMaster può essere definita in manifest Puppet (file di testo, scritto nel linguaggio Puppet) o su un sistema esterno ("External node classifier" , ad esempio un database ldap) a cui il PuppetMaster può essere configurato per collegarsi. Quando si usano frontend web come Puppet Dashboard o The Foreman questi POSSONO essere usati come external node classifier.    

Se invece si definiscono i nodi in un manifest Puppet, questi avranno una sintassi tipo:    
    
   node 'fileserver.example42.com' {    
       # Risorse Puppet, dichiarazione di variabili o inclusione di classi    
   }
    

In entrambi i casi per un nodo si possono definire delle variabili custom e includere classi o definire direttemente risorse ("resource types", come package, file, service, user ecc).    

Normalmente nella definizione di un nodo si includono direttamente delle classi, che tipicamente sono di due tipi:    

- Classi legate ad un modulo, e quindi ad una applicazione specifica, in cui sono definite le risorse da gestire relative a quella applicazione (es: include apache)    

- Classi "di raggruppamento" che a loro volta includono altre classi legate a specifiche applicazioni. Queste ultime, ad esempio possono essere classi generali che hanno gli elementi comuni a tutti i nodi della propria infrastruttura e/o classi legate a ruoli specifici (ad esempio server web, mail server ecc.)    

Vediamo un esempio reale di un nodo che include due classi definite nei rispettivi moduli (cacti e mysql) e una classe generale:    

   node 'cacti.example42.com' inherits basenode {    
       $cacti_mysqluser = "cactiuser"    
       $cacti_mysqlpassword = "example42"    
       $cacti_mysqlhost = "localhost"    
       $cacti_mysqldbname = "cacti"    
       $mysql_passwd = "example42"    
       include general    
       include cacti    
       include mysql    
   }
    

Notare che la gestione delle variabili in Puppet e in particolare il modo con cui vengono valorizzate non segue le stess logiche di un linguaggio procedurale e può creare confusione e problemi di "varible scoping". Una regola di massima è quella di definire PRIMA le variabili e poi includere le classi che le usano. Se si definisce una struttura basata sulla nodes inheritance come nell'esempio di sopra (un nodo reale che eredita un basenode) è bene definire ed eventualmente ridefinire le variabili a difersi livello dell'albero di ereditarietà, ma includere le classi solo alla fine, nella definizione del nodo fisico.    

In riferimento all'esempio di cui sopra, la classe generale potrà essere qualcosa tipo:    

   class general {    
       include puppet    
       include hosts    
       include users    
       include rsyslog    
       include ntp    
       include munin    
       include nrpe    
       [...]    
   }  
  

Una classe che invece contiene effettivamente risorse gestite da Puppet può essere qualcosa di simile:    

   class mysql {    
       package { "mysql":    
           name   => $operatingsystem ? {    
               ubuntu  => "mysql-client",    
               debian  => "mysql-client",    
               default => "mysql",    
               },    
           ensure => present,    
       }    
       package { "mysql-server":    
           name   => "mysql-server",    
           ensure => present,    
       }    
       service { "mysql":    
           name => $operatingsystem ? {    
               redhat  => "mysqld",    
               centos  => "mysqld",    
               default => "mysql",    
               },    
           ensure => running,    
           enable => true,    
           require => Package["mysql-server"],    
           subscribe => File["my.cnf"],    
       }    
       file { "my.cnf":    
           mode => 644, owner => root, group => root,    
           require => Package["mysql-server"],    
           ensure => present,    
           path => $operatingsystem ?{    
               default => "/etc/my.cnf",    
           },    
       }    
   }    
  
Questo esempio è una classe chiamata mysql che gestisce 4 risorse:    

- Il pacchetto "mysql" che ha nome diverso a seconda del sistema operativo e per il quale ci si assicura che sia "presente".    

- Il pacchetto "mysql-server", per il quale si definisce un nome unico.    

- Il servizio "mysql", con nome diverso a seconda del sistema operativo, per il quale Puppet si assicura che sia "running", lo abilita al boot, si assicura che venga gestito DOPO che il pacchetto "mysql-server" sia installato, e si "abbona" al File "my.cnf", nel senso che viene riavviato ogni volta che questo file viene modificato.    

- Il File "my.cnf", per il quale si definiscono modo, owner, group, il fatto che richiede prima l'installazione del pacchetto "mysql-server", il fatto che esista e il suo path. notare che in questo caso non viene definito COME questo file deve essere, quale contenuto deve avere.    

Alcune considerazione generali sul codice Puppet sopra riportato:    

"mysql", "mysql-server", "mysql", "my.cnf" sono i nomi delle risorse, e sono arbitrari (potrebbero chiamarsi Pippo) ma rappresenta il modo con cui risorse vengono referenziare (es: Package["mysql"] , il nome effettivo che queste risorse hanno sul sistema gestito sono definiti con l'argomento name => (per servizi e pacchetti) o path => (nel caso dei file). Se questi argomenti non sono definiti allora di default assumono il nome della risorsa stessa.    

Notare che possono esistere due diverse risorse con lo stesso nome (es: Package["mysql"] e Service["mysql"]) ma che la stessa risorsa con lo stesso nome può essere definita una volta sola per lo stesso nodo (non si possono definire due Package["mysql"] con caratteristiche diverse nello stesso nodo).    

Abbiamo quindi parlato di classi, che possono includere altre classi o direttamente delle risorse. Abbiamo accennato alle risorse che Puppet gestisce, dette anche resource Types. Queste possono essere native (Package, Service, File, User, Group, Mount, Exec ecc.) o create direttamente dall'utente. Ogni risorsa ha un nome e degli argomenti è importante usare la giusta sintassi:    

       package { "mysql-server": # Il nome è meglio metterlo fra doppio apice con i punti alla fine, Può anche stare su una nuova riga    
           name   => "mysql-server", # Ogni argomento è seguito dalla => e deve avere alla fine una virgola    
           ensure => present, # Il valore può essere con o senza apici. In genere si mettono fra apici stringhe alfanumeriche custom    
       }
    

Notare che il valore fornito ad un parametro può essere una variabile:    

           name   => "$mysql::params::packagename",

che fa riferimento diretto alla variabile $packagename definita nella classe apache::params  o può avere valori diversi a seconda del valore di altre variabili:    

           name   => $operatingsystem ? {    
               ubuntu  => "mysql-client",  
               debian  => "mysql-client",     
               default => "mysql",  
               }, # Ricordarsi la virgola dopo la graffa di chiusura  
  
in questo caso il parametro name assume diversi valori a seconda del contenuto della variabile $operatingsystem e quindi, di fatto, si adatta al supporto per diversi OS.

Preparazione del PuppetMaster
Autore: al - Ultimo Aggiornamento: 2010-06-25 10:35:59 - Data di creazione: 2010-06-25 09:54:14
Tipo Infobox: DESCRIPTION - Skill: 4- ADVANCED

Per poter iniziare a configurare risorse sui client, è necessario procedere a configurare il PuppetMaster e, soprattutto, scrivere del codice Puppet.

A livello di configurazione generale, non è necessario fare modifiche particolari a puppet.conf: le impostazioni di default sono sufficienti per operare, anche se in molti casi ne vengono modificati alcuni parametri.  
Il primo manifest (file in linguaggio Puppet) che di default viene letto dal Puppet Master è /etc/puppet/manifests/site.pp qui si possono iniziare ad importare altri manifest o definire direttamente i nodi da utilizzare e le rispettive risorse.  
Per importare specificatamente altri manifest la sintassi è:  
import /path/file.pp  
con il path che può anche essere relativo.  
I moduli (insieme di manifest e file strutturati secondo uno specifico standard) vengono caricati automaticamente se si trovano in una delle directory definite nel parametro di configurazione modulepath (di default /usr/share/puppet/modules e /etc/puppet/modules ).  

Esistono due diversi modi per definire i nodi (host) da gestire e le risorse che devono avere:
- definizione dei nodi in manifest;
- utilizzo di uno strumento esterno per definire nodi, vriabili e classi da includere.

Per il secondo caso sono necessarie alcune configurazioni extra e, soprattutto, va usato o sviluppato uno strumento dedicato. Nel mondo Puppet ne esistono due, particolarmente noti ed utilizzati, Puppet Dashboard (sviluppato sempre da PuppetLabs) e The Foreman.

Per il primo caso, che non richiede utleriori configurazioni o installazioni, si definiscono i nodi da gestire tramite il loro FQDN, direttamente in site.pp o più spesso in manifest ivi importati.
La sintassi per definire un nodo è la seguente:
node 'fileserver.example42.com' {
[...] Qui di possono includere classi, dichiarare variabili o inserire direttamente delle risorse Puppet
}


Il servizio si avvia con un prevedibile /etc/init.d/puppetmaster start

Privacy Policy