Puppet, klar. Und dann?
23.05.2013 | LinuxTag 2013
Thomas Gelf
www.netways.de
VORSTELLUNG
Kurzvorstellung: Thomas Gelf
- Seit 2010 Senior Consultant bei der NETWAYS GmbH in Nürnberg
- Zuvor über 10 Jahre:
- Web (Application) Development
- Routing/Switching (Banken und ISP-Backbone)
- ISP-Umfeld: Planung und Umsetzung hochverfügbarer Plattformen (Mail, Hosting, SIP-Carrier, IPv6...)
- Italienischer Staatsbürger deutscher Muttersprache, kurz:
- ...SÜDTIROLER!!!
Puppet und Ich
- Wie alles begann:
ADMIN-Magazin 06/2010
- (Inhouse-)Trainings
- Consulting
- Und natürlich Vorträge zu Puppet: LinuxTag, OSDC, PuppetCamp, GUUG Frühjahrsgespräche, GridKa School, CeBIT...
Puppet und Netways
- Offizieller PuppetLabs Schulungs-Partner
- Termine für Puppet Fundamentals:
- 04. - 06. Juni 2013 | Nürnberg
- 12. - 14. November 2013 | Zürich
- 03. - 05. Dezember 2013 | Nürnberg
- www.netways.de/training
Puppet und Netways
- Offizieller PuppetLabs Schulungs-Partner
- Termine für Puppet Advanced:
- 25. - 27. Juni 2013 | Nürnberg
- 08. - 10. Oktober 2013 | Nürnberg
- www.netways.de/training
Puppet und Netways
- Offizieller PuppetLabs Schulungs-Partner
- Termine für Extending Puppet using Ruby:
- 08. - 11. Juli 2013 | Nürnberg
- 09. - 12. September 2013 | Nürnberg
- www.netways.de/training
Es gibt Zertifizierungen!
- puppetlabs.com/services/certification
Puppet und Netways
- Direkt nach der OSDC 2014 - erstmals in Berlin:
- www.netways.de/puppetcamp
We are hiring!
www.netways.de/jobs
WICHTIG: Dieser Vortrag will...
- "Willkürlich" ausgewählte Komponenten des Puppet-Universums beleuchten
- Alltagsprobleme und mögliche Lösungen zeigen
- Zum Nachdenken anregen - und Lust auf mehr machen
- Keine Puppet-Einführung sein...
- ...die meisten Beispiele sind aber selbsterklärend
Übersicht
- Wo anfangen?
- Abhängigkeiten / Abläufe
- Systemübergreifende Konfiguration
- Orchestration: MCollective
- Workflows
- Schnittstellen
- External Node Classifier
- Lookup Funktionen und HIERA
- REST API
- Sonstiges
WARMUP: WO ANFANGEN?
Wofür ist Puppet zuständig?
- Bare metal deployment?
- Paketmanagement?
- Host-übergreifende Konfiguration?
- Automatisierte Abläufe?
Langsam anfangen, Step by Step:
- Erst langweiligen Kleinkram:
- NTP
- Vernünftiges Mailrouting (für Fehler in Cronjobs!)
- Logging
- Basis-Komponenten fürs Monitoring
- docs.puppetlabs.com/learning
Nicht übertreiben: Paketmanagement
package { 'apache2':
ensure => installed
}
- Versionen zu spezifizieren ist möglich
- Wenn möglich Funktionen der Distro steuern (HOLD)
- Bitte sparsam einsetzen:
package { 'xz-utils':
ensure => '5.1.1alpha+20110809-3'
}
Nicht übertreiben. Beispiel: Updates
# Möglich:
package { 'whatever':
ensure => 'latest'
}
# Aber besser:
case $osfamily {
'debian': {
cron { 'autoupgrade':
path => '/bin:/sbin:/usr/bin:/usr/sbin',
command => 'apt-get update && apt-get upgrade',
user => root,
hour => 2,
minute => ip_to_cron(),
}
}
'redhat': {
package { 'yum-autoupdate': ensure => installed }
}
}
Alles muss in Module!
- Module sparen Tippaufwand durch Konvention
- Idealerweise sind sie dann zudem plattformunabhängig:
$pkg = $osfamily ? {
'redhat' => 'openssh',
'debian' => [ 'openssh-server', 'openssh-client' ],
default => 'ssh'
}
package { $pkg: ensure => installed }
- VMware-Guests brauchen andere Pakete
- Container brauchen keinen nptd
DANN: REIHENFOLGE
Wir erinnern uns
Explizite Abhängigkeiten
class ssh {
package { 'openssh-server':
ensure => installed,
}
file { '/etc/ssh/sshd_config':
ensure => file,
source => 'puppet:///modules/ssh/sshd_config',
mode => 0644,
owner => 'root',
group => 'root',
require => Package['openssh-server'],
notify => Service['ssh'],
}
service { 'ssh':
ensure => running,
enable => true,
}
}
Kurzschreibweise
Package['openssh-server']
-> File['sshd_config']
~> service { 'ssh':
ensure => running,
enable => true,
}
- Nutzbar für bereits deklarierte Ressourcen...
- ...oder direkt beim Deklarieren derselben
Implizite Abhängigkeiten
File {
owner => 'user1',
group => 'group1',
require => [ User['user1'], Group['group1'] ],
}
file { '/tmp/test': ensure => directory }
file { '/tmp/test/file':
ensure => file,
require => File['/tmp/test'],
}
User['user1'] {
gid => 'group1',
require +> Group['group1'],
}
group { 'group1': ensure => present }
Noch eleganter: Run Stages
Run Stages: Beispiel
class yumrepos {
$url = "http://host/repo/$operatingsys../$architecture"
yumrepo { 'meinrepo':
baseurl => $url,
descr => 'Mein repository',
enabled => 1,
gpgcheck => 0,
}
}
stage { 'yum': before => Stage['main'] }
node /^www\d+/ {
class { 'yumrepos': stage => yum }
include webserver
include dbserver
}
Wichtige Regeln zu Abhängigkeiten
- Je weniger Abhängigkeiten desto besser
- Abhängigkeiten von anderen Modulen/Klassen sind OK
- Abhängigkeiten von Ressourcen in anderen Klassen:
- Zwischen Modulen unbedingt vermeiden
- Innerhalb eines Moduls unter Umständen sinnvoll
- Kurz: Hängt stark vom Moduldesign ab
- Und wenn ein Dependency-Cycle mal unklar ist:
puppet apply --graph
SYSTEMÜBERGREIFENDE CONFIG
Beispiele
- Load Balancer und Applikationsserver
- Cluster und Mitglieder
- Monitoring-Server und überwachte Anwendungen
- Anwendungen und remote Datenbanken
- Verteilung von "known hosts" oder /etc/hosts
- Konfiguration von Backup-Jobs
Lösung: exportierte Ressourcen
Exportierte Ressourcen - Beispiel I
- Webanwendung will von Monitoring-Server remote überwacht werden:
class webserver {
package { 'apache2': ensure => installed }
@@nagios_service { "check_http_$fqdn":
use => "check_http",
host_name => $fqdn,
target => "/etc/icinga/objects/check_http_$fqdn.cfg",
}
}
class icinga {
Nagios_service <<||>>
}
Exportierte Ressourcen - Beispiel II
- Webanwendung exportiert gewünschte Datenbank:
@@mysql::db { 'guug2013':
user => 'guug',
password => '2013',
host => $ipaddress,
grant => ['all'],
tag => 'web_db'
}
- Datenbank-Server setzt sie um:
Mysql::Db <<| tag == 'web_db' |>>
Exportierte Ressourcen - Beispiel III
- Noch kompakter: /etc/hosts
class hosts {
@@host { $fqdn:
ip => $ipaddress,
host_aliases => $hostname,
}
Host <<||>>
}
Voraussetzungen
[master]
storeconfigs = true
thin_storeconfigs = true
dbadapter = mysql
dbuser = puppet
dbpassword = ***
...
- VORSICHT: Ressourcenintensiv!
Wichtig: aufräumen!
- Puppet kann nicht wissen, ob ein Host:
- nur vorübergehend down ist...
- ...oder aber gar nicht mehr existiert:
puppet node clean host1.example.com
Neu: PuppetDB
- Neue Architektur
- Graphen können abgebildet werden
- Message Queue
- Java-Daemon
- Kann bei Bedarf auch viele Cores auslasten
Zu umständlich? Zu wenig?
- Wenn exportierte Ressourcen zu starr sind:
# Array aller aktiven Knoten mit Uptime > 30 Tagen
# und zugewiesener Klasse Apache:
$ret = pdbnodequery(
['>',['fact','uptime_days'],30],
['and',
['=','type','Class'],
['=','title','Apache']])
https://github.com/dalen/puppet-puppetdbquery
- Noch mehr? Orchestration, Marionette Collective!
ORCHESTRATION: MCOLLECTIVE
Was ist Marionette Collective?
- MQ-basierte Software zur Steuerung unserer Server
- Protokoll: STOMP
- Puppet-Runs on-demand
- Parallele manuelle Steuerung von Ressourcen on-the-fly
- Eigene Agenten super-einfach in Ruby umsetzbar
Einfach mal HALLO sagen...
% mco ping
dev8 time=126.19 ms
dev6 time=132.79 ms
dev10 time=133.57 ms
.
.
---- ping statistics ----
25 replies max: 305.58 min: 57.50 avg: 113.16
Wir stoppen...
- ...den Apache...
- ...auf allen Debian-basierten Servern...
- ...denen wir die Anwendung 'webappxy' zugewiesen haben:
mco rpc service stop service=apache2 \
--with-fact osfamily=debian \
--with-class role::webappxy
Fazit zu MCollectie
- Solltet ihr unbedingt einfach mal ausprobieren
- Genial, um Migrationen in verteilten Umgebungen zu skripten
- WICHTIG: Nicht einsetzen, ohne verstanden zu haben wie die MQ tickt...
- ...und Security-Fragen geklärt zu haben!
WORKFLOWS
Organisatorisches
- VCS: UNBEDINGT!
- Branches pro Environment / Abteilung / Puppet Master...
- Commit hooks - Syntax-Check
- Live-Master/Environment: getestete Versionsstände ausrollen
- Mehrere Modul-Bibliotheken kombinierbar
- Puppet-Lint
Wer darf was?
- Üblicher Grabenkampf Operating VS Development
- Stabilität VS neue Features
- Häufige kleine Updates bereiten weniger Schmerzen, WENN...
- ...sie getestet sind
- ...sich einfach zurückrollen lassen
- ...sofort messbar ist, ob Probleme auftreten
Seid großzügig ;-)
- Entwickler SOLLEN die Möglichkeit bekommen...
- ...sich selbst einfachst Umgebungen aufsetzen zu können
- ...Produktivsysteme nachzubauen
- ...eigene Puppet-Module zu schreiben
- Entwickler lieben andere Tools: Gepetto, Vagrant
Ziel
- Das alles fördert Transparenz
- Operating und Development rücken näher zusammen
- Reviews von Changes werden einfacher und dokumentierbar
- Dist-Upgrades sind old-school
- Wir leben in einer virtualisierten Wegwerfgesellschaft
SCHNITTSTELLEN - ENC
Unsere Node-Definitionen
- Werden eigentlich im Manifest definiert (site.pp)
node 'some-server.domain.tld' {
include baseconfig
include webserver
}
node 'www1.domain.tld' inherits 'some-server.domain.tld' {
include my-webapp
}
node /^www\d+\.domain\.tld$/ {
include baseconfig
class {'webserver': type => 'apache', version => '2.4' }
}
node default {
include unconfigured
}
Vor- und Nachteile textbasierter Nodes
- Wunderbar in Kombination mit GIT, SVN & Co
- Nicht so wunderbar für GUI-Integration
- Rollenzuweisungen ändern sich häufiger als Modul-DSL
- Text-Dateien sind fehleranfälliger
(Klammern, Regex-Fehler!)
ENC Konfiguration
- http://docs.puppetlabs.com/guides/external_nodes.html
- Parametrisierbare Klassen seit 2.6.5
- External Node Classifier:
[master]
node_terminus = exec
external_nodes = /usr/local/bin/my_node_classifier
ENC Ausgabe
---
classes:
baseconfig
webserver
type: Apache
version: 2.4
parameters:
global_var: foo
global_array:
- foo
- bar
environment: production
Beispiel in Perl
#!/usr/bin/perl
use YAML;
my $hostname = $ARGV[0];
# Unsere "CMDB":
my $result = {
'classes' => {
'baseconfig' => {
'datacenter' => 'Nuremberg'
},
'webserver' => {
'type' => 'apache',
'version' => '2.4'
}
}
};
print YAML::Dump($result);
SCHNITTSTELLEN - LOOKUPS
extlookup()
- Gibt es seit 2009, "offiziell" seit Puppet 2.6.1
- extdata -> CSV
$relay_host = extlookup('relay_host', 'default-relay.tld')
some-host.tld.csv:
relay_host,datacenter2.domain.tld
common.csv:
relay_host,datacenter1.domain.tld
# Sind im Grunde globale Variablen!!
$extlookup_datadir = "/etc/puppet/manifests/extdata"
$extlookup_precedence = ["%{fqdn}", "common"]
$relay_host = extlookup('relay_host')
Hiera!
Hiera - backends
Hiera!
class apache($version = hiera('apache::version', '2.4'))
class apache($version = hiera('version', '2.4'))
- ...oder noch besser, mittels 'data bindings':
class apache($version = '2.4')
Eigene functions und facts
- puppet master: (parser) functions
- puppet agent: facts
- Können und sollen in Modulen abgelegt werden
- Kann man via pluginsync verteilen
- Wird nicht in diesem Vortrag gezeigt
SCHNITTSTELLEN: REST API
Rest?
- Ein "RESTful Webservice":
- Wird mittels HTTP implementiert
- Stellt eine Sammlung von Ressourcen bereit
- Hat ein URI, einen "resource identifier"
- Kennt definierte Methoden: GET, PUT, POST, DELETE
- Nutzt Internet Media-Types
Rest API
- Verfügbar auf puppet master und agent
- https://master:8140/{environment}/{resource}/{key}
https://agent:8139/{environment}/{resource}/{key}
- Auf dem Agent nur wenn
listen = true
- http://docs.puppetlabs.com/guides/rest_api.html
Puppet REST API URI Beispiele
- GET /{environment}/catalog/{node certificate name}
- GET /{environment}/file_bucket_file/md5/{checksum}
- GET /{environment}/facts/{node certname}
- Berechtigungen müssen eventuell angepasst werden!
Kleines SSL-basiertes Beispiel
- Wir lieben Zertifikate...
- ...und wollen auf jeden Fall YAML sehen:
curl \
--cert /var/lib/puppet/ssl/certs/host.pem \
--key /var/lib/puppet/ssl/private_keys/host.pem \
--cacert /var/lib/puppet/ssl/ca/ca_crt.pem \
-k -H "Accept: yaml" \
https://master:8140/production/facts/somehostname
- Für YAML-Hasser wie mich gibt es auch JSON ;-)
Vorteile der REST API
- Es ist ein API
- Es ist schon da und verfügbar
- Keine Sorgen bzgl Schema-Änderungen
(z.B. storeconfigs/PuppetDB)
- Ausgabeformat lässt sich wählen
- http://docs.puppetlabs.com/guides/rest_api.html
BITTE NICHT...
- curl --... | grep ... | sed ... | awk ...
- Es gibt auch eine Welt außerhalb der Shell!
#!/usr/bin/php
<?php
$api = new Puppet_Api($master);
$facts = $api->hostFacts($hostname);
echo "$hostname is running $facts->osfamily";
- (bitte nutzt EURE bevorzugte Skriptsprache)
Schnittstellen - wie geht's weiter?
- Das ist euer Problem ;-)
- Use the right tool for the right job
- Fakten vs CMDB vs ENC vs HIERA:
- Aus CMDB könnte man nodes.pp generieren
- Eigener ENC könnte mit CMDB sprechen
- CMDB könnte man mit Facts befüllen
- Befüllt Puppet das Monitoring? Oder die CMDB?
- Kann ich Fakten trauen?
SONSTIGE FEATURES
Reporting
- Will man haben!
- Puppet Enterprise Console
- Foreman (theforeman.org)
Enterprise?
Enterprise: Live Management
Open Source Software
- Unabhängig von PE...
- ...ist und bleibt Puppet aber freie Software!
- Hat eine riesige Community
- Hat eine riesige Community
Puppet Module Forge

- Bereits über 900 Module
- Nutzt es als Inspirationsquelle!
- Und ist die Antwort wirklich 42?
Danke für eure Aufmerksamkeit!
Fragen?
class linuxtag2013::puppet {
service { 'questions':
ensure => answered
}
}
Thomas Gelf <thomas.gelf@netways.de>