Puppet (manifest)

Z DCEwiki
Verze z 28. 4. 2015, 13:52, kterou vytvořil Keny (diskuse | příspěvky) (→‎Syntaxe)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)
Skočit na navigaci Skočit na vyhledávání
puppet apply.svg

Cílem Puppetu je - udržovat systémové zdroje nodu tak aby konfigurace stroje odpovídala definovanému stavu.

To, v jakém stavu se mají tyto zdroje nacházet je deklarováno, v souborech s příponou .pp, které se nazývají manifesty a popisují jaký má být jejich cílový stav.

Je-li puppet zavolán v módu apply, sestaví z manifestu předaného na příkazové řádce katalog, který pak postupně prochází a přitom kontroluje, zda skutečný stav zdrojů odpovídá tomu deklarovanému.

Pokud ne, tak se ho pokusí uvést do stavu odpovídajícího deklaraci. Tak postupně zpracovává celý katalog, dokud systém neodpovídá definovanému stavu.

Agent/Master

V puppet v režimu agent funguje podobně, ovšem s tím rozdílem, že sestavení katalogu probíhá na straně centrálního úložiště manifestů, kde běží v režimu master.

Agent, který odeslal žádost o katalog na stroj Master, obdrží sestavený katalog a postupně ho kontroluje, tak jako v režimu 'apply. Hlášení o průběhu a výsledku zpracování pak odesílá na Master, který je pak případně distribuuje dále přes e-mail.

puppet agent.svg

Vytvoření manifestu

Manifesty se nazývají soubory, ze kterých se sestavuje katalog, podle kterého pak Puppet kontroluje a nastavuje zdroje tak, aby odpovídaly definovanému stavu systému.

Toto sestavení začíná výchozím manifestem site.pp, který Puppet - pokud nepoužívá jiné prostředí (environment) - hledá v adresáři /etc/puppet/manifests. Ten je bezprostředně po instalaci prázdný a soubor site.pp je nutno vytvořit.

site.pp
By měl obsahovat kód, který bude pro všechny nody společný.

Proměnné

Proměnné jsou objekty, které musí být v rámci jmenného prostoru příslušné třídy (scope) vždy unikátní. Není tedy možné v rámci jednoho scope jejich obsah operativně měnit. Lze je pouze - na základě zpracování kódu v manifestu - nastavit.


Takto deklarovanou proměnnou však lze využívat v nejrůznějších podmínkách, atp. Soubor site.pp je ideálním místem pro nastavení globálních proměnných proto, že pokud Puppet nenajde během zpracování manifestu deklarovaný objekt v rámci jeho jmenného prostoru, prohledává scope manifestu nejvyšší úrovně, kterým je výchozí soubor site.pp.

Proměnné deklarované v jiných třídách lze pochopitelně rovněž používat, musí ale být vždy deklarovány svým plným jménem, které tvoří jméno příslušného jmenného prostoru (třídy) a název proměnné.

