Puppet (manifest)

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání

U Debianu je bezprostředně po instalaci adresář /etc/puppet/manifests prázdný a skript pro sestavení manifestu je nutno teprve vytvořit.

Vytvoření manifestu

Manifest je soubor, který sestaví master na straně centrálního úložiště a výsledný dokument předá k lokálnímu zpracování agentu na straně klienta.

Jeho sestavení začíná souborem manifests/site.pp příslušného prostředí, ve kterém master hledá na základě požadavku agenta výchozí nastavení nodu podle jeho hostname.

V podstatě by bylo možné celý kód potřebný pro sestavení manifestu sem, ale takový skript by se záhy stal nepřehledný. Proto se využívají moduly a parametrizované třídy.

Upozornění Kód pro potředný pro sestavení manifestu, rozdělený do více souborů, se pak do výchozímu manifestu vkládal přes direktivu import, ovšem tato direktiva patří od verze 3.6 mezi nepodporované!

Proměnné

Soubor site.pp je ideálním místem pro umístění globálních proměnných. Každá proměnná existuje pouze v rámci svého jmenného prostoru, který se označuje jako scope. Pokud Puppet během zpracování manifestu v aktuálním jmenném prostoru nenajde, prohledá scope nejvyšší úrovně, kterým je výchozí soubor site.pp.

Promměné z jiných scope lze volat pouze jejich plným jménem, které tvoří jméno příslušného jmenného prostoru 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 '$::'
Upozornění V rámci scope lze proměnné přiřadit hodnotu pouze jedenkrát. Tzn. že globální proměnné, které již hodnotu mají, nelze přenastavit.

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

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

Z příkladu je zřejmé, že kromě direktivy import, která bude do manifestu integrovat obsah souboru nodes.pp je nastavena také proměnná $puppetserver, ve které je uloženo doménové jméno stroje master, na kterém běží démon 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. V šablonách, které se interpretují až na straně klienta však s nimi lze pracovat stejně jako s proměnnými, což 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řída definuje, jak mají věci v ní popsané na klientském nodu vypadat. Za tímto účelem v sobě obsahuje 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, š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ů

Na názvech importovaných souborů vcelku nezáleží. Důležité je, aby aby měly příponu ".pp". Soubor nodes.pp z našeho příkladu obsahuje seznam nodů, které mají být přes Puppet spravovány.

Direktivou node jsou v něm přiřazeny k sadě instrukcí, která se má použít pro sestavení manifestu ověřovací identifikátory, podle kterých se ověřuje doménoví jméno, pod kterým se ohlásil agent.

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.

Viz příklad obsahu výchozího souboru /etc/puppet/manifests/nodes.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.

Upozornění Bude-li v manifestu nakonfigurováno více nodů, který by vyhověl identifikátor agenta, pak Puppet pro sestavení manifestu použije ten, kterému jméno agenta vyhoví nejdřív.

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 si ji v případě potřeby kdykoliv vypsat, nebo vygenerovat do souboru, rovnou na příkazové řádce.

Dokumentaci k 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ý je umístěn v kořenovém adresáři modulu.
  • Dokumentace ke třídám (class), uživatelským typům (define) a nódům (node) je vždy umístěna bezprostředně před dokumentovaným kódem a (na rozdíl od souboru README) jako součást komentářů přímo ve skriptech. Při generování dokumentace se sloučí všechny informace k modulu (dokumentace z kódu a obsah souboru README) do jednoho dokumentu.

Pro formátování textu dokumentace se používá Markdown - systém jednoduchých formátovacích značek, který je při generování dokumentace interpretován na HTML kód.

puppet doc convetion.svg

Markdown syntaxe