Puppet

Puppet

Először még Micmactól hallottam felőle a 2006-os linux konfernecián, bár ő akkor a cfengine-t mutatta be.

A puppet egy unix környezethez írt, központosított szerver üzemeltetési feladatokat ellátó Ruby program.

A támogatott platformok listája

És hogy mit is tud tulajdon képpen?

  •  cron írás
  • program futtatás
  • fájlok szétosztása (jogosultságbeállítás)
  • unix account kezelés (korlátozottan)
  • hosts fájl szerkesztés
  • kötet csatolások
  • időzített parancs futtatás
  • csomag telepítés
  • host ssh kulcs kezelés
  • zone (solaris)
  • szervizek kezelése (/etc/init.d/ és társai)

Mindezt ssl-el titkosítva, authentikálva.

Ahogy elkezdtem használni:

Telepítés Debian Etch

Szerver

 apt-get install puppetmaster

Ez létrehoz egy könyvtárat: /etc/puppet aminek igy néz ki jelenleg a tartalma:

Ezek a fő konfig fájlok:

puppet:/etc/puppet# ls -R *
fileserver.conf  puppet.conf  puppetd.conf  puppetmasterd.conf  tagmail.conf

fileserver.conf

# This file consists of arbitrarily named sections/modules
# defining where files are served from and to whom
# Define a section 'files'
 # Adapt the allow/deny settings to your needs. Order
# for allow/deny does not matter, allow always takes precedence
# over deny

[syslog]
path /etc/puppet/files/syslog
allow <network tartomany>
allow <ip cím>

[checkprg]
path /etc/puppet/files/checkprg
allow <network tartomany>
allow <ip cím>
deny <ip cím>
.
.
.

puppetmasterd.conf

[puppetmasterd]
# Make sure all log messages are sent to the right directory
# This directory must be writable by the puppet user
logdir=/var/log/puppet
vardir=/var/lib/puppet
rundir=/var/run
# beallitjuk, hogy a valtozasok menjenek e-mail-ben...
reports = tagmail,daily

[ldap]
ldapnodes = true
ldaptls = true
ldapserver = ldap.domain.tld
ldapbase = ou=Puppet,dc=domain,dc=tld
ldapstring = (&(objectclass=puppetClient)(cn=%s))

tagmail.conf

all: puppet@<domain>.<tld>

Itt vannak a puppet fájlszerver különböző fájljai könyvtárakban:

files:
backup checkprg nrpe puppet segito syslog

files/backup:
backup_szimszon hostname1_backup.cfg hostname2_backup.cfg
files/checkprg:
check.cfg check.cfg.hostname1

files/puppet:
puppetd.conf

files/segito:
altalanos.func util.func

files/syslog:
syslog-ng.conf syslog-ng.conf.hostname.domain.tld

Manifests, ahol le van írva, mit hogyan kell kézbesíteni:

manifests:
classes hosts includes site.pp

Tulajdonképpen a site.pp-ben lehet megmondani, hogy miből építkezhet a puppet.

site.pp

import "includes/*"
import "/etc/puppet/manifests/classes/*"
import "/etc/puppet/manifests/hosts/hostname1/*"
import "/etc/puppet/manifests/hosts/hostname2/*"

Itt vannak az általános osztályok

manifests/classes:
check_prg.pp ntpdate.pp segito_bash.pp
backup_szimszon.pp puppet.pp syslog-ng.pp

check_prg.pp osztály:

class check_prg {
# becsatolja azt a fajlt, amiben a /usr/local/etc konyvtar
# elkeszitese van leirva
include usr_local_etc

# definialjuk a /usr/local/etc/check.cfg fajlt, ahol a
# source adja meg, hogy eloszor a puppet file szerverrol probalja letolteni
# a [checkprg] szekciobol a check.cfg.$fqdn (facter valtozo, a kliens
# teljes domain nevet adja vissza), ha nem sikerul akkor a
# check.cfg fajlt tolti le.
# Valamint a require mondja meg, hogy az egesz elofeltetele a
# /usr/local/etc meglete.
file { "/usr/local/etc/check.cfg":
owner => "root",
group => "root",
mode => 400,
source => [ "puppet://puppet/checkprg/check.cfg.$fqdn",
"puppet://puppet/checkprg/check.cfg" ],
require => File["/usr/local/etc"]
}
file { "/usr/local/sbin/check_prg.sh":
owner => "root",
group => "root",
mode => 750,
source => [ "puppet://puppet/checkprg/check_prg.sh.$fqdn",
"puppet://puppet/checkprg/check_prg.sh" ],
require => File["/usr/local/etc/check.cfg"]
}

# itt beallitjuk a crontab-ot.
cron { check_prg:
command => "/usr/local/sbin/check_prg.sh",
user => "root",
minute => "*/5",
require => File["/usr/local/sbin/check_prg.sh"]
}
}

backup_szimszon.pp

