Konfiguráció menedzsment eszközök

A Unix/Linux szerverek üzemeltetése wikiből
(Konfiguráció menedzsment szócikkből átirányítva)

Előre felhívom a figyelmet, hogy ez a szócikk nem elegendő a benne felsorolt eszközök használatának elsajátítására. Arra viszont remélem, elegendő lesz, hogy kiindulópontot nyújtson az ezek használatáról való döntéshez.

Tartalomjegyzék

1 A probléma

Van n db. számítógép, amik nagyon hasonló feladatot látnak el, így nagyon hasonlóan is kellene őket adminisztrálni. Külön adminisztrálni mindegyiket kényelmetlen, és meglehetősen nagy káoszhoz vezetne.

2 A naiv hozzáállás

Az ötlet hihetetlenül egyszerű. Összeállítunk egy shellscriptet, ami elvégzi a gépen a szükséges módosításokat, összecsomagoljuk a számára szükséges fájlokkal, majd az adminisztrálni kívánt gépekre valahogyan eljuttatjuk a csomagot, és lefuttatjuk rajtuk a shellscriptet. Ezt pl. egy cron job segítségével automatizálni is lehet valamennyire. Az ötlettel azonban van néhány probléma. Mi van pl., ha néhány gépen sikeresen lefut az így összeállított shell script, néhányon pedig nem? Mi van, ha néhányon véletlen többször is lefut? A központilag adminisztrálni próbált gépek konfigurációja ez által el fog térni egymástól, és így megnehezítettük a saját dolgunkat. Arról nem is beszélve, hogy az ilyen céllal összedobott shellscriptek könnyen elérhetik az átláthatatlanság, és ezáltal a karbantarthatatlanság határát.

3 cfengine

A cfengine egy eszközcsomag önálló, vagy hálózatba kapcsolt számítógépek adminisztrációjára. Az első verziója 1993-ban jelent meg. Jelenlegi verziójának "Community Edition" változata GPLv3 licensz alatt terjed. A 3-as verzió által használt nyelv nem kompatibilis a 2-es verzió nyelvével, de a 2-es verziót használó rendszerek probléma nélkül migrálhatóak 3-as verzióra. Az eszköz működése úgynevezett ígéreteken alapul, melyekhez tartani igyekszik magát a rendszer. Nem garantálható, hogy ezek minden időpillanatban teljesüljenek, az azonban igen, hogy a rendszer tartson az ezekben meghatározott állapothoz. A fejlesztés alapötlete az, hogy nem az fontos, hogy milyen változtatásokat végzünk a rendszeren, hanem az, hogy milyen elvárásokat kell teljesítsen a rendszer.

3.1 Komponensek

  • cf-agent - A rendszer állapotára vonatkozó ígéretek betartásával foglalkozik. Működését a common és az agent köteg befolyásolja.
  • cf-execd - A cf-agent rendszeres futtatását végzi. Működését a common és az executor köteg befolyásolja.
  • cf-know - Tudásmodellező ágens. Tulajdonképpen dokumentációt generál a rendszerről. Működését a common és a knowledge köteg befolyásolja.
  • cf-monitord - Passzív monitorozó ágens. Információt gyűjt a rendszer állapotáról. Működését a common és a monitor köteg befolyásolja.
  • cf-promises - Ígéret validátor. Ígéretek szintaxisát lehet vele ellenőrizni.
  • cf-runagent - cf-agent távoli gépen való elindítását lehet vele kérni.
  • cf-serverd - Feladata az elvek és adatok terjesztése a kliensek felé. A cf-agent kéréseire reagál. Működését a common és a server köteg befolyásolja.
  • cf-report - A cfengine által tárolt adatokat ember által olvasható formára hozza. Működését a common és a reporter köteg befolyásolja.
  • cf-key - Nyilvános - privát kulcspárokat lehet vele generálni a cfengine számára.
  • cf-hub - A kereskedelmi változat része. Itt nem foglalkozom vele.

3.2 Fogalmak

  • Ígéret - Nyilatkozat a fenntartandó állapotról.
  • Ígéretköteg - Ígéretekből álló köteg.
  • Ígérettest - Az ígéretnek annak részleteit kifejtő része.
  • Adattípusok - Skalár: sztring, egész, vagy valós szám.
  • Változó - Balérték - jobbérték összerendelés. A jobbérték skalár, vagy skalárokból álló lista.
  • Függvény - Beépített, paraméterezhető jobbérték.
  • Osztály - A cfengine kontextust leíró megoldása. Rá alapozva lehet döntéseket hozni.

