Puppet (moduly)

From DCEwiki
Jump to: navigation, search
V kapitole věnované seznámení se strukturou manifestu bylo v odstavci o třídách uvedeno několik ukázkových příkladů vytvoření a implementace třídy. I když třídy mohou být součástí hlavního manifestu, je to z praktického hlediska nesmysl, protože by se stal záhy nepřehledný. Proto se implementace tříd, deklarovaných v hlavním manifestu, udržují odděleně v takzvaných modulech. Puppet má v sobě integrovaný režim pro práci s moduly, proto by každý modul by měl být v maximální míře univerzální, tak aby jej bylo možné distribuovat a sdílet. (Viz Práce s moduly).


  • Specifické manifesty soustřeďte do samostatně udržovaného modulu
  • A parametr, kterým lze na ně odkazovat, předávejte při deklaraci třídy jako její atribut.

Moduly

V deklaraci nodu se třída implementovaná v modulu deklaruje přes direktivu include stejným způsobem, jako kdyby byla součástí výchozího manifestu.

Nenajde-li Puppet v režimu master, který sestavuje katalog, třídu ve výchozím manifestu, předpokládá její výskyt ve stejnojmenném modulu.

Ve té nejprostší podobě tak modul vypadá jako adresář, v úložišti modulů na stroji kde je master, se stejným názvem, jako má použitá třída. Ten obsahuje podadresář manifests se souborem init.pp, ve kterém je deklarovaná.

init.pp

Je výchozí soubor modulu, ve kterém je deklarovaná třída a s implementovanými typy, které se pak budou zpracovávat na straně agenta.

V rámci modulu můžeme tvořit další podtřídy, které lze rovněž deklarovat v souboru init.pp, nebo v dalších souborech v rámci adresáře manifest. Každý z nich musí mít název podtřídy a příponu .pp.

Následující ukázkový kód demonstruje deklaraci třídy "hosts" ve stejnojmenném modulu, která si přes direktivu include natahuje ze souboru s názvem config.pp podtřídu "hosts::config". Před implementací kódu této podtřídy bude aplikován typ file, přes který budeme zakládat na straně agenta soubor /etc/hosts.

Obsah souboru init.pp je tedy prozatím následující:

Poznámka
class hosts {
	file {"/etc/hosts":
		content => template("obsah_pro_hosts"),
	}
	include hosts::config
}

Obsahem dalšího souboru s názvem config.pp bude podtřída modulu "hosts" - "hosts::config", která bude obsahovat typ host, přes který lze spravovat jednotlivé záznamy v souboru /etc/hosts. V ukázkovém příkladu přidává pouze jeden záznam a to nastavení jména pro IP adresu stroje master:

Poznámka
class hosts::config {
	host {"master":
		ip => '147.32.87.200',
		name => 'master',
		comment => "Puppetmaster",
		host_aliases => "master.felk.cvut.cz",
		ensure => present,
	}
}

Podtřídy

V adresáři manifests mohou být další podadresáře. Puppet pak automaticky chápe soubory v nich umístěné jako podtřídy.

Aby bylo možné k nim uvést dokumentaci, je třeba do nich přidat soubor init.pp, a v něm podtřídu deklarovat jako obvykle, nebo lze dokumentaci podtřídy (podadresáře) a její deklaraci umístit do výchozího init.pp celého modulu

Úložiště modulů

Puppet může mít prostřednictvím proměnné $modulepath nastaveno více než jedno úložiště modulů. Na prvním místě je, coby jako výchozí úložiště, adresář modulů příslušného prostředí. Za ním, odděleny dvojtečkou, mohou být uvedeny další cesty. Nepracuje-li agent v odděleném prostředí, jsou moduly obvykle umístěny v adresáři /etc/puppet/modules.

user@stroj~$ sudo puppet agent --configprint modulepath
/etc/puppet/environments/testing/modules:/etc/puppet/modules:/usr/share/puppet/modules

Třídu "basic" z ukázkové deklarace nodu by tedy master postupně hledal v souborech:

  1. /etc/puppet/environments/testing/modules/basic/manifests/init.pp
  2. /etc/puppet/modules/basic/manifests/init.pp
  3. /usr/share/puppet/modules/basic/manifests/init.pp

