Elaborato Maiello Alessandro N46001176
Transcript
Elaborato Maiello Alessandro N46001176
Scuola Politecnica e delle Scienze di Base Corso di Laurea in Ingegneria Informatica Elaborato finale in RETI DI CALCOLATORI Sistemi di gestione automatica della configurazione: Puppet Anno Accademico 2013/2014 Candidato: Alessandro Maiello matr. N46001176 Alla mia famiglia, che con tanti sacrifici mi ha permesso di arrivare fin qui. Indice Indice .................................................................................................................................................. III Introduzione ......................................................................................................................................... 4 Capitolo 1: DevOps .............................................................................................................................. 6 1.1 DevOps: principi e finalità .................................................................................................... 7 1.2 DevOps e il mobile ................................................................................................................ 9 Capitolo 2: Software Management tools ............................................................................................ 11 2.1 Modelli di funzionamento ................................................................................................... 11 2.2 Panoramica su Salt, Ansible e Chef .................................................................................... 13 2.2.1 Salt ............................................................................................................................... 13 2.2.2 Ansible ......................................................................................................................... 14 2.2.3 Chef .............................................................................................................................. 15 2.2.3.1 Componenti di chef ........................................................................................................ 16 Capitolo 3: Puppet .............................................................................................................................. 19 3.1 Puppet Management Tool ................................................................................................... 20 3.1.1 Modelli di funzionamento ............................................................................................ 20 3.2 Il linguaggio Puppet ............................................................................................................ 22 3.2.1 Risorse .......................................................................................................................... 22 3.2.2 Manifesti e classi .......................................................................................................... 23 3.2.3 Moduli .......................................................................................................................... 25 3.2.4 Variabili e parametri di classe ...................................................................................... 27 3.2.5 Facts e conditional statements...................................................................................... 28 3.2.6 Ordinamento delle risorse ............................................................................................ 31 3.3 Installazione e configurazione di Puppet open source ........................................................ 34 3.3.1 Creazione e configurazione del Puppet master ............................................................ 34 3.3.2 Creazione e configurazione del Puppet agent .............................................................. 37 3.3.3 Prima connessione e scambio certificati ...................................................................... 38 Conclusioni ........................................................................................................................................ 45 Bibliografia ........................................................................................................................................ 46 Introduzione Con l’introduzione e l’estensione di tecniche informatiche e telematiche si è avuta una vera e propria rivoluzione in parecchi settori, dall’economia alla politica, alla società in generale. Soprattutto nel settore economico, ma non solo, l’informatizzazione ha cambiato sia i ritmi produttivi che i consumi, automatizzando gran parte del lavoro e portando l’uomo ad occuparsi prevalentemente di funzioni di controllo. Sempre più aziende, enti o organizzazioni hanno bisogno di una propria infrastruttura IT, che a causa del gran numero di macchine da cui è costituita, non è molto semplice da gestire e configurare. Al fine di migliorare i tempi di produzione e di sviluppo dei prodotti e per semplificare la gestione dell’infrastruttura IT, molte compagnie hanno investito il loro denaro per lo sviluppo di alcuni software management tools, che vengono incontro alle esigenze degli amministratori di sistema: facilitano ed automatizzano la gestione delle configurazioni di software e servizi di un’infrastruttura informatica. Attraverso questi tools, indipendentemente dal numero di macchine che costituiscono la rete del sistema, è possibile definire una o più configurazioni che verranno poi applicate automaticamente a sottoinsiemi di nodi del sistema e gestite dagli stessi. Puppet è uno di questi strumenti software open-source ed è in grado di gestire sistemi e infrastrutture di rete durante il loro ciclo di vita in maniera del tutto automatica, dalla configurazione e provisioning fino al reporting, e di mantenere sempre aggiornata 4 un'enorme quantità di servizi da essi offerti, garantendo così costi sempre più bassi. Oltre a Puppet, vi sono altri tools sia open-source che in versione Enterprise, in grado di gestire infrastrutture IT molto complesse. Ognuno di essi è dotato di un proprio DSL (Domain-Specific Language), essenziale al fine di poter definire files di configurazione contenenti la descrizione dello stato finale desiderato per il sistema da gestire. Questo elaborato si propone, nel primo capitolo, di illustrare l’importanza del movimento DevOps ai fini dello sviluppo dei tools di gestione automatica delle configurazioni, per poi fornire, nel secondo capitolo, una panoramica degli stessi delineandone le caratteristiche principali. Il terzo capitolo, infine, focalizzerà l’attenzione sul modello Master/Agent del tool Puppet, sugli elementi fondamentali del suo DSL e sulla sua installazione e configurazione iniziali, mostrando anche qualche semplice esempio di funzionamento. 5 Capitolo 1: DevOps Con il termine DevOps, si intende quel movimento secondo il quale sviluppatori e addetti alle operations all’interno di un’organizzazione IT debbano collaborare e comunicare tra loro al fine di migliorare la produttività e la velocità di sviluppo e distribuzione del software, automatizzando i flussi di lavoro e misurando costantemente le prestazioni delle applicazioni. Tradizionalmente, Dev (Developers) e Ops (Operations Team) lavorano separatamente: gli sviluppatori si occupano di creare l’applicazione; gli addetti alle operations si occupano di tutto il resto, come l’ottimizzazione delle risorse e delle prestazioni, il controllo di qualità del software ecc. Questa divisione dei ruoli nello sviluppo del software poteva andare bene fintanto che i prodotti da rilasciare richiedevano settimane o mesi di lavoro, ma nell’attuale era degli app store, dove le applicazioni vengono rilasciate in pochi giorni, essa inizia ad essere una scelta poco sensata. Questo movimento viene reso popolare tramite una serie di DevOps Day, iniziati nel 2009 in Belgio, e poi svolti in India, USA, Brasile, Australia, Germania e Svezia, per discutere 6 sul divario operativo e lasciare che ingegneri del software potessero parlare dei modi migliori per raggiungere dimensioni e velocità ottimali nella distribuzione del codice. Il movimento DevOps riprende i principi delle metodologie Agili, le quali avevano abbandonato il modello a cascata a favore di un modello di sviluppo continuo per il software, e applica lo stesso concetto anche alle operations, implementando quindi rilasci e integrazione continui. In modo da facilitare ciò, DevOps incoraggia l’automazione dei processi di rilascio e configurazione e dei cambiamenti. DevOps ha trovato terreno fertile soprattutto grazie all’avvento del cloud computing, un insieme di servizi e tecnologie che permettono di memorizzare e elaborare dati utilizzando risorse hardware/software distribuite e virtualizzate in rete, favorendo così l’automazione e la continuità in termini di sviluppo e distribuzione del software. L’idea fondamentale di DevOps è di “descrivere un’infrastruttura come codice” per consentire il provisioning e la configurazione di ambienti DevOps, e per permettere l’utilizzo di tools di gestione della configurazione quali Chef, Puppet, Salt e Ansible, al fine di rendere le aziende sempre più competitive perché pronte a rispondere rapidamente alle richieste di mercato. 1.1 DevOps: principi e finalità L’utilizzo e l’adozione di DevOps consente di velocizzare i cambiamenti del software e, indipendentemente dal settore di interesse, permette di rilasciare più celermente servizi e software migliore, con costi e rischi minori. DevOps esalta la collaborazione tra i partecipanti allo sviluppo del software, quali sviluppatori, tester, business teams e addetti alle operations, al fine di ottenere un obiettivo comune: l’innovazione, sostenuta da rilasci continui e feedback costante. DevOps, quindi, non è l’obiettivo ma è il mezzo che consente di raggiungere gli obiettivi prefissati a patto di seguire determinati principi. DevOps aiuta ad ottenere alcuni punti fondamentali: Velocizzare i cicli di feedback. 7 Miglioramento dell’esperienza dell’utente finale. Aumentare la produttività. Ottimizzare i processi. Diminuire i difetti di produzione. Ridurre i tempi di rilascio del software. Al fine di raggiungere questi obiettivi è necessario seguire alcuni principi essenziali: Incoraggiare l’apprendimento collaborativo e la sperimentazione: la condivisione della conoscenza consente ai team di identificare e riutilizzare i pattern ben riusciti, mentre la sperimentazione permette di tentare nuovi approcci, imparare dai fallimenti e innovare il software durante il suo ciclo di vita. Supporto alla distribuzione mediante processi affidabili e ripetibili: qui l’automazione gioca un ruolo essenziale. Definire i test in maniera automatica consente di velocizzare il rilascio del software, di ridurre il numero di errori dovuti alla definizione manuale dei testi e, quindi, di diminuire la possibilità di fallimenti al momento del rilascio. Monitoring e convalida della qualità operativa: in base a questo principio è necessario monitorare le caratteristiche, funzionali e non, dell’applicazione attraverso l’utilizzo e la valutazione di determinate metriche sulla qualità. Questi parametri devono essere acquisiti in un formato tale da poter essere compresi e utilizzati da tutti gli stakeholder dell’azienda. Amplificazione dei cicli di feedback: consentire a tutti gli addetti allo sviluppo del software di imparare dai feedback è essenziale al fine di effettuare i cambiamenti il più presto possibile e di ridurre di conseguenza i costi. Per fare ciò le organizzazioni devono creare canali di comunicazione efficienti che consentano a tutti di accedere ai dati raccolti. 8 1.2 DevOps e il mobile Nel settore mobile, vi è una grande varietà di piattaforme di rilascio. La situazione è in qualche modo simile a quella presente molti anni fa nel settore desktop quando ancora esistevano parecchi standard differenti tra loro. Ciò che la differenzia da essa è che nel settore mobile, oltre ai diversi sistemi operativi, bisogna tenere in considerazione anche le diverse caratteristiche dei terminali di destinazione, quali la risoluzione, il processore, la potenza grafica, le reti supportate, ognuna delle quali aggiunge un ulteriore livello di complessità allo sviluppo dell’applicazione. Quest’ultimo è reso ancora più difficile dalla necessità di accorciare i tempi di rilascio sul mercato, in quanto dei ritardi eccessivi potrebbero incidere sull’effettiva capacità dell’applicazione di venire incontro alle esigenze degli utenti. DevOps rappresenta una delle possibili soluzioni a questi problemi. Esso consente di rilasciare un’applicazione funzionante completa di tutte le caratteristiche più recenti, in qualsiasi momento durante la produzione della stessa. DevOps, infatti, rigetta il modello a cascata a favore di un approccio agile, che consenta di sviluppare l’applicazione in modo incrementale, tenendo traccia di tutti i cambiamenti della stessa e della effettiva possibilità di implementare i cambiamenti stessi. Per garantire il successo del rilascio è necessario quindi identificare, tracciare, catturare e testare ogni cambiamento e ciò è possibile attraverso un approccio disciplinato che vede i team di sviluppo e delle operations lavorare assieme al fine di garantire rilasci del software frequenti, affidabili e di alta qualità. Attraverso DevOps è possibile: Catturare i cambiamenti Automatizzare il modo in cui essi avvengono Automatizzare il testing Mantenere i cambiamenti piccoli abbastanza da ridurre i rischi DevOps fornisce un approccio disciplinato e automatizzato allo sviluppo dell’applicazione, integrando piccoli miglioramenti funzionali, che potrebbero evolvere col tempo in funzioni ben più complesse e articolate. Per DevOps, infatti, sia i rilasci delle 9 applicazioni sia gli aggiornamenti sono fondamentali, in quanto il vero obiettivo non è la perfezione, ma il miglioramento continuo. 10 Capitolo 2: Software Management tools I software management tools sono strumenti che permettono la gestione automatica della configurazione di una grande quantità di nodi della rete in maniera prevedibile ed idempotente. Essi leggono le informazioni contenute nei file di configurazione ed espresse nel proprio DSL che descrivono lo stato finale desiderato per il sistema, e le applicano ai nodi interessati. Attraverso di esse, un amministratore di sistema è in grado quindi di replicare un configurazione su più nodi in maniera automatica o di ripristinarla celermente in caso vi fossero dei problemi. 2.1 Modelli di funzionamento I due modelli di funzionamento supportati dai software management tools sono: il Master/Agent e lo Standalone. Il modello Standalone è consigliato per infrastrutture piccole e poco complesse in quanto permette di aggirare l’overhead introdotto dal modello Master/Agent, che è invece consigliato per infrastrutture che richiedono un alto tasso di parallelizzazione delle operazioni di gestione e maggior centralizzazione. Nel modello Standalone (Fig.1) i cataloghi, contenenti le informazioni sullo stato desiderato del sistema, sono testati e inviati da una o più workstations locali ai vari nodi. 11 Figura 1: Modello Standalone Nel modello Master/Agent (Fig.2), invece, una macchina viene designata come server (Master) e si occuperà di stabilire connessioni in entrata o in uscita con i nodi della rete (Agent), che possono richiedere i cataloghi al Server, e di gestire separatamente le informazioni di configurazione per ognuno di essi. In questo modello, quindi, gli amministratori applicano cambiamenti al master, il quale poi li propagherà verso i nodi che li applicheranno localmente. I nodi riportano poi al master se i cambiamenti sono stati applicati con successo o meno. I nodi possono ricevere le informazioni dal master attraverso due modalità distinte: pull e push. Modalità pull: gli Agent interrogano periodicamente il Master (di default ogni 30 min), per verificare se vi sono nuovi cambiamenti da dover applicare. In questo modello, i cambiamenti applicati al master vengono quindi propagati ai nodi con un certo ritardo. Modalità push: il Master ha il compito di propagare i cambiamenti agli Agents, di solito attraverso code di messaggi. I cambiamenti si propagano più rapidamente rispetto al modello pull. 12 Figura 2: Modello Master/Agent 2.2 Panoramica su Salt, Ansible e Chef Analizziamo ora alcuni dei tools più diffusi. 2.2.1 Salt Salt, rilasciato nel 2011 da SaltStack, è un tool molto scalabile in grado di gestire decine di migliaia di server. Si basa su CLI e la comunicazione, basata sul metodo push, è abbastanza semplice poiché avviene tramite SSH. I clients, detti minions, ricevono i comandi dal server master e rispondono con i relativi risultati. I server master possono essere più di uno e distribuiti su più livelli in modo da distribuire il carico delle richieste, anche se così facendo si rischia di aumentare la ridondanza dei dati. Salt si può eseguire sia in modalità Standalone, nelle piccole infrastrutture o per ragioni di testing, sia in modalità Master/Agent, tramite la quale il client riceverà la propria configurazione attraverso files chiamati Salt States (SLS), raccolti, compilati e successivamente inviati dal master. Infine, grazie al sistema di peering, i masters, dopo aver ricevuto richieste dai minions, possono a loro volta delegare le risposte ad altri masters. Per esempio, questo meccanismo risulta efficace quando deve essere analizzato in tempo reale un database per il recupero di dati utili al completamento di una configurazione per un client. Salt supporta diverse distribuzioni: Arch Linux, Debian, Fedora, FreeBSD, Gentoo, OS X, RHEL e derivate, Solaris, Ubuntu, Windows,Suse. Per maggiori informazioni riguardo alle specifiche installazioni vedi http://docs.saltstack.com/en/latest/topics/installation. 13 2.2.2 Ansible Un altro strumento open-source utilizzato per la gestione delle configurazioni e per l’automazione di un’infrastruttura IT è Ansible. Lanciato nel 2012, gestisce i nodi tramite SSH e necessita di Python (2.4 o successivi) per essere installato su questi ultimi. Ansible ha un’architettura modulare che consente di poterlo estendere all’infinito: ogni modulo, che può essere scritto in qualsiasi linguaggio di programmazione, svolge una determinata funzione e gestisce un singolo aspetto di ogni sistema. I componenti principali sono: • Inventario. E’ la lista di server sui quali Ansible applica, a comando, le configurazioni di sistema e le istruzioni di automazione. Di default è contenuto all’interno del file /etc/ansible/hosts, anche se è possibile specificare un percorso a piacere. • Tasks. Sono una serie di istruzioni che Ansible esegue in ordine di apparizione. • Handlers. Sono delle istruzioni che vengono eseguite a seguito di una determinata azione. Gli Handlers si basano sul modulo service, utilizzato per gestire i servizi di sistema. • Playbook. Sono delle collezioni di Tasks e devono essere definiti in linguaggio YAML. • Moduli. Vengono utilizzati per la gestione di servizi cloud. Facilitano l’installazione di pacchetti software su server Linux con apt e yum, la gestione di file di configurazione e database etc. A differenza di altri tools, Ansible, non richiede l’installazione di alcun agent sui server, in quanto utilizza di default il trasporto SSH, eliminando così anche la necessità di installare software estraneo sui nodi. Qualora la comunicazione avvenga con sistemi che non consentono di default l’accesso alla SSH come root, Ansible accetta credenziali di tipo sudo per eseguire comandi e operazioni su tali sistemi. Per operazioni semplici, come ad esempio verificare che un servizio sul sistema è in esecuzione o innescare aggiornamenti del sistema e riavvii dello stesso, lo scambio di informazioni tra hosts avviene senza l’utilizzo di particolari file di configurazione. 14 Ansible può essere distribuito in ambienti di virtualizzazione e in ambienti di cloud pubblico e privato, quali VMware, OpenStack, AWS, Eucalyptus Cloud, KVM, e CloudStack. La macchina da cui vengono lanciati i comandi richiede l’installazione di Python 2.6 e supporta diverse distribuzioni basate su Linux e Unix, tra le quali ricordiamo Red Hat, Debian, CentOS, OS X e BSD; sistemi Windows non supportati. I nodi invece che devono essere gestiti richiedono l’installazione di Python 2.4 (o successivi). L’installazione di python-simplejson è necessaria se si eseguono versioni di Python precedenti alla 2.5. Inoltre viene fornito supporto per macchine Windows. 2.2.3 Chef Anche Chef, come i precedenti, è un tool per la gestione delle configurazioni di un’infrastruttura IT, distribuito sotto la licenza Apache 2.0 e scritto in Ruby (lato client) e in Erlang4 (lato server). Chef si basa su semplici concetti, quali il raggiungimento dello stato di sistema desiderato, la pianificazione centralizzata dell’infrastruttura IT e l’aggregazione di semplici risorse per realizzare sistemi complessi. Si basa su due modalità di funzionamento: • Architettura Standalone. Permette di utilizzare i cookbooks (“ricette”) senza richiedere alcun accesso allo Chef server. Il demone chef-solo viene eseguito in locale e richiede che: sia i cookbooks sia le relative dipendenze vengano memorizzati sul disco fisico di quel nodo. Non supporta tutto l’insieme di funzionalità che invece mette a disposizione chef-client. • Architettura Client/Server. In quest’architettura, lo Chef server rappresenta il repository centrale di tutti i dati, le “ricette”, di configurazione. Qualsiasi nodo che esegue chef-client, invece, può essere gestito tramite il sistema Chef. Chef-client esegue tutte le attività di configurazione specificate dalla run-list, prelevando tutti i dati di configurazione necessari dal server centrale. La comunicazione tra client e server viene resa sicura tramite l’utilizzo di una combinazione di chiavi pubbliche e private. 15 2.2.3.1 Componenti di chef Come si nota dall’immagine sottostante, numerosi sono i componenti che permettono di gestire un sistema con Chef. Questi lavorano insieme per fornire informazioni le istruzioni a chef-client, affinchè questo possa eseguire il proprio lavoro. Figura 3: Chef Components I principali componenti di Chef (Fig. 3) sono: • Chef-client. E’ l’agent che viene eseguito su ogni nodo che deve essere gestito da Chef. Questo esegue tutte le operazioni necessarie per portare il nodo nello stato 16 richiesto. Rappresenta il componente principale installato sui nodi insieme ad ohai, tool utilizzato per individuare gli attributi dei nodi (utilizzo della rete, della memoria, della CPU etc.) • Workstation. E’ la macchina che esegue knife e che viene utilizzata per controllare un singolo Chef server. Permette all’utente di testare e gestire i cookbooks e di caricarli sullo Chef server. Knife è uno strumento a linea di comando utilizzato per gestire nodi, cookbooks e ricette, risorse cloud etc. • Chef server. Raccoglie tutti i dati di configurazione necessari a chef-client per configurare un nodo. Memorizza cookbooks, le politiche che devono essere applicate ai nodi e i metadati che li descrivono. I cookbooks costituiscono la parte fondamentale per la distribuzione delle politiche di configurazione. Questi definiscono come deve essere configurato un nodo, attraverso l’utilizzo di attributi e “ricette”; quest’ultime, scritte in Ruby, devono definire qualsiasi cosa sia necessaria per configurare una specifica parte del sistema. Due componenti molto importanti del server sono gli attributi e le run-list: i primi rappresentano specifici dettagli di un nodo, quali lo stato corrente, lo stato precedente e successivo all’esecuzione di chef-client e vengono definiti dallo stato del nodo stesso, dai cookbooks, dalle varie regole. Le run-list, invece, definiscono tutte le impostazioni di configurazione da applicare al nodo, un elenco ordinato di regole da eseguire, secondo l’ordine di apparizione. • Chef Supermarket. E’ il luogo in cui i cookbooks della comunità vengono creati e mantenuti. Inoltre, Chef server mette a disposizione dell’utente delle funzionalità premium che possono essere facilmente abilitate ed integrate, quali: • Chef Manager. Fornisce un’interfaccia web-based per la gestione di attributi, runlist, roles, cookbooks etc. che sono memorizzati sul server. • Chef Analytics. Fornisce visibilità in tempo reale di cosa sta accadendo sullo Chef server, compreso cosa sta cambiando, chi ha fatto e quando sono avvenuti i cambi. 17 • Chef Availability. Si occupa di replicare lo Chef server, in modo da fornire supporto per l’High Availability. Chef può essere integrato con le piattaforme di gestione di sistemi cloud, come Rackspace, Amazon EC2, Google Cloud Platform, OpenStack, Microsoft Azure, per configurare automaticamente nuove macchine. Chef-client `e supportato da diverse distribuzioni Linux, Unix, e Microsoft Windows, tra le quali troviamo Ubuntu, Debian, RHEL/CentOS, Fedora, Mac OS X, Solaris, FreeBSD, Windows Server. Chef-server supporta invece solo alcune versioni di CentOS, Oracle Linux, RHEL ed Ubuntu. 18 Capitolo 3: Puppet Puppet è uno strumento di gestione delle risorse e del software, rilasciato nel 2005 dalla Puppet Labs, grazie al quale è possibile automatizzare ogni passo del processo di sviluppo del software, a partire dal provisioning delle macchine virtuali e fisiche fino alla configurazione e al reporting; dalle prime fasi di sviluppo del codice fino al testing, al rilascio del prodotto e dei futuri aggiornamenti. Puppet consente di: • definire lo stato desiderato della configurazione dell’infrastruttura grazie ad un semplice linguaggio di tipo dichiarativo; • simulare modifiche alla configurazione prima di applicarle definitivamente all’infrastruttura, in modo da sapere cosa accadrà quando il cambio verrà effettuato; • applicare lo stato desiderato in maniera automatica, correggendo così eventuali variazioni nella configurazione; • consultare i reports presenti sul puppet Master, contenenti informazioni dettagliate sull’esatta configurazione dei nodi, inclusi tutti i cambiamenti effettuati e quando sono stati applicati. Il reporting è disponibile solo in Puppet Enterprise. Per definire, quindi, lo stato desiderato del sistema, è possibile scrivere i moduli in base alle proprie specifiche di realizzazione utilizzando il DSL di Puppet, oppure utilizzare dei moduli pre-compilati disponibili online sul Puppet Forge Marketplace e scaricabili gratuitamente. Puppet Software è disponibile nelle due distribuzioni OpenSource (personalizzabile, 19 flessibile e disponibile sotto la licenza Apache 2.0) e Enterprise (che include più di 40 servizi open-source come Puppet, PuppetDB, PE Console, ecc.). Puppet Enterprise, inoltre, include un’interfaccia grafica web per l’analisi dei reports e il controllo dell’infrastruttura, funzioni per la gestione degli aggiornamenti e della manutenzione, meccanismi di gestione dei certificati e strumenti di cloud provisioning. 3.1 Puppet Management Tool Puppet Management Tool rappresenta lo strumento più completo in termini di azioni disponibili, moduli di configurazione e interfaccia utente. La versione open-source offre le funzionalità fondamentali sulla gestione a quasi tutti i principali sistemi operativi. Tutti i moduli e le configurazioni sono scritti con un linguaggio specifico basato su Ruby, mentre, per quanto riguarda l’interfaccia utente, Puppet ha la GUI più completa tra i tools sovracitati, con pieno supporto per Linux, Microsoft Windows, Unix/Unix-like e MacOS X, consentendo il controllo in tempo reale dei nodi gestiti mediante moduli e cataloghi precedentemente compilati ma limitando la possibilità di configurarli. Il reporting, invece, è ben sviluppato in quanto fornisce dettagli sullo stato dei sistemi e sulle modifiche di volta in volta apportate. 3.1.1 Modelli di funzionamento Puppet offre due possibili modalità di funzionamento: Master/Agent (predefinita), e standalone. In Puppet standalone, ogni nodo usa periodicamente il commando puppet apply per compilare e applicare il proprio catalogo, usando il set completo di moduli e manifesti di Puppet. Ogni nodo, cioè, possiede una copia degli stessi files e dati che il puppet master possiede nel modello Agent/Master. Questa modalità di funzionamento distribuisce il carico della compilazione su più nodi invece di concentrarlo su un unico o su pochi master servers, e non richiede la presenza di un servizio puppet master sempre disponibile e reattivo. Lo svantaggio è che risulta meno 20 pratico aggiornare le configurazione e che ogni nodo può vedere come sono configurati gli altri nodi. Inoltre, la distribuzione dei manifesti, moduli e dati aggiornati ad ogni nodo è a completo carico dell’utente, e non viene gestita automaticamente dal puppet master. La modalità di funzionamento Master/Agent, ovvero quella predefinita, prevede la presenza di uno o più Puppet master servers che controllano le informazioni di configurazione, mentre i nodi che devono essere controllati richiedono al master solo i propri cataloghi di configurazione. In questa architettura, i nodi da controllare eseguono il Puppet Agent daemon, come un servizio in background. Uno o più servers eseguono il Puppet master daemon, generalmente come un’applicazione Rack gestita attraverso un web server (come Apache con Passenger). La comunicazione avviene in questo modo. Periodicamente i Puppet agent invieranno informazioni al Puppet master contattandolo sulla porta 8140 (impostata di default). La connessione che si stabilisce tra loro è crittografata: il client genera una key auto-firmata prima di collegarsi al server, dopodiché gliela invia e attende che la verifichi. In seguito, l’agent invia una richiesta di certificato che il master deve convalidare per poter stabilire definitivamente una connessione sicura, cioè il server si comporta come “autorità di certificazione”. In questo modo il client potrà richiedere (polling) un catalogo al master. Questo compilerà e reinvierà il catalogo al rispettivo nodo, usando diversi mezzi di informazione ai quali ha accesso. Ricevuto il catalogo, il Puppet agent lo applicherà controllando ogni risorsa descritta da esso. Se trova delle risorse che non sono nello stato desiderato, applicherà ogni cambiamento necessario per correggerle. (Oppure, in no-op mode, esso riporterà al master quali cambiamenti sarebbero stati necessari). Dopo aver applicato il catalogo, l’agent invierà un report al Puppet master. 21 3.2 Il linguaggio Puppet Puppet usa un proprio domain-specific language (DSL) per descrivere le configurazioni delle macchine. Il DSL di Puppet è un linguaggio di tipo dichiarativo anziché imperativo, ovvero invece di definire un processo o un set di istruzioni, il codice di Puppet descrive solamente lo stato finale desiderato per il sistema e si affida a providers interni per l’effettiva implementazione. Il codice in questo linguaggio viene salvato in files chiamati manifesti, che non sono altro che semplici files di testo txt salvati con estensione .pp. Più manifesti vengono raggruppati in moduli, le cui combinazioni permettono di creare le diverse configurazioni. 3.2.1 Risorse Prima di definire nel dettaglio cosa sono i manifesti ed i moduli, è opportuno partire dall’analisi dei blocchi fondamentali della sintassi del modello di linguaggio dichiarativo di Puppet, ovvero le risorse. Le risorse sono le unità fondamentali per la modellazione dei sistemi. Ogni risorsa descrive un aspetto del sistema ed il suo stato, ad esempio un servizio che dovrebbe essere in esecuzione oppure un package da installare. Il blocco di codice che descrive la risorsa è detto dichiarazione della risorsa, come ad esempio: L user { 'root': ensure => 'present', comment => 'root', gid => '0', home => '/root', password => '$1$jrm5tnjw$h8JJ9mCZLmJvIxvDLjw1M/', password_max_age => '99999', password_min_age => '0', shell => '/bin/bash', uid => '0', } La parola user, prima della parentesi graffa, è il tipo della risorsa. Esso serve a definire il 22 genere della risorsa in questione. La parola root tra le singole virgolette prima della colonna è il titolo della risorsa. Puppet utilizza il titolo della risorsa come suo identificatore univoco, ovvero non vi possono essere due risorse con lo stesso nome. Dopo i due punti della prima linea vi è una lista di attributi ed i corrispondenti valori. Ogni linea è costituita dal nome dell’attributo, un => (detto ‘hash rocket’), un valore, e una virgola finale. La dichiarazione di una risorsa assume quindi la seguente forma contratta: type {'title': attribute => 'value', } Dichiarare una risorsa serve ad aggiungerla al catalogo, e per dire a Puppet di gestirne lo stato. Così, quando Puppet applicherà il catalogo compilato, esso: Leggerà lo stato attuale della risorsa sul sistema di destinazione; Confronterà lo stato attuale con quello desiderato; Se necessario, cambierà il sistema al fine di forzare lo stato desiderato; Puppet fornisce alcuni tools essenziali per la gestione delle risorse. Essi sono: Puppet describe: fornisce una descrizione del tipo della risorsa; Puppet resource: fornisce una descrizione della risorsa e, se eseguito con il flag –e, di aprirla nell’editor di testo per modificarla; Puppet apply: permette di creare una risorsa, o di effettuare modifiche veloci ad una esistente. Questo sistema di dichiarazione delle risorse e di providers è chiamato Resource Abatraction Layer o RAL. 3.2.2 Manifesti e classi Due elementi fondamentali di Puppet per l’organizzazione e l’implementazione della dichiarazione delle risorse sono: le classi e i manifesti. Il corretto uso di entrambi è 23 essenziale al fine di creare codice Puppet testabile e riusabile. Come è stato già detto, un manifesto è un file di testo che contiene codice Puppet ed è salvato con estensione .pp. Sebbene sia utile salvare e modificare codice Puppet attraverso un file, lo scopo principale dei manifesti è quello di organizzare il codice in un modo che Puppet stesso può comprendere. Teoricamente è possibile aggiungere qualsiasi pezzo di codice sintatticamente valido ad un manifesto, ma, affinchè l’architettura di Puppet funzioni efficacemente, occorre seguire delle regole di base nella scrittura e nel posizionamento dei manifesti. Un elemento chiave della corretta gestione dei manifesti è costituito dalle classi. Nel DSL di Puppet una classe è un blocco di codice, contenente risorse o altre classi, al quale viene assegnato un nome. Una classe serve a gestire un insieme di risorse relative a una singola funzione o a un componente del sistema. Per usare una classe sono necessari due operazioni. Innanzitutto è necessario definirla scrivendo una definizione di classe e salvandola in un manifesto. La classe può poi essere dichiarata per applicarla ai nodi dell’infrastruttura. Quest’operazione può essere effettuata in modi diversi. Una possibile soluzione prevede l’utilizzo del classificatore di nodi della PE Console, mentre un’altra prevede l’utilizzo del manifesto site.pp. Questo è il primo manifesto che il Puppet agent controlla quando si connette al master. Esso definisce i settaggi globali e le risorse di default che verranno applicate a tutti i nodi dell’infrastruttura, e contiene le definizioni dei nodi (chiamate node statements), ovvero blocchi di codice Puppet che definiscono insiemi di nodi e dichiarano quali classi devono essere applicate ad essi. Tornando alle classi, esse in Puppet sono singleton, ovvero una classe può essere dichiarata una sola volta su un dato nodo. Un esempio di definizione di classe che deve essere salvata in un opportuno manifesto cowsay.pp nella directory ./manifests è illustrato alla pagina successiva. 24 class cowsayings::cowsay { package { 'cowsay': ensure => 'present', } } In questo modo abbiamo definito la classe, ma non l’abbiamo dichiarata. Per fare ciò è possibile creare un manifesto cowsay.pp nella directory ./tests ed applicarlo tramite puppet apply, oppure utilizzare uno dei metodi menzionati in precedenza. Nel primo caso, ciò che dovrà essere inserito nel manifesto è il seguente codice: include cowsayings::cowsay Puppet fornisce il tool puppet parser per controllare la sintassi di un manifesto. Il parser non ritornerà nulla se non vi sono errori, altrimenti occorre riaprire il manifesto e correggere il problema. 3.2.3 Moduli I moduli sono una convenzione per organizzare i manifesti in modo che possano essere localizzati e caricati automaticamente dal Puppet master. Essi consentono di organizzare il codice Puppet in unità che siano testabili, riusabili e portabili, ovvero modulari. Questo comporta che anziché scrivere da zero il codice per ogni configurazione di cui si ha bisogno, è possibile riutilizzare e comporre tra loro moduli già esistenti. E poiché questi moduli sono separati e indipendenti, essi risultano facili da testare, manutenere e condividere. I moduli possono contenere molteplici classi di Puppet, generalmente collegate tra loro. Un modulo è una directory con uno specifico layout interno, che è localizzata in una delle modulepath directories del Puppet master. In Puppet Enterprise la directory modulepath principale per gli utenti si trova in /etc/puppetlabs/puppet/modules sul Puppet master server. E’ possibile conoscere il modulepath su un sistema con Puppet utilizzando il comando ‘puppet agent --configprint modulepath’. 25 Un esempio di modulo è il seguente: /etc/puppetlabs/puppet/environments/production/modules/ └── apache ├── files ├── lib ├── manifests ├── spec ├── templates └── tests ... Le subdirectories standardizzate consentono agli utenti di Puppet e a Puppet stesso di localizzare ognuno dei componenti che costituiscono il modulo: apache: la directory più esterna corrisponde al nome del modulo; files: contiene files statici che i nodi possono scaricare; lib: contiene plugins; manifests: contiene tutti i manifesti del modulo; spec: contiene tests per i plugins; templates: contiene i templates che i manifesti possono usare; tests: contiene esempi che mostrano come dichiare le classi del modulo; I moduli e la struttura di directory degli stessi, infine, forniscono un importante mezzo per la gestione dello scope in Puppet. Mantenendo tutto perfettamente impacchettato nel proprio modulo, infatti, è possibile evitare più facilmente confusioni e collisioni di nomi. 26 3.2.4 Variabili e parametri di classe La sintassi delle variabili di Puppet consente di assegnare un nome a una parte di dati, in modo da utilizzare quel nome in un manifesto per riferirsi al valore contenuto. Nella sintassi di Puppet, i nomi di variabile sono preceduti da un $ (segno del dollaro), e il valore è assegnato con l’operatore = ; Un esempio di assegnazione di una stringa a una variabile è il seguente: $myvariable = 'look, a string!' Una volta definita la variabile, è possibile usarla in qualsiasi parte del manifesto in cui ci si voglia riferire al valore assegnato. Sebbene il sistema delle variabili possa sembra simile a quello di altri linguaggi di programmazione, esso presenta delle differenze sostanziali: A differenza della dichiarazione di una risorsa, in un manifesto è necessario dichiarare la variabile prima di poterla usare; Se si prova a usare una variabile non definita, Puppet parser non ritornerà errori, in quanto considererà la variabile come se contenesse il valore speciale undef. E’ possibile assegnare una variabile una sola volta all’interno dello stesso scope, ovvero, una volta assegnato, il valore non può essere modificato. La sintassi delle variabili di Puppet comprende anche meccanismi di interpolazione, attraverso i quali è possibile inserire stringhe, memorizzate come variabili, all’interno di altre stringhe, e meccanismi che consentono di definire il valore di una variabile in una classe quando essa viene dichiarata anziché definita. In quest’ultimo caso si parla di parametri di classe. Quando si definisce una classe, è possibile inserire una lista di parametri e, opzionalmente, di valori di default tra il nome della classe e la parentesi graffa aperta. Una classe parametrizzata assumerà quindi la seguente forma: class classname ( $parameter = 'default' ) { ... } 27 Una volta definita, una classe parametrizzata può essere dichiarata con una sintassi simile a quella della dichiarazione di una risorsa, incluse le coppie chiave valore per ogni parametro da settare. class {'classname': parameter => 'value', } L e classi parametrizzate sono utili nel caso in cui si voglia applicare la classe ad ogni nodo dell’infrastruttura o a molti nodi, apportando dei cambiamenti su ogni nodo. Anziché riscrivere l’intera classe o il modulo da zero per apportare questi cambiamenti, è possibile usare le classi parametrizzate per modificare questi valori quando la classe viene dichiarata. 3.2.5 Facts e conditional statements Puppet gestisce configurazioni su molteplici sistemi differenti, quindi il codice che viene scritto deve essere flessibile e portabile. Sebbene il resource abstraction layer faccia già molto al fine di garantire l’adattabilità del codice, vi sono comunque degli elementi che è opportuno lasciare alla gestione del programmatore. Puppet fornisce due strumenti essenziali per la scrittura di codice adattabile, ovvero i facts e i conditional statements. Il tool facter è uno strumento attraverso il quale è possibile reperire tutte le informazioni riguardanti uno specifico nodo, come ad esempio il sistema operativo in esecuzione, la versione di puppet installata e altre informazioni utili per la gestione del nodo. Il facter può essere lanciato da riga di comando, e in questo caso fornisce a video le informazioni del nodo al quale si riferisce, oppure può essere utilizzato per incapsulare le informazioni del nodo nelle variabili nei manifesti. Per ottenere la lista di tutti i facts disponibili attraverso il facter, occorre lanciare il comando: facter -p | less 28 Ogni fact che comparirà nella lista potrà essere usato nei manifesti con la sintassi $::factname. I doppi punti ‘::’ indicano che il fact è definito nel top scope, ovvero prima che ogni variabile nelle classi o nelle definizioni dei nodi sia assegnata. Sebbene si possano usare i facts senza i due punti, è opportuno adottare questa sintassi al fine di evitare collisioni di nomi, in quanto un fact potrebbe essere sovrascritto da una variabile definita localmente. I conditional statements ritornano valori differenti o eseguono diversi blocchi di codice sulla base del valore di una determinata variabile. Usati in combinazione con i facts, essi quindi permettono di scrivere codice adattabile che si comporti in maniera desiderata su macchine che eseguono sistemi operativi differenti e che svolgono ruoli diversi nell’infrastruttura. Puppet supporta diversi metodi per implementare i conditional statements: If statements; Unless statements; Case statements; Selectors; Gli if statements in Puppet sono simili a quelli presenti negli altri linguaggi di programmazione. Un if statement include un blocco di codice Puppet che sarà eseguito solo se la condizione che lo precede risulta vera. Un if statement può anche contenere un numero qualsiasi di clausole elseif e else. Le regole sono le seguenti: Se la if condition fallisce, Puppet si sposta sulla elseif condition (se ne esiste una); Se sia la if che la elseif falliscono, Puppet eseguirà il codice nel blocco else (se ne esiste uno). Se tutte le condizioni falliscono e non c’è un blocco else, Puppet non farà nulla e continuerà l’esecuzione. 29 Segue un esempio di codice: class accounts ($name) { if $::operatingsystem == 'centos' { $groups = 'wheel' } elsif $::operatingsystem == 'debian' { $groups = 'admin' } else { fail( "This module doesn't support ${::operatingsystem}." ) } notice ( "Groups for user ${name} set to ${groups}" ) user { $name: ensure => 'present', home => "/home/${name}", groups => $groups, } } Lo statement unless si comporta in maniera inversa all’if. Esso eseguirà il blocco di codice solo se la condizione è falsa. In questo caso però non esistono gli equivalenti dell’elseif e dell’else. Come l’if statement, i case statements eseguono solo uno di una serie di blocchi di codice. Essi sono costituiti da un’espressione di controllo, una lista di casi, e una serie di blocchi di codice che corrispondono ai casi. Puppet eseguirà il primo blocco di codice il cui valore corrisponde all’espressione di controllo. Un esempio è il seguente: Qcase $::operatingsystem { u 'CentOS': { $apache_pkg = 'httpd' } 'Redhat': { $apache_pkg = 'httpd' } e 'Debian': { $apache_pkg = 'apache2' } 'Ubuntu': { $apache_pkg = 'apache2' } s default: { fail("Unrecognized operating system for webserver.") } t} package { $apache_pkg : ensure => present, } 30 Questo codice in particolare consente di settare la variabile $apache_pkg in base al sistema operativo presente sul nodo, il cui nome è noto attraverso la variabile $::operatingsystem. I selector statements, infine, sono simili ai case statements, ma invece di eseguire un blocco di codice, un selettore assegna direttamente un valore. Un selettore può apparire in questo modo: Q $rootgroup = $::osfamily ? { 'Solaris' => 'wheel', 'Darwin' => 'wheel', 'FreeBSD' => 'wheel', 'default' => 'root', } Qui, il valore della variabile $rootgroup è determinato sulla base del controllo della variabile $::osfamily. 3.2.6 Ordinamento delle risorse Quando si ha a che fare con del codice, generalmente lo si legge dall’alto verso il basso e lo si esegue nello stesso ordine. Nel caso di Puppet non è così. Quando Puppet lavora con le dichiarazioni delle risorse nei manifesti, non le esegue in un ordine prefissato ma cerca di volta in volta il modo più efficiente di agire. Il catalogo è una lista di tutte le risorse che dovranno essere applicate a un determinato sistema, e le relazioni tra di esse. Per alcuni tipi di risorse Puppet è intelligente abbastanza da capire quali sono le dipendenze tra le risorse. Queste dipendenze implicite tra le risorse sono dette autorequisiti. Il comando utilizzato per controllare gli autorequisiti di una risorsa è puppet describe. Eseguendo ad esempio: puppet describe file 31 Nella descrizione della risorsa apparirà il seguente paragrafo: Autorequires: If Puppet is managing the user or group that owns a file, the file resource will autorequire them. If Puppet is managing any parent directories of a file, the file resource will autorequire them. Questo significa che dichiarando una risorsa di tipo file, Puppet gestirà automaticamente i suoi autorequisiti. Alcune volte, tuttavia, è necessario specificare a Puppet quale dichiarazione di risorsa deve essere applicata prima di un’altra. Ad esempio, volendo dichiarare un servizio che dovrebbe essere in esecuzione, bisogna assicurarsi che il package corrispondente sia già installato e configurato prima di avviare il servizio. Per ovviare al problema, la sintassi di Puppet offre diversi metodi per gestire esplicitamente l’ordinamento delle risorse. Uno di questi metodi consiste nel dire a Puppet quale ordinamento delle risorse adottare attraverso l’utilizzo di metaparametri nella dichiarazione delle stesse. I metaparametri sono attributi che possono essere settati in qualsiasi risorsa per dire a Puppet come gestirla. Ci sono in totale quattro attributi metaparametrici che è possibile include nella dichiarazione delle risorse per ordinare le relazioni tra le stesse. Before indica che la risorsa debba essere applicata prima della risorsa specificata. Require indica che la risorsa debba essere applicata dopo la risorsa specificata. Notify indica che la risorsa debba essere applicata prima della risorsa specificata, proprio come con before. In aggiunta a ciò, notify genererà un evento di refresh per la risorsa specificata qunado la risorsa notificante cambierà. Subscribe indica che la risorsa debba essere applicata dopo la risorsa specificata, proprio come con after. In aggiunta a ciò, subscribe genererà un evento di refresh per la risorsa sottoscrivente quando la risorsa specificata cambierà. 32 Il valore del metaparametro è il titolo o i titoli (in un array) di una o più risorse target. Ecco un esempio di utilizzo del metaparametro notify: file {'/etc/ntp.conf': ensure => file, source => 'puppet:///modules/ntp/ntp.conf', notify => Service['ntpd'], } service {'ntpd': ensure => running, } I In questo esempio viene gestito il file /etc/ntp.conf. Ogni volta che il file ntp.conf cambia, un evento di refresh sarà avviato per il servizio di nome ntpd. Gli eventi di refresh, di default, riavviano un servizio, ma è possibile specificare cosa dovrebbe essere fatto durante un refresh usando l’attributo refresh per il tipo di risorsa service, il cui valore è il comando da eseguire. 33 3.3 Installazione e configurazione di Puppet open source Come abbiamo già detto in precedenza, Puppet può essere installato su una moltitudine di sistemi operativi differenti. La guida che verrà mostrata in questa sezione fa riferimento all’installazione di Puppet su due macchine dotate di Ubuntu 14.04, quindi, in caso di sistemi differenti, i comandi mostrati saranno diversi. Prima di procedere con l’installazione è opportuno verificare che il firewall non sia restrittivo e che consenta al master di essere raggiungibile sulla porta 8140, e che la rete sia opportunamente configurata assegnando a ogni host un hostname univoco. 3.3.1 Creazione e configurazione del Puppet master 1. Il Puppet master, per questa guida, dovrà essere una macchina dotata di Ubuntu 14.04 e con hostname ‘puppet’. Per fare ciò, una volta avviata la macchina, è necessario configurare il file /etc/hosts su tutte le macchine della rete e aggiungere la seguente riga: #IPpuppetMaster puppetmaster.example.com puppet dove #IPpuppetMaster è l’ip del puppet master che può essere visualizzato utilizzando il comando ifconfig sulla macchina master. 2. Installare il package NTP e configurarlo impostando i server di riferimento il più vicino possibile al puppet master. Usare il seguente comando per l’installazione: P sudo apt-get update && sudo apt-get -y install ntp Per la configurazione, invece, occorre aprire il file ntp.conf: sudo nano /etc/ntp.conf 34 Aggiungere poi i server dalla pagina NTP Project Pool all’inizio del file: I server server server server 0.it.pool.ntp.org 1.it.pool.ntp.org 2.it.pool.ntp.org 3.it.pool.ntp.org Infine, riavviare il servizio per applicare le modifiche: sudo service ntp restart L’installazione dell’NTP è necessaria al fine di garantire che il tempo di sistema del master sia accurato per una corretta gestione dei certificati. Certificati inviati dal passato o dal futuro, infatti, potrebbero essere rifiutati dai nodi. 3. Scaricare e installare il package Puppet Labs: I wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb sudo dpkg -i puppetlabs-release-trusty.deb sudo apt-get update sudo apt-get install puppetmaster-passenger Interrompere il Puppet master fermando il servizio apache2: sudo service apache2 stop 4. Eliminare i certificati creati in automatico durante l’installazione dei package. La posizione di default dei certificati di Puppet è /var/lib/puppet/ssl. Per eliminarli usare il seguente comando: sudo rm -rf /var/lib/puppet/ssl 35 5. Configurare i certificati modificando il file di configurazione del puppet master: I sudo nano /etc/puppet/puppet.conf Il file conterrà il seguente testo: M[main] logdir=/var/log/puppet vardir=/var/lib/puppet ssldir=/var/lib/puppet/ssl rundir=/var/run/puppet factpath=$vardir/lib/facter templatedir=$confdir/templates [master] # These are needed when the puppetmaster is run by passenger # and can safely be removed if webrick is used. ssl_client_header = SSL_CLIENT_S_DN ssl_client_verify_header = SSL_CLIENT_VERIFY Modificarlo eliminando la riga templatedir e aggiungendo le seguenti righe in coda alla sezione main: S certname = puppet dns_alt_names = puppet,puppetmaster.example.com Se nel momento della connessione tra master e agent, il servizio puppet sull’agent dovesse dare errore di certificato non trovato, allora è necessario modificare il file di configurazione di Apache per settare il corretto nome al certificato da trovare (/etc/apache2/sites-available/puppetmaster.conf). 6. Generare un nuovo certificato CA eseguendo il seguente comando: i sudo puppet master --verbose --no-daemonize Il cui output sarà il seguente: 36 Info: Creating a new SSL key for ca Info: Creating a new SSL certificate request for ca Info: Certificate Request fingerprint (SHA256): EC:7D:ED:15:DE:E3:F1:49:1A:1B:9C:D8:04:F5:46:EF:B4:33:91:91:B6:5D:19:A C:21:D6:40:46:4A:50:5A:29 Notice: Signed certificate request for ca ... Notice: Signed certificate request for puppet Notice: Removing file Puppet::SSL::CertificateRequest puppet at '/var/lib/puppet/ssl/ca/requests/puppet.pem' Notice: Removing file Puppet::SSL::CertificateRequest puppet at '/var/lib/puppet/ssl/certificate_requests/puppet.pem' Notice: Starting Puppet master version 3.6.2 Premere CTRL-C per ritornare alla shell. 7. La configurazione del master è terminata e quindi occorre avviare il servizio. Prima di fare ciò è opportuno creare un file di manifesto site.pp vuoto con il comando: sudo touch /etc/puppet/manifests/site.pp Avviare quindi il servizio apache2: sudo service apache2 start 3.3.2 Creazione e configurazione del Puppet agent 1. Scaricare e installare il package Puppet Labs: wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb sudo dpkg -i puppetlabs-release-trusty.deb sudo apt-get update sudo apt-get install puppet 2. Abilitare il puppet agent. Per fare ciò, aprire il file: e sudo nano /etc/default/puppet 37 e modificare il valore di START a “yes”: START=yes 3. Configurare l’agent modificando il suo file di configurazione. sudo vi /etc/puppet/puppet.conf Il contenuto sarà uguale a quello del file di configurazione del puppet master prima delle modifiche. Eliminare anche qui la riga di templatedir, e tutta la sezione del master. Aggiungere poi il seguente testo: [agent] server = puppetmaster.example.com Avviare il puppet agent: sudo service puppet start 3.3.3 Prima connessione e scambio certificati 1. Eseguire il seguente comando sul puppet agent per effettuare la prima connessione: Apuppet agent -t Al primo tentativo di comunicazione, l’agent invierà una richiesta di firma del certificato al master che dovrà accettarla prima di poter controllare il nodo. 2. Eseguire il seguente comando sul puppet master per visualizzare la lista di certificati da firmare: sudo puppet cert list Avendo configurato un unico nodo, la lista conterrà una sola richiesta contenente l’hostname del nodo stesso come ad esempio: 38 N"hostnameNodo" (SHA256) B1:96:ED:1F:F7:1E:40:53:C1:D4:1B:3C:75:F4:7C:0B:A9:4C:1B:5D:95:2B:79:C o 0:08:DD:2B:F4:4A:36:EE:E3 Non vi sarà alcun ‘+’ davanti ad essa. Questo indica che non è stata ancora firmata. 3. Per firmare la richiesta, eseguire il seguente comando sul puppet master: sudo puppet cert sign hostnameNodo L’output sarà il seguente: Notice: Signed certificate request for hostnameNodo Notice: Removing file Puppet::SSL::CertificateRequest hostnameNodo at '/var/lib/puppet/ssl/ca/requests/hostnameNodo.pem' L’infrastruttura è ora perfettamente configurata per essere gestita da Puppet. 39 3.4 Esempi di funzionamento di Puppet 3.4.1 Utilizzo dei facts Ora che l’infrastruttura è stata configurata, è possibile verificarne il corretto funzionamento attraverso l’esecuzione di semplici manifesti. Come abbiamo detto in precedenza, il file di manifesto principale sul Puppet master è collocato in /etc/puppet/manifests/site.pp. Aprirlo sul master: sudo nano /etc/puppet/manifests/site.pp Aggiungere le seguenti righe di codice: S file {'/tmp/example-ip': ensure => present, mode => 0644, content => "Questo è il mio indirizzo IP pubblico: ${ipaddress_eth0}.\n", } Salvare il file e chiuderlo. Queste linee di codice servono a specificare che ogni nodo dovrà avere un file di testo di nome /tmp/example-ip, con i permessi –rw–r—r--, e contenente l’IP pubblico del nodo. Applicare le modifiche ai nodi eseguendo il comando sudo puppet agent –test da uno dei nodi, oppure attendere che essi richiedano automaticamente il catalogo al master. Per stampare il contenuto del file a video eseguiamo il seguente comando da un nodo: L cat /tmp/example-ip L’output dovrebbe essere simile al seguente: Questo è il mio indirizzo IP pubblico: 192.128.182.133 40 3.4.2 Specifica dei nodi Se si vuole definire una risorsa per dei nodi in particolare e non per tutti, è necessario definire un nodo nel manifesto. Sul master, aprire il site.pp: sudo vi /etc/puppet/manifests/site.pp Aggiungere le seguenti righe di codice: S node 'ns1', 'ns2' { file {'/tmp/dns': ensure => present, mode => 0644, content => "Solo i server DNS possiedono questo file.\n", } } node default {} Salvare e uscire. Queste linee di codice specificano che solo i nodi di nome ‘ns1’ e ‘ns2’ dovranno avere un file di nome /tmp/dns contenente il testo indicato in content. Come prima, applicare le modifiche ai nodi con il comando sudo puppet agent –test da uno dei nodi interessati, oppure attendere che essi richiedano automaticamente il catalogo al master. Per stampare il contenuto del file a video eseguiamo il seguente comando da un nodo: L cat /tmp/dns L’output sarà il seguente: Solo i server DNS possiedono questo file. 41 3.4.3 Utilizzo di un modulo Proviamo adesso ad utilizzare un modulo disponibile sul Puppet Forge Marketplace: Apache. Per installarlo, eseguire sul Puppet master il seguente comando: Msudo puppet module install puppetlabs-apache Modificare il site.pp: A sudo nano /etc/puppet/manifest/site.pp Aggiungere le seguenti righe per installare Apache sul nodo #hostdesiderato. S node '#hostdesiderato' { class { 'apache': } apache::vhost { 'example.com': port => '80', docroot => '/var/www/html' } } Salvare e uscire. La prossima volta che Puppet aggiornerà l’ #hostdesiderato, esso installerà il package Apache e configurerà un virtual host chiamato “example.com” con le specifiche descritte nel codice. Per aggiornare l’host subito, eseguire il seguente comando dall’host in questione: N sudo puppet agent --test Nell’output dovrebbero comparire diverse righe che indicano che Apache sta venendo installato sul nodo. Una volta terminato, se tutto è stato fatto correttamente, è possibile recarsi all’indirizzo IP pubblico del nodo attraverso un qualsiasi browser, per visualizzare la pagina di benvenuto di Apache. 42 3.4.4 Configurare un virtual host Apache Nel precedente esempio abbiamo visto come è possibile utilizzare il modulo di apache per visualizzare la pagina di benvenuto dello stesso utilizzando un nodo della rete. In questo paragrafo invece, utilizzeremo lo stesso modulo per hostare una pagina web di nostro gradimento, salvata in forma di file html e di files ad esso associati. L’esempio prenderà come riferimento la homepage di puppetlabs, ovvero https://puppetlabs.com/. Per iniziare è necessario collegarsi al sito https://puppetlabs.com/ e salvare la pagina web utilizzando come nome ‘index’ per semplificare il codice. Verranno creati un file ‘index.html’ e una cartella ‘index_files’ contenente tutti i files necessari alla corretta visualizzazione della pagina. Per hostare la pagina salvata è necessario definire una propria classe. Per fare ciò, occorre creare le directories opportune con i seguenti comandi: A sudo mkdir –p /etc/puppet/modules/sito/manifests sudo mkdir –p /etc/puppet/modules/sito/files Aprire il file init.pp con il seguente comando: Dsudo nano /etc/puppet/modules/sito/manifests/init.pp Definire la classe nel seguente modo: C class sito{ class{‘apache’: default_vhost => false, } apache::vhost {‘prova.com’: port => ‘80’, docroot=> ‘/var/www/sito’ } file {‘/var/www/sito/index_files’: ensure => directory, mode => ‘0644’, source => ‘puppet:///modules/sito/index_files’, recurse => remote, } file {‘/var/www/sito/index.html’: ensure => present, mode => ‘0644’, source => ‘puppet:///modules/sito/index.html’, } } 43 Copiare i files necessari ad hostare il sito, dalla cartella in cui sono stati salvati alla cartella ‘files’ del relativo modulo: A sudo cp –r /home/osboxes/Downloads/index.html etc/puppet/modules/sito/files/ sudo cp –r /home/osboxes/Downloads/index_files /etc/puppet/modules/sito/files/ Aprire il file site.pp con il seguente comando: A sudo nano /etc/puppet/manifests/site.pp Aggiungere le seguenti righe per specificare il nodo cui applicare la classe: I node ‘#hostdesiderato’{ include sito } In questo modo la classe sito sarà applicata al nodo #hostdesiderato. Per applicare le modifiche, infine, eseguire il seguente comando dal nodo in questione: S sudo puppet agent -t See tutto è stato effettuato correttamente, collegandosi all’indirizzo ip pubblico dell’#hostdesiderato, sarà possibile visualizzare la homepage del sito della Puppetlabs. 44 Conclusioni Il processo di automatizzazione che ha colpito la nostra società in questi ultimi anni è stato sia una conseguenza sia un requisito dello sviluppo e della grande crescita delle infrastrutture IT, che costituiscono la base di ogni azienda moderna. Senza i software di gestione automatica delle configurazioni, sarebbe risultato ostico se non impossibile riuscire a gestire in maniera efficace ed efficiente reti costituite da un enorme e sempre crescente numero di macchine. Lo scopo di questo elaborato è stato, quindi, quello di analizzare e far conoscere le piattaforme ed i tools maggiormente utilizzati per la gestione ed il mantenimento di piccole e grandi infrastrutture IT e di rendere il lettore più familiare con una tecnologia che in futuro potrebbe riguardarlo più da vicino ed integrarsi con la sua vita quotidiana. Automatizzazione è stata e sarà ancora per molto la parola chiave dello sviluppo tecnologico che ha visto e che vedrà protagonista la nostra società negli anni a venire. 45 Bibliografia [1] What is Puppet?, http://puppetlabs.com/puppet/what-is-puppet, 18 Giugno 2015 [2] What is DevOps?, http://devops.com/category/features/, 22 Giugno 2015 [3] IBM, http://www.ibm.com/developerworks/devops/index.html, 23 Giugno 2015 [4] Google Cloud, https://cloud.google.com/solutions/google-compute-engine-management-puppet-chef-saltansible, 25 Giugno 2015 [5] SaltStack, http://www.saltstack.com/, 27 Giugno 2015 [6] Ansible, http://www.ansible.com/home, 27 Giugno 2015 [7] Chef, http://www.getchef.com/chef/, 28 Giugno 2015 [8] Puppet 3.8 Reference Manual, http://docs.puppetlabs.com/puppet/3.8/reference/, 2 Luglio 2015 [9] Puppet forge Apache, https://forge.puppetlabs.com/puppetlabs/apache, 14 Luglio 2015 46