3.3 Szintaxis

  • Az azonosítók az alábbi karakterekből állnak: ('a-zA-Z0-9_')
  • Minden adat idézőjelek között kell szerepeljen.
  • Az ígéretkötegek az alábbi formájúak:
bundle ágens-típus azonosító
{
 ...
}
  • A sablonok az alábbi formájúak:
body ígéret_típus sablon_azonosító
{
...
}
  • Az ígéretek testét alkotó 'ígéret kifejezések' az alábbi alakúak lehetnek:
balérték => sablon(paraméterek)
balérték => sablon
balérték => függvény()
balérték => "Idézőjelek közé zárt skalár"
balérték => { Lista }

3.4 A munkakönyvtár

/var/cfengine
/var/cfengine/bin
/var/cfengine/inputs
/var/cfengine/outputs

3.5 Osztályok

Amikor a cfengine egy komponense megkezdi futását, felderíti, milyen osztályokba sorolható a gép, amin fut. Ilyen osztályok adódnak az operációs rendszer fajtájából, a domain névből, a dátumból, az aktív interfészek neveiből és IP-címeiből, és felhasználó által definiált jellemzőkből. Az, hogy milyen osztályokba tartozik egy gép, kideríthető az alábbi paranccsal:

cf-promises -v

3.6 Globális és lokális osztályok

Példa globális osztálydefinícióra:

bundle common g
{
classes:
  "one" expression => "any";
}

Példa lokális osztálydefinícióra:

bundle agent osztaly_1
{
classes:
  "two" expression => "any";
}

A lokális osztályok csak abban a kötegben érvényesek, amelyikben definiálva vannak.

3.7 Ígéretek alakja

típus:
    osztályok::
        "ígéretet tevő objektum" -> { "objektumok", "melyeknek érdeke", "az ígéret" }
            attribútum1 => érték1
            attribútum2 => érték2

Ezen elemek nem mindegyike szükséges mindig. Azon objektumok listája, melyeknek érdeke az adott ígéret, csak dokumentációs célokat szolgál. Ha az ígéret minden osztályra vonatkozik, nem kell osztályokat felsorolni. Attribútumok sem kellenek minden esetben, mivel többnyire van alapértelmezett értékük.

3.8 Kötegek

A cfengine lehetővé teszi ígéretek kötegekbe csoportosítását. A köteg típusa annak a komponensnek a neve, melynek szánva van.

3.9 Sablonok

A sablonok célja, hogy újrahasznosítható formában tartalmazzanak bonyolult paramétereket. Az ilyen sablonok alakja:

body ígérettípus azonosító(paraméterek)
{
attribútum1 => "$(paraméter)";
attribútum2 => "konstans";
osztály::
    attribútum3 => "konstans2";
}

Mint látható, a sablonokban is lehetnek osztályok. Ezek "és" kapcsolatba kerülnek azzal az osztályhalmazzal, mely a hívó ígéret feltétele.

3.10 Változók

A változókhoz a vars ígérettípus alá tartozó ígéretekkel lehet értékeket rendelni.

3.11 Felhasznált irodalom és bővebb dokumentáció

http://www.cfengine.org/manuals/cf3-reference.html

4 Puppet

4.1 Felépítés

A puppet név alapvetően a kliens oldali programot takarja. Szerver oldali párja a puppet-server nevű csomagban található a disztribuciók többségében, és puppetmasterd névre hallgat. Mind a kliens, mind a szerver ruby programnyelven íródott, és GPL licensz alatt érhető el. A fejlesztőktől a két programot egyetlen forráscsomagban tölthetjük le. A szerver a 8140-es TCP porton, SSL titkosított kapcsolaton érhető el. A manifest fájlok a szerver /etc/puppet/manifests/ útvonalán, .pp névvégződésű fájlokban találhatóak. Közülük a nodes.pp az, ami a hostok neve szerint szétválasztva dönti el, mely hostra mely konfigurációs elvárások vonatkoznak. include utasításokkal ebbe további konfigurációs fájlok illeszthetők. Mikor a puppetd elindul, csatlakozik a puppet szerver 8140-es portjára, lekérdezi a rá vonatkozó manifest-et, és a host konfigurációját úgy módosítja, hogy az eleget tegyen a manifest-ben írt elvárásoknak. Ha eleve eleget tesz nekik, akkor természetesen semmit nem tesz. A módosításokról aztán jelentést küldhet a kliens a szerver felé, majd ugyanezt alapértelmezés szerint fél óránként újra megteszi.