Pro další proces zpracování manifestu akceptuje master vždy pouze první deklaraci třídy, na kterou narazí.

Pokud ji nikde nenajde, skončí proces generování manifestu chybovým oznámením.

Struktura modulu

Kromě povinného adresáře manifests se mohou v kořeni modulu vyskytnout i další soubory a adresáře. Z hlediska sestavení manifestu jsou významné především tyto:

  • files pro uložení souborů
  • templates pro uložení šablon
  • lib uživatelské pluginy; .rb skripty, které nejsou součástí instalace agenta
  • facts.d spustitelné soubory pro zístávání externích fakt
  • tests pro ilustrační soubory s deklarací tříd a metod implementovaných v modulu
  • spec soubory pro testování pluginů


files

Je adresář ve kterém jsou uloženy soubory a adresáře, které se mají distribuovat tak jak jsou (ssh klíče, výchozí konfigurační soubory aj.). Agent k nim přistupuje přes filebucket v rámci jmenného prostoru příslušného modulu. Není tak nutné si hlídat absolutní cesty v rámci souborového systému stroje master.

Poznámka
 file {"/etc/hosts":
         source => "puppet:///modules/hosts/hosts_default",
 }

templates

Je adresář, do kterého se ukládají šablony. Šablony jsou soubory s příponou .erb, jejichž obsah může být je během zpracování modifikován díky vloženým kouskům interpretovaného kódu programovaného v ruby.