$<jmenný prostor proměnné>::<proměnná>
  • Jméno proměnné začíná vždy znakem '$' (znak DOLLAR)
  • K přiřazení hodnoty se používá operátor = (znak "rovná se..").
  • Proměnná může obsahovat řetězec, číslo, pravdivostní hodnotu (false, undef,..), pole nebo kontrolní součet.
  • Proměnnou lze předat jako hodnotu parametru, ale také se dá použít jako jméno zdroje. Zdrojem se rozumí soubor operací, uzavřený ve složených závorkách { }.
  • Proměnné se dají vkládat do řetězců, které musí být uzavřené do uvozovek (znak ").
  • Proměnná, které nebyla přiřazen žádná hodnota vrací řetězec undef
Poznámka Některé verze puppetu mají bug, které při volání globálních proměnných a vyžadují při jejich volání prefix '$::'

Příklad obsahu výchozího souboru /etc/puppet/manifests/site.pp

Poznámka
$puppetserver = 'master.felk.cvut.cz'

V příkladu je nastavena proměnná $puppetserver, která obsahuje doménové jméno stroje, na kterém běží Puppet jako démon v režimu master (nainstalovaný z balíku puppetmaster)

Fakta

Při psaní manifestu lze používat pouze proměnné, ale pro šablony je dostupný ještě jeden zdroj informací - fakta

Fakta jsou informace dostupné pouze na straně klienta, proto se nedají použít při psaní manifestu. Ale lze s nimi pracovat v šablonách, které se budou interpretovat až na straně klienta. To umožňuje generovat konfigurační soubory přímo na míru stroje.


Jaká fakta jsou na nodu dostupná, lze zjistit utilitou facter.

Třídy

Kromě nastavení nodů obsahuje soubor nodes.pp z našeho příkladu také definici společné třídy basic, která bude aplikována na všechny nody, které si ji přes direktivu include natáhnou.

Třídy deklarují, jak mají zdroje v nich popsané na klientském nodu vypadat. Za tímto účelem v sobě obsahují vše potřebné pro realizaci manifestu.


Operace, které jsou nezbytné pro to aby klient odpovídal třídě, se realizují přes tzv. typy. V rámci třídy lze využívat také nejrůznější stavové podmínky, proměnné, integrované funkce, metody, šablony, definice závislostí a třídy z dalších modulů. Viz ukázka použití třídy subclass z modulu modul v rámci třídy basic:

Poznámka
class basic {
      include modul::subclass
    }
Parametrizované třídy

Od verze 2.6.x lze při volání tříd používat parametry. Aplikace takové parametrizované třídy vypadá podobně, jako použití typu, liší se však tím, že její opakované použití na různých místech manifestu nevyvolá chybu. Třída se totiž sama o sobě stará pouze o to aby příslušné věci v systému vypadaly tak jak mají.

Poznámka
class basic ( $editor = 'vim' ){
      if $editor {
         package { "$package":
            ensure => install,
         }
      }
    }

Použití třídy

Použití třídy spočívá v její deklaraci. Tu lze provést několika způsoby, ale vždy pouze jednou. Je-li stejná třída deklarovaná také na jiném místě manifestu, tak už to nemá žádný vliv - nicméně agent proces jeho zpracování neukončí chybou.

Nejčastěji se provádí deklarace prostřednictvím funkce include, jak bylo uvedeno kupř. ve výše umístěném příkladu. Prostřednictvím této funkce lze deklarovat i několik tříd najednou. Jejich názvy přitom musí být odděleny čárkou. Viz příklad.

Poznámka
     include basic, apache, mysql

Od verze 2.5.x lze třídy deklarovat také pomocí funkce require. Ta se využívá především tam, kde je třeba ošetřit závislosti. Kupř. v následujícím příkladu se provede deklarace třídy apache, ještě před zpracováním obsahu definovaného typu apache::vhost, protože konfiguraci virtuálního serveru nelze provést dokud není nainstalován webový server apache.

Poznámka
define apache::vhost ( $port, $docroot, $servername, $vhost_name ){
      require apache
      ...
    }
Upozornění Pozor! Funkce require, která provádí deklaraci třídy, není totéž co metaparametr require, který se používá pro nastavení závislostí

Pro nastavení vzájemných závislostí má Puppet mechanismus, který umožnuje docílit stejného efektu, jako při deklaraci přes funkci require také s využitím funkce include:

define apache::vhost ( $port, $docroot, $servername, $vhost_name ){
      include apache
      Class['apache'] -> Apache::Vhost[$title]
      ...
    }
Použití parametrizované třídy

Bohužel ani jedna z dosud uvedených funkcí neumožňuje deklarovat třídu s použitím parametrů. Jak už bylo zmíněno, parametrizované třídy lze používat od verze 2.6.x a k jejich deklaraci se používá speciální typ class. I když lze pochopitelně parametrizovanou třídu deklarovat také obvyklým způsobem, pokud má být ve výchozím nastavení.

Deklaraci parametrizované třídy basic (viz výše uvedený příklad parametrizované třídy) lze provést tímto způsobem:

Poznámka
class { 'basic':
      editor => 'nano',
    }

V takovém případě by byl v rámci této třídy nainstalován textový editor nano a nikoliv vim, jak by tomu bylo, kdyby byla třída deklarována bez parametru.

Poznámka
class { 'basic': }
Upozornění Pozor! Jakmile je třída jednou deklarovaná, nelze ji deklarovat v rámci aktuálního jmenného prostoru znovu, byť s jiným parametrem!

Nastavení nodu a použití regulárních výrazů

Kromě obecných zdrojů může výchozí manifest obsahovat také deklarace nodů, které mají být přes Puppet spravovány.

Direktiva node vymezuje v deklaraci manifestu blok kódu, který se má použít pro sestavení katalogu pouze pokud jeho identifikátor vyhoví jménu, kterým se ohlásil agent.

Upozornění Bude-li v manifestu nakonfigurováno více nodů, který by mohlo vyhovět jméno agenta, pak Puppet pro sestavení manifestu použije ten, kterému jméno agenta vyhoví nejdřív.
Poznámka Jelikož veškerá komunikace probíhá přes SSL, musí být na stroji master certifikát, který si vyžádal agent nejprve ověřen. Bez něj by totiž master s agentem vůbec nekomunikoval. Identifikátor (doménové jméno stroje ze kterého se agent ohlásil) je součástí tohoto ověřeného certifikátu.

Jako identikátor se může použít celé doménové jméno, ale stačí i jeho zkrácená verze. Pokud identifikátor SSL certifikátu, kterým se agent autorizuje vůči stroji master vyhoví nastavenému řetězeci, pak budou nastavené operace použity při sestavení jeho manifestu.

Příklad deklarace nodu ve výchozím manifestu /etc/puppet/manifests/site.pp :

Poznámka
 #
 # NODE CONFIGURATION
 #
 class basic {
 	}
 node 'master.felk.cvut.cz' {
 	include basic
 	}

Má-li být definice nodu společná více strojům, lze provést přiřazení buď jejich vyjmenováním..

Poznámka
    node 'www.felk.cvut.cz', 'www2.felk.cvut.cz', 'www3.testing.com' {
      include basic
    }

..nebo nastavením regulárního výrazu. Jako regulární výraz bere master řetězec tehdy, jsou-li místo uvozovek použita lomítka

Poznámka
node /^www\d+$/ {
      include basic
    }

Předchozímu regulárnímu výrazu by vyhověly všechny stroje, jejichž (zkrácené) doménové jméno by začínalo řetězcem www následovaným číselnou hodnotou - bez ohledu na doménu ze které by lezly.

Dá se ale použít i složitější podmínka, která vymezí nod pouze vůči strojům petr a pavel z domény felk.cvut.cz.

Poznámka
node /^(petr|pavel)\.felk\.cvut\.cz$/ {
      include basic
    }
default

Normálně se chová Puppet tak, že agenta, jehož doménové jméno, ať plné, nebo zkrácené, nevyhoví žádnému identifikátoru ignoruje.

Jsou však situace, kdy chceme zpuppetizovat každý stroj, bez ohledu na to jaký identifikátor nod pošle. Pro takový případ je třeba založit v manifestu nod default

Poznámka
node default {
      include basic
    }

Dokumentace kódu

Dokumentace k Puppetu je součástí jeho kódu a lze ji v případě potřeby kdykoliv vypsat na příkazové řádce, nebo do souboru. Dokumentaci k manifestu a vlastním modulům si však musíme průběžně psát sami.

  • Popis modulu a informace o tom, jak jej používat, je v souboru README, který se při generování dokumentace hledá v kořenovém adresáři modulu. Je-li nalezen, tak se sloučí dokumentace z kódu a obsah souboru README do jednoho dokumentu, ve jehož rámci lze pak používat pro pohyb v textu hyperlinky.
  • Dokumentace ke třídám (class), uživatelským typům (define) a nódům (node) se vždy umísťuje bezprostředně před dokumentovaný kód a (na rozdíl od souboru README) jako komentář - tj. na řádky které musí začínat mřížkou (#).

Atributy, hodnoty a parametry

Aby byla dokumentace konzistentní, je třeba pokud možno dodržovat jednotnou terminologii. Deklarace zdrojů a parametrizovaných tříd, aj. se vždy skládá z typu a názvu.

Rozdíl je v tom, že zatím co při deklaraci typů a parametrizovaných tříd hovoříme o jejich atributech', u deklarace proměnných a jejich hodnot u metod a implementace tříd hovoříme o parametrech.

puppet doc convetion.svg

Syntaxe

Pro formátování textu integrované dokumentace se používá systém formátovacích značek, které jsou při generování dokumentace interpretovány na HTML kód. Puppet umí zpracovávat dvě formátovací konvence, které se však od sebe vzájemně dost liší:

rdoc
je značkovací systém podobný syntaxi mediawiki, který lze použít k dokumentaci deklarativního kódu v manifestech
markdown
je značkovací systém, který se používá k dokumentaci interního kódu Puppetu, psaného v ruby. k dokumentaci kódu manifestů jej nelze použít!
Poznámka Existuje-li v modulu, soubor README (resp. README.rdoc) bude jeho obsah sloučen s dokumentací k metodám v modulu do jedné stránky. Lze pak na ně odkazovat z jiných stránek dokumentace přes hyperlinky.

README lze formátovat i v markdownu, ovšem pak musí mít tento soubor příponu .md. To platí pro všechny soubory, které používají markdown. U všech ostatních Puppet automaticky předpokládá rdoc. Obsah README.md však nebude integrován s dokumentací metod, neboť v kódu manifestu Puppet akceptuje pouze rdoc a formátovací syntaxi není možné mixovat.

rdoc - zvýraznění textu

Ke zvýraznění textových řetězců se používají následující značky:

* : hvězdička pro ztučnění
_ : podtržítko pro kurzívu
+ : plus pro zvýrazněný strojopis

Řetězec *bold* se tak ve vygenerované dokumentaci objeví jako bold

Upozornění Puppet používá tzv simple rdoc, který má svá specifika. Mezeru chápe jako oddělovač a tak řetězec *bold text* se tak i ve vygenerované dokumentaci objeví jako *bold text*.

Tedy pokud má být zvýraněn textový řetězec který mezery obsahuje, musí být uzavřeno mezi značkami každé slovo zvlášť: *bold* *text*

Bohužel je problém také s interpretací značek pro zvýraznění u řetězců které obsahují diakritiku (bug?), dvojtečku nebo čárku. Tečku, pomlčku nebo lomenou závorku parser zkousne.

rdoc - sekce

Sekce se tak jako u mediawiki oddělují jejich nadpisy, ovšem s tím rozdílem, že formátovací značka není v tomto případě párová

Poznámka
= První úroveň
== Druhá úrověň
=== Třetí úroveň
...
  • Nadpis každé stránky je vždy první úrovně, proto sekce v dokumentaci kódu manifestu by měly začínat od druhé úrovně
  • Z vizuálního hlediska nemá smysl používat víc jak pět úrovní (interpretace nadpisu šesté úrovně se od nadpisu páté úrovně vizuálně neliší)

rdoc - seznamy

Pro vytvoření seznamu používá:

* nebo - : hvězdička nebo pomlčka na začátku řádku pro vytvoření odrážky
1. : Číslo následované tečkou na začátku řádku pro vytvoření číslovaného seznamu
Upozornění Číslované seznamy nelze přerušovat, ani vnořovat. Také jim nelze určit od jaké hodnoty má číslování začít

rdoc - odsazení bloku

Odsazení bloku textu udělají dvě dvojtečky (::).

Upozornění Odsazení textu nelze kombinovat s ukázkami kódu

rdoc - ukázkový kód

Ukázkový kód generuje parser z řádků které začínají minimálně dvěmi mezerami

Upozornění Aby byl kód interpretován jako ukázka kódu, tak mu nesmí předcházet odsazení, nebo popiska bez obsahu. A předchozí blok textu musí být ukončen prázdným řádkem

rdoc - popiska

Popiska se používá kupř. při popisu jednotlivých parametrů či argumentů metod a tříd

Poznámka
[$parametr]
Popis parametru

Je interpretováno jako:

$parametr
Popis parametru

rdoc - hyperlinky

Hyperlinky se generují z řetězců uzavřených do hranatých závorek, který musí předcházet řetězec, který bude interpretován jako odkaz.

Poznámka
Internetový odkaz[url://]

Má-li být vytvořen odkaz z víceslovného řetězce, pak musí být tento řetězec uzavřen do složených závorek

Poznámka
{Internetový odkaz}[url://]

Parser při generování dokumentace do HTML vytváří následující stromovou strukturu

Poznámka
modul.html              # Sloučen obsah souboru README a dokumentace metod modulu modul
modul/modul.html        # Dokumentace k výchozí třídě modulu - modul
modul/modul/class.html  # Dokumentace ke třídě class v modulu modul

Na metody ve výchozím souboru modul.html lze odkazovat pomocí kotev, které mají pevně danou syntaxi. Kotva má k názvu modulu vždy přiřazen řetězec modulmethod-i-

Poznámka
Hyperlinkový odkaz na metodu metoda[#method-i-metoda] v rámci souboru README modulu modul
Poznámka
Hyperlinkový odkaz na metodu metoda[../modul.html#method-i-metoda] z dokumentace k některé třídě či podtřídě modulu modul

Odkazovat lze také na třídy a podtřídy jiných modulů. Viz příklad hyperlinkový odkaz na třídu class v modulu modul z dokumentace k některé třídě či podtřídě v jiném modulu

Poznámka
Link a třídu class[../modul/class.html]

Nebo ukázkový příklad odkazu na podtřídu modul::class::subclass v modulu modul z dokumentace k některému jinému modulu, třídě či podtřídě.

Poznámka
Link na podtřídu modul::class::subclass[../modul/class/subclass.html]
Poznámka U hyperlinků na třídy a podtřídy není nutné řetězec uzavírat do složených závorek, protože dvojtečka není (na rozdíl od mezery) chápána jako odddělovač
Upozornění Dejte si pozor u hyperlinků v dokumentaci nodů. Tam totiž záleží, jesti používáte jeden hlavní manifest site.pp, nebo jestli máte konfiguraci nodů rozdělenou do souborů v adresáři site.pp/. V tom prvním případě stačí u relativní cesty vyskočit pouze o jednu úroveň, kdežto v tom druhém o dvě! Takto: $basic::setwpd[../../basic.html#method-i-setpwd]


rdoc - include

Tato funkcionalita se hodí například pro oddělení kódu, který se stereotypně opakuje v dokumentaci tříd a metod - typicky info o copyrightu. Následující ukázkový kód demonstruje vložení obsahu (formátovaného v rdoc) ze souboru copyright

Poznámka
:include:copyright

Parser ho postupně hledá na několika místech:

  1. Nejprve tam co je dokumentovaný manifest
  2. A potom v kořeni adresáře s konfigurací - Pozor! Nemusí vždy fungovat! V takovém případě lze vyřešit problém pomocí symlinku

Můžeme tedy na tento soubor odkazovat i z jiných modulů nastavením cesty

Poznámka
:include:modules/admins/copyright

V tomto případě natáhne obsah souboru copyright umístěného k kořenovém adresáři modulu admins

Poznámka Stejně jako u souboru README je vkládaný kód obsahem souboru. Můžeme také vkládat obsah jiných manifestů, pak ale musí být vkládaný text ve formě komentáře. Pokud parser dokument nenajde, nevloží nic.