4.2 Manifest példa

nodes.pp

node bootszerver {
    include tftp
}

tftp.pp

class tftp {
    package { "tftpd":
        ensure => installed,
        ensure => latest
    }
    package { "xinetd":
        ensure => installed,
        ensure => latest
    }
    yumrepo { "sajat":
        baseurl => "http://repo.sajatdomain/yumrepo",
        descr => "Sajat yum repository-m, melyben a tftpboot-konyvtar csomag talalhato.",
        enabled => 1,
        gpgcheck => 0
    }
    package { "tftpboot-konyvtar":
        ensure => installed,
        ensure => latest
    }
    file { "/etc/tftpd.map":
        source => "puppet://tftp_konf/tftpd.map"
    }
    service { "xinetd":
        ensure => running
    }
}

Amit ebből a (gyakorlati felhasználásra túl rövid, wiki szócikkbe túl hosszú) példából rögtön láthatunk, az az, hogy a manifestek resource-okból állnak, amiknek típusa (pl. package, service, file, exec), neve (a ':' karakter előtt), valamint attribútumai vannak. Az attribútum nevéhez annak értékét a '=>' operátor segítségével lehet hozzárendelni. Az attribútumoknak lehetnek alapértelmezett értékei. Ezen alapértelmezett értékeket típusonként be lehet állítani. Pl. az exec típus path attribútumához az alábbi módon rendelhetünk alapértelmezett értéket:

Exec { path => '/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin' }

Ami itt rögtön feltűnik, hogy az exec típus nevét nagy kezdőbetűvel írtuk. Ennek az az oka, hogy a kezdőbetű alapján tudja a puppet, hogy deklarációról van -e szó. A kis kezdőbetű deklarációt jelent. Márpedig most nem deklarálni akarunk egy resource-t, hanem alapértelmezett értéket akarunk megadni egy típusra. Azt, hogy milyen paraméterek vannak, a resource típusa határozza meg, azonban léteznek metaparaméterek, amik minden resource esetében megtalálhatóak. Ilyen a subscribe és a require. Mindkettejük egy resource-ra való referenciát, vagy resource referenciák listáját veheti fel értékéül. Referenciát úgy adhatunk meg, hogy nagy kezdőbetűvel megadjuk a resource típusát, majd '[]' között a nevét. A puppet képes változókat is kezelni. A változók neve '$' karakterrel kezdődik. Példa változó értéke alapján való döntésre:

path => $operatingsystem ? {
    solaris => "/usr/local/etc/sudoers",
    default => "/etc/sudoers"
}

A puppet által ismert típusokról, metaparaméterekről, beépített függvényekről, és minden egyébről korrekt dokumentáció érhető el a hivatalos weblapján: http://projects.puppetlabs.com/projects/puppet/wiki/Reference_Index Érdemes továbbá megemlíteni, hogy a puppet saját típusokat és függvényeket megvalósító, ruby nyelven írt modulokkal is bővíthető, így a fentebb említett dokumentációban adott típusok viszonylag kis száma nem korlátozza az eszköz használhatóságát. Ezen modulok megalkotásának módjáról is olvasható dokumentáció a fentebbi címen.

4.3 Felhasznált irodalom

http://projects.puppetlabs.com/projects/puppet/wiki

5 ISconf

Az ISconf mögötti elv meglehetősen egyszerű: Ha két hoston pontosan ugyanazokat a változtatásokat pontosan ugyanabban a sorrendben végzik el, pontosan ugyanúgy fognak viselkedni. Az, hogy a két rendszer garantáltan, pontosan ugyanúgy viselkedjen, a legalacsonyabb költséggel az előző mondatban ismertetett módszerrel oldható meg. A cfengine által alkalmazott elképzelésekhez képest tehát az a fő különbség, hogy a változtatások sorrendje is szigorúan kötött. Így az ISconf nem azt garantálja, hogy a vele adminisztrált rendszerek tartani fognak az előírt állapothoz, hanem azt, hogy egyik, pontosan az előírtnak megfelelő állapotból a másik, pontosan a később előírtnak megfelelő állapotba kerülnek anélkül, hogy bármikor is nem az előírtnak megfelelő állapotba kerülnének. Amennyiben az előírttól eltérő állapotot tapasztalunk, az meghibásodás, vagy a rendszer ellen intézett támadás eredménye, így ebben az esetben ki kell deríteni, mi okozta a problémát. Amennyiben biztonsági hiba az ok, javítani kell a biztonsági hibát, majd az érintett rendszereket újratelepíteni, és hagyni, hogy az ISconf a legutolsó előírt állapotba hozza a rendszert. A helyreállításhoz szükséges idő rövidíthető, ha van egy olyan állapotnak megfelelő image, melyből már viszonylag kevés (néhány óra alatt elvégezhető mennyiségű) műveletet kell végrehajtania az ISconf-nak. Rollback-et tehát soha nem végzünk. Ha hiba miatt tértünk el a helyes állapottól, újratelepítjük a rendszert. Persze, ez azt is jelenti, hogy az adminisztrációra kizárólag az ISconf használandó, hiszen minden, nem az ISconf által elkövetett változtatás az ISconf által előírttól eltérő állapotot eredményezne.