Poznámka
 file {"cesta_k_souboru/soubor.txt":
         content => template("hosts/hosts_sablona.erb",
 }

lib

Pomocí pluginů lze do modulu integrovat funkce, typy a fakta, co nejsou standardní součástí Puppetu. Pluginy jsou soubory, uložené v podadresářové struktuře adresáře lib. Více viz v kapitole Puppet - Fakta a pluginy.

facter

Skripty s příponou .rb v tomto adresáři, dovolují získat a nastavit během zpracování manifestu další fakta se kterými lze pracovat.

augeas

lenses 
Do tohoto adresáře lze umístit parsery konfiguračních souborů (lens), které nejsou standardní součástí instalačního balíku augeas-lenses. Více k augeasu viz kapitola Augeas - nástroj pro práci s konfiguračními nástroji
Poznámka Podpora pro Augeas je od Puppetu verze 2.7.18

puppet

parser/functions 
Sem se umístí skript s příponou .rb, který umožní přidat další funkci využitelnou při zpracování manifestu.
provider/<type> 
Skripty s příponou .rb, které dovolí rozšířit možnosti některého ze stávajících typů, jsou umístěny do podadresářů, s názvem odpovédajícího typu. Kupř. soubor lib/puppet/provider/package/source.rb bude obsahovat kód, kterým lze přidat další parametry k typu package
type 
Lze také ke stávajícím typům přidat další typ, skriptem s příponou .rb umístěným sem.

facts.d

Do tohoto adresáře lze umístit skripty a binární soubory, jejichž výstupem lze nastavit další využitelná fakta. Pozor, tyto soubory musí být spustitelné agentem!.

tests

spec

Dokumentování modulů

Dokumentace ke třídám a metodám v modulu se tvoří úplně stejným způsobem, jako když se dokumentuje kód manifestu.

Kromě podrobné dokumentace jednotlivých metod a tříd však můžeme mít zpracovanou také globální dokumentaci modulu v souboru README. Ten se umisťuje do kořene modulu a může mít případně také příponu .rdoc, nebo .md podle použité formátovací konvence.

README

Soubor README se nachází v kořeni modulu a pokud nemá příponu .rdoc, nebo .md, která by specifikovala použitou formátovací konvence, tak se předpokládá, že je obsah formátovaný pomocí rdoc. Při generování dokumentace do HTML se jeho obsah sloučí s dokumentací veřejných metod, které jsou dokumentovány v kódu, takže lze na ně odkazovat skrze hyperlinky[1].

README.rdoc 
musí mít obsah formátovaný jako rdoc, stejně jako dokumentace v kódu. Pouze s tím rozdílem, že nejde interpretované komentáře, tudíž řádky nezačínají znakem #
README.md 
musí mít obsah formátovaný jako markdown. V tomto případě však vygenerovaná dokumentace nebude zkombinována s dokumentací k veřejným metodám.

Práce s moduly

Jak už bylo zmíněno hned v úvodu této kapitoly, kód v modulech by měl být v maximální míře obecný a univerzálně použitelný. Napsat takový modul však není nic jednoduchého. Proto firma Puppet Labs, která vývoj Puppetu zaštiťuje, od verze 2.7.10 nabízí jeho uživatelům možnost vytvořené moduly sdílet prostřednictvím úložiště na serveru Puppet Forge.

Nástroj pro práci s moduly, který umí také pracovat s tímto úložištěm, je v Puppetu integrován. takže vyhledávat vhodné moduly a instalovat je do lokálního úložiště modulů lze rovnou z příkazové řádky.

Vyhledání a instalace modulu z úložiště na Puppet Forge

Dříve, než začneme psát vlastní modul bychom se tedy měli poohlédnout, zda-li již pro to co potřebujeme někdo nějaký modul nevytvořil.

Následující příklad demonstruje vyhledání modulu pro instalaci a konfiguraci poštovního serveru exim4

Poznámka
root@master~# puppet module search exim
Notice: Searching https://forgeapi.puppetlabs.com ...
NAME                DESCRIPTION                     AUTHOR        KEYWORDS      
example42-exim      Puppet module for exim          @example42    exim mail     
joejulian-exim      Manages Exim                    @joejulian    CentOS exim   
akumria-nullmailer  Install and configure nullm...  @akumria      mail mta exim

Pokud se rozhodneme vyzkoušet kupř. modul od uživatele example42, nainstalujeme do svého lokálního úložiště modulů modul example42-exim. Instalace modulu není v podstatě nic jiného, než stažení zabaleného archívu z webu a jeho rozbalení do úložiště modulů /etc/puppet/modules příslušného prostředí.

Poznámka
root@master~# puppet module install -i /etc/puppet/modules --verbose example42-exim
Notice: Preparing to install into /etc/puppet/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Info: Resolving dependencies ...
Info: Preparing to install ...
Notice: Installing -- do not interrupt ...
/etc/puppet/modules
└─┬ example42-exim (v2.0.13)
  └── example42-puppi (v2.1.9)

Distribuce vlastního modulu

Vytvořit vlastní instalační balíček modulu není nic těžkého.

V podstatě stačí do kořene modulu doplnit soubor metadata.json, ve kterém jsou uloženy základní informace o modulu:

  • jak se jmenuje
  • kdo ho vytvořil
  • jaké má číslo verze
  • co vlastně obsahuje
  • a případně na jakých dalších modulech závisí
Poznámka Starší verze Puppetu místo něj používaly soubor s názvem Modulefile

Modulefile

metadata.json

Soubor s informacemi o modulu pro práci s moduly v rámci Puppetu (viz níže).

Zabalení modulu

Poznámka
root@master~# puppet module build /etc/puppet/modules/admins
Notice: Building /etc/puppet/modules/admins for release
Module built: /etc/puppet/modules/admins/pkg/want-admins-0.1.1.tar.gz

Instalace modulu z lokálního tarballu

Instalaci z lokálního tarballu je třeba provádět s parametrem --ignore-dependencies, protože pokud by ve svých závislostech odkazoval na modul který není součástí Puppet Forge, skončila by instalace oznámením, že balík nelze nainstalovat pro nesplněné závislosti.

Poznámka
root@master~# puppet module install --environment testing ~/want-admins-0.1.1.tar.gz --ignore-dependencies --force
Notice: Preparing to install into /etc/puppet/environments/testing/modules ...
Notice: Installing -- do not interrupt ...
/etc/puppet/environments/testing/modules
└── want-admins (v0.1.1)

Bez parametru --force lze modul instalovat pouze pokud neexistuje.

Poznámka
root@master~# puppet module install --environment testing ~/want-admins-0.1.1.tar.gz --ignore-dependencies
Notice: Preparing to install into /etc/puppet/environments/testing/modules ...
Error: Could not install module 'want-admins' (v0.1.1)
  Installation would overwrite /etc/puppet/environments/testing/modules/admins
    Use `puppet module install --force` to install this module anyway

S parametrem --force instalace z balíku nahradí stávající obsah modulu.

Přehled nainstalovaných modulů

K výpisu modulů se používá příkaz list. To postačí, pokud se nepoužívá jiné než výchozí prostředí. Jinak se musí atributem --environment upřesnit výchozí prostředí.

Poznámka
root@master~# puppet module list --environment testing
/etc/puppet/environments/testing/modules
├── apache2 (???)
...
└── want-vim (v0.1.0)
/etc/puppet/modules
├── puppetlabs-apt (v1.2.0)
...

Z následujícího ukázkového výpisu modulů lze vyčíst že..

  • Modul apache2 zatím není nijak podchycen, protože mu chybí číslo verze (chybí soubor metadata.json. Podle tohoto čísla se udržuje přehled o závislostech modulů, proto při každé úpravě modulu, která může mít vliv na jeho implementaci vy mělo být číslo verze navýšeno.
  • Modul want-vim, je již upraven zcela v souladu s pravidly. Je to lokálně nainstalovaný modul, u kterého bylo výchozí číslo verze v0.1.0 bylo navýšeno po drobné úpravě
  • Modul puppetlabs-apt je ale instalován z repozitáře Puppet Forge. Vyskytne-li se v takovém modulu nějaká chyba, měl by být především informován tvůrce modulu (v tomto případě puppetlabs), aby se mohl postarat o nápravu. Vydá-li pak aktualizovanou verzi modulu, je třeba provést aktualizaci.

Aktualizace modulu

K aktualizaci modulů se používá příkaz upgrade

Poznámka
root@master~# puppet module upgrade --environment testing puppetlabs-apt --modulepath /etc/puppet/modules
Notice: Preparing to upgrade 'puppetlabs-apt' ...
Notice: Found 'puppetlabs-apt' (v1.2.0) in /etc/puppet/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Upgrading -- do not interrupt ...
/etc/puppet/modules
└── puppetlabs-apt (v1.2.0 -> v1.5.0)
Upozornění Pokud je modul nainstalován do jiné cesty, než která přísluší prostředí - stejně jako v tomto ukázkovém případě - skončí aktualizace cbybou. U takového modulu musí být uvedeno prostřednictvím atributu --modulepath, ve které lokaci se zdrojové kódy modulu skutečně nalézají.

Odebrání modulu

Vygenerování struktury modulu

git (PUPPET) :~# puppet module generate --environment production want-lvm2
We need to create a metadata.json file for this module.  Please answer the
following questions; if the question is not applicable to this module, feel free
to leave it blank.

Puppet uses Semantic Versioning (semver.org) to version modules.
What version is this module?  [0.1.0]
--> 

Who wrote this module?  [want]
--> 

What license does this module code fall under?  [Apache 2.0]
--> GPLv3

How would you describe this module in a single sentence?
--> Konfigurace LVM volumes

Where is this module's source code repository?
--> 

Where can others go to learn more about this module?
--> 

Where can others go to file issues about this module?
--> 

----------------------------------------
{
  "name": "want-lvm2",
  "version": "0.1.0",
  "author": "want",
  "summary": "Konfigurace LVM volumes",
  "license": "GPLv3",
  "source": "",
  "project_page": null,
  "issues_url": null,
  "dependencies": [
    {"name":"puppetlabs-stdlib","version_requirement":">= 1.0.0"}
  ]
}
----------------------------------------

About to generate this metadata; continue? [n/Y]
--> y

Notice: Generating module at /root/want-lvm2...
Notice: Populating templates...
Finished; module generated in want-lvm2.
want-lvm2/manifests
want-lvm2/manifests/init.pp
want-lvm2/spec
want-lvm2/spec/classes
want-lvm2/spec/classes/init_spec.rb
want-lvm2/spec/spec_helper.rb
want-lvm2/tests
want-lvm2/tests/init.pp
want-lvm2/Gemfile
want-lvm2/Rakefile
want-lvm2/README.md
want-lvm2/metadata.json
  1. To ovšem neplatí pokud budou použity k formátování dokumentace značky pro Markdown (soubor README.md)