P U P P E T http://reductivelabs.com/trac/puppet Vad är Puppet? * Språk för att definiera hur maskiner ska konfigureras * Programmen som applicerar den definitionen Se till att: * paket är/inte är installerade * konfigfiler har rätt innehåll * tjänster kör/inte kör ... Varför ska man använda Puppet? * Automatisering * Dokumentation * Struktur * Återanvändning * Testinstallationer * Ominstallationer Jämfört med: rdist/rsync + ssh/pdsh - Påverkar bara de maskiner som är uppe just då - Ingen spårbarhet eller klonbarhet. Man vet fortfarande inte hur maskinerna är eller ska vara konfigurerade. Jämfört med: Installera om maskiner från master-image - Kräver nertid för maskinen - Funkar i sin renaste form bara för identiska maskiner. Måste kompletteras med skriptning om maskinerna skiljer sig åt. - Ger klonbarhet, men inte spårbarhet. Man kan göra identiska maskiner, men man är inte mycket till hjälp om man t.ex vill byta OS-versioner eller OS-dist. - Hänsyn måste tas till data, så att det inte försvinner. + Ger ett garanterat identiskt tillstånd. Jämfört med: Installera om med omfattande %post i kickstart - Kräver nertid för maskinen - Oportabelt: varje OS-dist har sin egen kickstart- motsvarighet. - Kan vara knepigt att hålla alla kickstartfiler i synk med varandra. - Hänsyn måste tas till data, så att det inte försvinner. + Ger ett garanterat identiskt tillstånd. + Ger både klonbarhet och spårbarhet Jämfört med: Dokumentera - Tråkigt. - Lätt att man missar att skriva ner någon detalj, beskriver för vagt, inte hinner göra det "just nu", osv. - Fortfarande en massa manuellt jobb att klona. - Lätt att göra fel när man följer dokumentationen. + Ofta lättare och naturligare att beskriva inte bara vad, utan också varför. ± Ger poäng hos PHB:er. Koncept * Idempotens * Konvergens * Deklarativt språk, inte imperativt file { "/etc/hemligt.txt": owner => "root", group => "wheel", mode => 0600; } file { "/etc/nsc": ensure => directory; } file { "/etc/sysconfig/selinux": content => "SELINUX=permissive\nSELINUXTYPE=targeted\n"; } file { "/etc/ntp.conf": source => "/config/files/ntp.conf"; } type { title_a: param1 => value1a, param2 => value2a, ...; title_b: param1 => value1b, param2 => value2b, ...; ... } file { "/etc/hemligt.txt": owner => "root", group => "root", mode => 0600; "/etc/nsc": ensure => directory; "/etc/sysconfig/selinux": content => "SELINUX=permissive\nSELINUXTYPE=targeted\n"; "/etc/ntp.conf": source => "/config/files/ntp.conf", mode => 0444; "/etc/rndc.key": ensure => "/var/named/chroot/etc/rndc.key"; } package { "ntp": ensure => installed; "dhcp": ensure => absent; "torque": ensure => installed, provider => rpm, source => "/pkg/local/torque-2.2.1-1cri.x86_64.rpm"; } yumrepo { "smokerings": descr => "Smokerings local repository", baseurl => "file:///pkg/local/smokerings/x86_64/", gpgcheck => 0, enabled => 1; "nordugrid": descr => "NorduGrid - stable", baseurl => "http://ftp.nordugrid.org/repos/redhat/el5/x86_64/stable", gpgkey => "http://ftp.nordugrid.org/RPM-GPG-KEY-nordugrid", gpgcheck => 1, enabled => 1; } service { "dhcpd": enable => false, ensure => stopped; "ntpd": enable => true, ensure => running; } * cron * notify * nagios_command * exec * package * nagios_contact * file * resources * nagios_contactgroup * filebucket * schedule * nagios_host * group * service * nagios_hostescalation * host * ssh_authorized_key * nagios_hostextinfo * (interface) * sshkey * nagios_hostgroup * k5login * tidy * nagios_hostgroupescalation * mailalias * user * nagios_service * maillist * yumrepo * nagios_servicedependency * mount * zone * nagios_serviceescalation * nagios_serviceextinfo * nagios_servicegroup * nagios_timeperiod package { "ntp": ensure => installed; } file { "/etc/ntp.conf": source => "/config/files/ntp.conf", require => Package["ntp"]; } service { "ntpd": enable => true, ensure => running, subscribe => File["/etc/ntp.conf"]; } package { "ntp": ensure => installed, before => File["/etc/ntp.conf"]; } file { "/etc/ntp.conf": source => "/config/files/ntp.conf", notify => Service["ntpd"]; } service { "ntpd": enable => true, ensure => running; } class ntp-generic { file { "/etc/ntp": # Ntpd needs to be able to store /etc/ntp/drift. ensure => directory, owner => "ntp", group => "ntp", mode => 0755; } package { "ntp": ensure => installed; } service { "ntpd": enable => true, ensure => running; } } class timeserver { include ntp-generic file { "/etc/ntp.conf": source => "/config/files/ntp.conf-server"; } } class timeclient { include ntp-generic file { "/etc/ntp.conf": source => "/config/files/ntp.conf-client"; } } node armstrong { include timeserver file { "/etc/nodetype": content => "system-server\n"; } } node goodman, "miller.smokerings.nsc.liu.se" { include timeclient file { "/etc/nodetype": content => "system-server\n"; } } node n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20, n21, n22, n23, n24, n25, n26, n27, n28, n29, n30, n31, n32, n33, n34, n35, n36, n37, n38, n39, n40, n41, n42, n43, n44, n45, n46, n47, n48 { include timeclient file { "/etc/nodetype": content => "computenode\n"; } } file { "/var/named/chroot/etc/named.conf": source => "/config/Files/named.conf"; "/var/named/chroot/etc/rndc.conf": source => "/config/Files/rndc.conf"; "/var/named/chroot/var/named/192-168-116.zone": source => "/config/Files/192-168-116.zone"; "/var/named/chroot/var/named/192-168-117.zone": source => "/config/Files/192-168-117.zone"; } $pupfiles = "/config/Files" $namedroot = "/var/named/chroot/" $namedetc = "${namedroot}etc" $zonedir = "${namedroot}var/named" file { "$namedetc/named.conf": source => "$pupfiles/named.conf"; "$namedetc/rndc.conf": source => "$pupfiles/rndc.conf"; "$zonedir/192-168-116.zone": source => "$pupfiles/192-168-116.zone"; "$zonedir/192-168-117.zone": source => "$pupfiles/192-168-117.zone"; } file { "/etc/smurf.conf": source => ".../smurf.conf-$operatingsystem"; "/etc/gnapp.conf": source => ".../gnapp.conf-$hostname"; "/usr/bin/gargamel": ensure => ".../gargamel.$architecture"; } $bindpkg = $operatingsystem ? { "Fedora" => ["bind", "bind-chroot"], "Gentoo" => ["net-dns/bind"], } package { "bindpackage": name => $bindpkg, ensure => installed; } service { "named": enable => true, ensure => running, require => Package["bindpackage"]; } case $operatingsystem { "CentOS", "Fedora": { package { "bind": ensure => installed; "bind-chroot": ensure => installed; } service { "named": enable => true, ensure => running, require => [ Package["bind"], Package["bind-chroot"] ]; } } "Gentoo": { package { "net-dns/bind": ensure => installed; } service { "named": enable => true, ensure => running, require => Package["net-dns/bind"]; } } } import "util.pp" import "dns.pp" import "rootuser.pp" import "osfixes.pp" import "puppet.pp" import "filesystems.pp" import "network.pp" import "time.pp" import "installation.pp" import "cluster.pp" import "manifests/*.pp" $cluster_domain = "smokerings.nsc.liu.se" $n_computenodes = 66 file { "/etc/hosts": ensure => file, content => template("$pupfiles/hosts.erb"); } 127.0.0.1 localhost ::1 localhost6 192.168.116.1 armstrong.<%= cluster_domain %> armstrong 192.168.116.2 goodman.<%= cluster_domain %> goodman 192.168.116.3 miller.<%= cluster_domain %> miller 192.168.116.4 ellington.<%= cluster_domain %> ellington 192.168.116.5 basie.<%= cluster_domain %> basie # 192.168.116.129-200 compute nodes <% 1.upto(n_computenodes.to_i) do |i| -%> 192.168.116.<%= i+128 %> n<%= i %>.<%= cluster_domain %> <% end -%> * alert * file() * search * crit * fqdn_rand() * sha1() * debug * generate() * tag * defined() * include * tagged() * emerg * info * template() * err * notice * warning * fail * realize # Mirror a directory tree using rsync. # # The key in the file $sshkey must not be encrypted. define rsync_mirror($source, $target, $sshkey="", $unless="", $onlyif="") { if $sshkey { $sshcmd = "ssh -i$sshkey" } else { $sshcmd = "ssh" } exec { "rsync -aRqv --no-implied-dirs --delete --delete-excluded '$source' '$target'": env => "RSYNC_RSH=$sshcmd", path => "/bin:/usr/bin", unless => $unless ? { "" => undef, default => $unless }, onlyif => $onlyif ? { "" => undef, default => $onlyif }; } } Utökningar * Egendefinierade typer * Egendefinierade funktioner * Egendefinierade fakta * Utökningar skrivs i Ruby Klient-server * puppetmasterd på en server * puppetd på alla klienter * Krypterad förbindelse * Server och klient autentiseras med X.509-certifikat Andra liknande verktyg: Cfengine + Moget + Välanvänt + Hyfsat väldokumenterat - Jobbigt att få rätt ordning - Svårt att utöka + Har fileditering inbyggt i sig - "Lågnivå" Andra liknande verktyg: Bcfg2 - XML Andra liknande verktyg: PCfengine "Cfengine i Python" - Finns inte än... Bra och dåligt med Puppet - Mycket yngre än Cfengine - Inte så bra dokumentation + "Högnivåoperationer" - Saknar en del "lågnivå"-guck (redigering av textfiler) + Utökningsbart (i Ruby) + Kraftfull mallhantering ("templates") för filinnehåll