5.1 Használat

Az ISconf használata jelentősen eltér a cfengine és a Puppet használatától. Inkább egy verziókezelő használatára emlékeztet: a változtatások előtt lock-olni kell, utánuk pedig commit-olni. A cfengine-től és a Puppettől eltérően az ISconf esetén nem egy konfigurációs fájl közvetlen szerkesztése által hajthatóak végre a változtatások, hanem az isconf parancs által.

isconf [-Dhrq] [-c config] [-m message] verb [verb_args]

5.2 Parancsok

  • ci: commit. Hozzáadja az aktuális tranzakciót a journal-hoz.
  • exec: Lokálisan végrehajtja rendszeradminisztrátori jogosultsággal az utána megadott parancsot, és hozzáadja az aktuális tranzakcióhoz is ugyazt a parancsot.
  • fork: Lemásolja az aktuális journalt egy másik branch-be, és a lokális gépet átállítja erre az újonnan létrehozott branch-re.
  • lock: A tranzakció kezdetét jelöli.
  • migrate: Átállítja egy másik branch-re a lokális gép konfigurációját. Ez csak abban az esetben sikeres, ha az aktuális branch-ben még nem keletkeztek olyan változások, amik abban a branch-ben, ahová migrálunk, nem szerepelnek.
  • reboot: újraindítást tesz az aktuális tranzakció parancsai közé.
  • restart: újraindítja az ISconf-ot.
  • snap: készít egy snapshotot a paramétereként megadott fájlról, ami aztán a többi gépre is átkerül.
  • start: elindítja az ISconf daemont.
  • stop: leállítja az ISconf daemont.
  • unlock: felszabadítja a zárat a lokális branch-re. A tranzakció így nem kerül a journalba, a lokális gépen viszont megmaradnak a változtatások, így a lokális gép újratelepítendővé válik, hogy ismét egyezzen a konfigurációja a többi gépével.
  • up: frissíti a helyi gép konfigurációját a journalnak megfelelően. Ezt a parancsot be szokás tenni a crontabba. Ha nincs hozzá megadva a -r kapcsoló, akkor az újraindítást igénylő tranzakciónál megáll.

5.3 Környezeti változók

Az ISconf környezeti változók által konfigurálható. Ezek:

  • IS_DOMAIN - ISconf domain neve. Az összes adminisztrálni kívánt gépen egyeznie kell.
  • IS_HOME - Az ISconf által adattárolásra használt útvonal.
  • IS_HMAC_KEYS - A HMAC kulcs fájl neve.
  • IS_HTTP_PORT - Fájlátvitelre használt HTTP szerver portszáma.
  • IS_NETS - A nets fájl neve
  • IS_NOBROADCAST - Ha be van állítva, nem használ UDP broadcast-eket, csak a nets fájlban megadott hostoknak küld UDP csomagokat.
  • IS_PORT - Az ISconf daemon által kommunikációra használt port száma.
  • IS_REBOOT_CMD - A parancs, amit az ISconf végre kell hajtson az "isconf reboot" parancs hatására.

5.4 Konfiguráció

A konfigurációra használt környezeti változók a /etc/is/main.cf fájlban beállíthatók. A fájl formája:

cél: opcionális include-ok
    változó1 = érték
    változó2 = érték

A cél string a hostnévre illeszkedik. Kis- és nagy betűk között nem tesz különbséget. Ha .-ot is tartalmaz, a teljes domain névre illeszkedik. Csak az első illeszkedő cél kerül kiértékelésre, de a DEFAULT cél mindig kiértékelésre kerül. A commentek "#" karakterrel kezdődnek.

5.5 Felhasznált irodalom

ISconf(8) man page

6 Szerző, utolsó módosítás dátuma

  • Szerző: Meszes-Bábszki Áron
  • Utolsó módosítás dátuma: 2010. 01. 17.
Személyes eszközök