class backup_szimszon {

include backup_idok
# manifests/includes/backup_idok.pp fajl tartalma
# itt lehet felsorolni, hogy melyik gepnek mikor kezdodjon a mentese
#
# case $fqdn {
# "<hostname1>.<domain>.<tld>": { $hour = "0" $minute = "30" }
# "<hostname1>.<domain>.<tld>": { $hour = "2" $minute = "30" }
# }
#

include usr_local_etc

# ellenorizzuk, hogy a gawk telepitve van-e
package { "gawk": ensure => installed }

file { "/usr/local/etc/backup1":
ensure => directory,
require => File["/usr/local/etc"]
}

# itt szukseges volt a valtozot {} koze tenni...
file { "/usr/local/etc/backup1/${hostname}_backup.cfg":
owner => root,
group => root,
mode => 400,
source => ["puppet://puppet/backup/${hostname}_backup.cfg",
"puppet://puppet/backup/hostname_backup.cfg"],
require => File["/usr/local/etc/backup1"]
}

file { "/usr/local/sbin/backup_szimszon":
owner => root,
group => root,
mode => 750,
source => "puppet://puppet/backup/backup_szimszon",
require => [File["/usr/local/etc/backup1/${hostname}_backup.cfg"],
Package["gawk"]]
}

cron { "backup_szimszon":
command => "/usr/local/sbin/backup_szimszon",
hour => $hour,
minute => $minute,
user => "root",
require => File["/usr/local/sbin/backup_szimszon"]
}
}

Itt az egyes host-okhoz tartozó könyvtárak:

manifests/hosts:
hostname1 hostname2

és a host-hoz tartozó osztályok

manifests/hosts/hostname1
crontab_hostname1.pp
manifests/hosts/hostname2
crontab_hostname2.pp

manifests/includes:
backup_idok.pp usr_local_etc.pp

Ez a könyvtár tartalmazza az ssl tanúsítványokat, amiket a rendszer saját maga kezel, meglepő hatékonysággal.

ssl:
ca certs private private_keys public_keys

Nálunk a node-ok ldap-ban vannak, ezt a puppetmaster.conf [ldap] részében állítottuk be.

Itt az ldap schema:

# These OIDs are all fake. No guarantees there won't be conflicts.
#
# $Id$

attributetype ( 1.1.3.10 NAME 'puppetclass'
DESC 'Puppet Node Class'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.1.3.9 NAME 'parentnode'
DESC 'Puppet Parent Node'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

objectclass ( 1.1.1.2 NAME 'puppetClient' SUP top AUXILIARY
DESC 'Puppet Client objectclass'
MAY ( puppetclass $ parentnode ))

# added by szimszon
objectclass ( 1.1.1.3 NAME 'puppetDomain' SUP top STRUCTURAL
DESC 'Puppet Domain objectclass'
MUST ( domain ))

És itt az eredeti.
Ezzel a következő fa struktúrát valósítottuk meg:

ou=Puppet,dc=domain,dc=tls
|
+--domain=domain.tls
| |
| +--cn=hostname1
| | |
| | +-- dn: cn=hostname1,domain=domain.tls,ou=Puppet,dc=domain,dc=tls
| | +-- objectClass: top, device, ipHost, puppetClient
| | +-- cn: hostname1
| | +-- ipHostName: <ip>
| . +-- puppetClass: check_prg
| . +-- parentNode: vbelso
| .
+--domain=virtual
| |
| +--cn=vbelso
| | |
| | +-- dn: cn=vbelso,domain=virtual,ou=Puppet,dc=domain,dc=tls
| | +-- objectClass: top, device, puppetClient
| | +-- cn: vbelso
| . +-- puppetClass: unix_ldap_auth, syslog-ng
| . +-- parentNode: default
| .
| +--cn=default
| | |
| | +-- dn: cn=default,domain=virtual,ou=Puppet,dc=domain,dc=tls
| | +-- objectClass: top, device, puppetClient
| | +-- cn: default
| . +-- puppetClass: ntpdate
. .
. .
.

Ahol:

puppetClass Puppet konfigurációs class
parentNode Az a Node aminek a Puppet konfigurációs class -szait örökli.

Ezzel megkarcoltuk már a felszínt :)

Kliens

A tűzfalon nyissuk meg a 8140-es portot a puppet szerver felől.

apt-get install puppet

Mikor települt, a szerveren alá kell iratni a kliens tanúsítványát. Kilistázzuk, mik várnak aláírásra:

server# puppetca --list
<hostname1>.<domain>.<tld>
server# puppetca --sign <hostname1>.<domain>.<tld>

Érdemes a /etc/puppet/puppetd.conf-ban a

 report=true
értéket is megadni.

Ezután, és ha az osztályok (class), gépek (node) és minden be van konfigolva, indítsuk újra a kliens puppetd-t:

 client# /etc/init.d/puppet restart
Igazság szerint első indításkor inkább az alábbit javasolnám:

 client# /etc/init.d/puppet stop
client# puppetd --verbose
mert így nem kerül háttérbe a folyamat és a képernyőn szépen látjuk a logokat.

Irodalom:

Mindenkinek jó rendszeradminisztrációt... és ez csak a felszín felszínének a felszíne volt :)

 

# diff /usr/lib/ruby/1.8/puppet/parser/interpreter.rb.old /usr/lib/ruby/1.8/puppet/parser/interpreter.rb
392,394c392,394
< if node =~ /\./
< node = node.sub(/\..+/, '')
< end
---
> #if node =~ /\./
> # node = node.sub(/\..+/, '')
> #end

Ennyi kell ahhoz, hogy LDAP-ban tárolt node nevek mintaillesztésénél ne vesszen el a domain. Az eredeti fájl használatakor:

cn=hostname,domain=domain...

használható, de csak a hostname az amit a puppet keres, viszont ha van mondjuk két mail hostnevű gépünk más-más domain-ben, akkor szükségünk lehet a fenti módosításra, amivel a puppet különbséget tud tenni a:

cn=mail.domain1.tld,domain=domain1.tld

és a

cn=mail.domain2.tld,domain=domain2.tld

 között.