puppetdocs

Ultimate puppet walkthrough guide! (in German)

AGPL-3.0 License

Stars
9

Puppet walkthrough

Inhaltsverzeichnis

Best Practices fr das Testen von Komponenten

Was ist ein Puppet Modul

  • Ein normales Puppet Modul kann man auch als Komponentenmodul bezeichnen
  • Es bndelt Puppet Klassen, welche eine einzelne Komponente verwalten (z.B. nginx oder Apache oder HAProxy)
    • Eine Klasse bndelt Puppet Ressourcen in einem Namespace. Dies hat wenig Klassen aus einem OOP Kontext zu sein
    • Man sollte eine Klasse in Puppet nicht mit einer Klasse in Java oder C# vergleichen
  • Jedes Komponentenmodul sollte ein eigenes Git Repository haben
  • Jedes Komponentenmodul ist nicht nur ein Puppet Projekt, sondern auch ein Ruby Projekt (weil puppet in Ruby geschrieben ist)
    • Ruby Projekte haben immer ein Gemfile, dies listet Ruby Abhngigkeiten fr die Laufzeit, fr Tests und fr die Entwicklung
    • Ruby Projekte haben meistens ein Rakefile, dort sind Tasks definiert (hnlich einem Makefile)
    • Ruby Projekte testet man (unter anderem) mit Ruby Tools

Nheres dazu unter puppetlabs_spec_helper.

Warum will man Linter

  • In Programmiersprachen, egal ob Puppet DSL, Ruby, Rspec DSL oder andere, gibt es viele Schreibweisen fr das selbe Ergebniss
  • Onboarding neuer Entwickler ist einfacher, wenn Code einheitlich ist
  • Updates sind mit einheitlichem Code einfacher
    • Code auf eine neue Ruby Version portieren
    • Code auf eine neue Puppet Version portieren
  • In jedem kosystem gibt es eine Community welche sich Style Guides ausdenkt, diesen kann man mit Lintern anwenden/erzwingen
  • In einer CI Pipeline sind Linter gut, da sie sehr schnell arbeiten und direkt Feedback liefern
    • Optional auch als pre-commit Hook lokal ausfhren
  • Ein Linter prft nicht zwingend den Code auf Syntax Fehler

rspec

  • rspec ist ein unit testing framework in Ruby. Es bringt eine eigene DSL mit
  • rspec-puppet ist eine Erweiterung fr rpsec, um Puppet code testen zu knnen
  • Unit Tests sind Tests, welche einzelne Funktionen / minimale Codeblcke testen
  • rspec-puppet validiert, ob bestimmte Puppet Resourcen so im Katalog sind, wie man sie erwartet
    • korrekte Parameter, Reihenfolge der Resourcen, Prfen ob der Katalog kompiliert

rspec Beispiele

Minimales Beispiel

# import a helper
require 'spec_helper'

# class we want to test
describe 'borg' do
  # mock an FQDN
  let :node do
    'rspec.puppet.com'
  end

  let :facts do
    {
      "operatingsystem": "CentOS",
      "operatingsystemmajversion": 7
    }
  end

  # mock class params if required
  # bad practice, a module should work with default data
  let :params do
    {
      backupserver: 'localhost'
    }
  end

  context 'with all defaults' do
    it { is_expected.to compile.with_all_deps }
  end
end
  • Gefhlt 80% der Probleme kann man damit lsen. Die meisten Fehler fhren dazu, dass der Code nichtmal kompiliert

Prfen der einzelnen Resources:

require 'spec_helper'

describe 'borg' do
  let :node do
    'rspec.puppet.com'
  end

  on_supported_os.each do |os, facts|
    context "on #{os} " do
      let :facts do
        facts
      end

      let :params do
        {
          backupserver: 'localhost'
        }
      end

      context 'with all defaults' do
        it { is_expected.to compile.with_all_deps }

        it { is_expected.to contain_file('/etc/backup-sh-conf.sh') }
        it { is_expected.to contain_file('/etc/borg') }
        it { is_expected.to contain_file('/etc/profile.d/borg.sh') }
        it { is_expected.to contain_file('/usr/local/bin/borg-backup') }
        it { is_expected.to contain_file('/usr/local/bin/borg_exporter') }
        it { is_expected.to contain_file('/etc/borg-restore.cfg') }
        it { is_expected.to contain_class('borg::install') }
        it { is_expected.to contain_class('borg::config') }
        it { is_expected.to contain_class('borg::service') }
        it { is_expected.to contain_ssh__client__config__user('root') }
        it { is_expected.to contain_borg__ssh_keygen('root_borg') }
        it { is_expected.to contain_exec('ssh_keygen-root_borg') }
      end

      case facts[:os]['name']
      when 'Archlinux'
        context 'on Archlinux' do
          it { is_expected.to contain_package('borg') }
          it { is_expected.to contain_package('perl-app-borgrestore') }
        end
      when 'Ubuntu'
        context 'on Ubuntu' do
          it { is_expected.to contain_package('borgbackup') }
          it { is_expected.to contain_package('borgbackup-doc') }
          it { is_expected.to contain_package('gcc') }
          it { is_expected.to contain_package('make') }
          it { is_expected.to contain_package('cpanminus') }
          it { is_expected.to contain_package('libdbd-sqlite3-perl') }
          if facts[:os]['release']['major'] == '16.04'
            it { is_expected.to contain_apt__ppa('ppa:costamagnagianfranco/borgbackup') }
          end
        end
      when 'RedHat', 'CentOS'
        context 'on osfamily Redhat' do
          it { is_expected.to contain_package('perl-local-lib') }
          it { is_expected.to contain_package('perl-Test-Simple') }
          it { is_expected.to contain_package('perl-App-cpanminus') }
          it { is_expected.to contain_package('gcc') }
          it { is_expected.to contain_exec('install_borg_restore') }
          it { is_expected.to contain_file('/opt/BorgRestore') }
          it { is_expected.to contain_file('/usr/local/bin/borg-restore.pl') }
        end
      when 'Gentoo'
        context 'on osfamily Gentoo' do
          it { is_expected.to contain_package('App-cpanminus') }
        end
      when 'Fedora'
        context 'on osfamily Fedora' do
          it { is_expected.to contain_package('perl-Path-Tiny') }
          it { is_expected.to contain_package('perl-Test-MockObject') }
          it { is_expected.to contain_package('perl-Test') }
          it { is_expected.to contain_package('perl-autodie') }
        end
      end
    end
  end
end

Quelle ist das puppet-borg modul

rspec-puppet-facts

  • Puppet Module nutzen fast immer den $facts Hash
  • In Tests muss man die Daten also mocken
  • Das ganze sollte konsistent (z.B. CentOS vs centos) in allen Modulen sein
  • Am liebsten automatisiert durch alle Betriebssysteme in der metadata.json iterieren und fr jedes OS die Facts mocken

rspec-puppet-facts macht genau das!

require 'spec_helper'

describe 'borg' do
  let :node do
    'rspec.puppet.com'
  end

  on_supported_os.each do |os, facts|
    context "on #{os} " do
      let :facts do
        facts
      end

      let :params do
        {
          backupserver: 'localhost'
        }
      end

      context 'with all defaults' do
        it { is_expected.to compile.with_all_deps }
      end
    end
  end
end

Es ist wichtig das alle Betriebssysteme, auf denen ein Modul genutzt wird, auch in der metadata.json stehen!

facterdb

  • rspec-puppet-facts ermglicht das iterieren ber die metadata.json in rspec tests
  • die gemockten factsets kommen aus dme facterdb Projekt
  • Sammlung an Scripten + Vagrant configs um VMs zu starten und darin facter Versionen zu installieren
  • Gesammelten Daten werden als Ruby gem released

Fr alle genutzten Betriebssysteme sollten in dem Projekt factsets sein!

Beaker

  • Acceptance testing framework fr Puppet
  • Startet Virtualbox/Docker Instanz, fhrt darin das Puppet Modul aus
  • Idempotenz kann getestet werden
    • Puppet Modul zwei mal ausfhren, zweiter run darf keine nderungen zeigen
  • Mit rspec/serverspec kann das System inspiziert werden
    • Prfen ob Packete installiert sind
    • Ob Services gestartet sind und laufen
    • Ob TCP ports offen sind
    • Und vieles mehr
require 'spec_helper_acceptance'

describe 'zabbix::server class' do
  context 'default parameters' do
    # Using puppet_apply as a helper
    it 'works idempotently with no errors' do
      # this will actually deploy apache + postgres + zabbix-server + zabbix-web
      pp = <<-EOS
        class { 'postgresql::server': } ->
        class { 'zabbix::database': } ->
        class { 'zabbix::server': }
      EOS

      shell('yum clean metadata') if fact('os.family') == 'RedHat'

      # Run it twice and test for idempotency
      apply_manifest(pp, catch_failures: true)
      apply_manifest(pp, catch_changes: true)
    end

    # do some basic checks
    describe package('zabbix-server-pgsql') do
      it { is_expected.to be_installed }
    end

    describe service('zabbix-server') do
      it { is_expected.to be_running }
      it { is_expected.to be_enabled }
    end
  end
end

Quelle der Tests ist das voxpupuli/zabbix Modul.

puppet-lint

  • Ruby Projekt um verschiedene Styles in der Puppet DSL zu checken / erzwingen
  • Bietet ein Plugin-System
    • Jeder Check ist ein Plugin / eigenstndiges Ruby gem
    • Die meisten Plugins haben eine Autokorrekturfunktion

Liste der aktuell empfohlenen plugins:

Gemfile:

  gem 'puppet-lint-leading_zero-check',                             :require => false
  gem 'puppet-lint-trailing_comma-check',                           :require => false
  gem 'puppet-lint-version_comparison-check',                       :require => false
  gem 'puppet-lint-classes_and_types_beginning_with_digits-check',  :require => false
  gem 'puppet-lint-unquoted_string-check',                          :require => false
  gem 'puppet-lint-variable_contains_upcase',                       :require => false
  gem 'puppet-lint-absolute_classname-check', '>= 2.0.0',           :require => false
  gem 'puppet-lint-topscope-variable-check',                        :require => false
  gem 'puppet-lint-legacy_facts-check',                             :require => false
  gem 'puppet-lint-anchor-check',                                   :require => false

man kann in der Puppet DSL gezielt einzelne Linter deaktivieren, sofern sie ein False/Positive liefern:

# lint:ignore:case_without_default

Fr Fehlermeldungen in einem sinnvollen Format kann man folgendes in seinem Rakefile eintragen:

PuppetLint.configuration.log_format = '%{path}:%{line}:%{check}:%{KIND}:%{message}'

Fr neue Komponentenmodule sollte man auch puppet-lint-param-docs nutzen. Dies erzwingt Dokumentation fr jeden Parameter.

Ausgabe mit Fehler:

$ bundle exec rake lint
manifests/init.pp:106:arrow_on_right_operand_line:WARNING:arrow should be on the right operand's line

Ausgabe mit Autokorrektur:

$ bundle exec rake lint:auto_correct
manifests/init.pp:106:arrow_on_right_operand_line:FIXED:arrow should be on the right operand's line

puppet-syntax

  • Checkt die Syntax der Puppet DSL mit puppet parser
  • Checkt die Syntax von erb Templates mit Ruby
  • Checkt die Syntax von EPP Templates mit puppet
  • Checkt die Syntax von Hiera YAML Datein
    • Prft auf valides YAML
    • Prft auf korrekte Syntax der Keys, damit Puppet damit umgehen kann

Beispielhafte Ausgabe vom Rake Task wenn es keine Fehler gibt:

$ bundle exec rake syntax
  ---> syntax:manifests
  ---> syntax:templates
  ---> syntax:hiera:yaml

Ausgabe mit Syntaxfehlern:

$ bundle exec rake syntax
  ---> syntax:manifests
  rake aborted!
  Could not parse for environment production: Syntax error at end of file at demo.pp:2
  Tasks: TOP => syntax => syntax:manifests
  (See full trace by running task with --trace)

RuboCop

  • RuboCop ist ein Linter fr Ruby Datein
  • Er lintet keinen Puppet DSL Code, aber eigenes Types und Provider
  • Er lintet alle Datein mit Tests
  • RuboCop ist sehr schmerzhaft...
    • Hat aber eine autofix Option die relativ gut funktioniert

Ausgabe mit Fehlern:

$ bundle exec rake rubocop
Running RuboCop...
Inspecting 4 files
..C.

Offenses:

spec/spec_helper.rb:8:1: C: Layout/EmptyLines: Extra blank line detected. (https://github.com/bbatsov/ruby-style-guide#two-or-more-empty-lines)

4 files inspected, 1 offense detected
RuboCop failed!

Mit Autokorrektur:

 bundle exec rake rubocop:auto_correct
Running RuboCop...
Inspecting 4 files
Parser::Source::Rewriter is deprecated.
Please update your code to use Parser::Source::TreeRewriter instead
..C.

Offenses:

spec/spec_helper.rb:8:1: C: [Corrected] Layout/EmptyLines: Extra blank line detected. (https://github.com/bbatsov/ruby-style-guide#two-or-more-empty-lines)

4 files inspected, 1 offense detected, 1 offense corrected

puppetlabs_spec_helper

  • gem von Puppet Inc.
  • Hat sehr viele der oben genannten Tools als Abhngigkeit
  • Puppet kmmert sich um korrekte Versionen die untereinander kompatibel sind. Man muss nur noch puppetlabs_spec_helper einbinden
  • Viele Rake Tasks sind bereits mit dabei

Gemfile:

source ENV['GEM_SOURCE'] || "https://rubygems.org"
gem 'puppetlabs_spec_helper'

Rakefile:

require 'puppetlabs_spec_helper/rake_tasks'

Alle Rake Tasks ausgeben:

bundle exec rake -T
rake beaker                    # Run beaker acceptance tests
rake beaker:sets               # List available beaker nodesets
rake beaker:ssh[set,node]      # Try to use vagrant to login to the Beaker node
rake build                     # Build puppet module package
rake build:pdk                 # Build Puppet module with PDK
rake build:pmt                 # Build Puppet module package with PMT (Puppet < 6.0.0 only)
rake check:dot_underscore      # Fails if any ._ files are present in directory
rake check:git_ignore          # Fails if directories contain the files specified in .gitignore
rake check:symlinks            # Fails if symlinks are present in directory
rake check:test_file           # Fails if .pp files present in tests folder
rake clean                     # Clean a built module package
rake compute_dev_version       # Print development version of module
rake help                      # Display the list of available rake tasks
rake lint                      # Run puppet-lint
rake lint_fix                  # Run puppet-lint
rake parallel_spec             # Run spec tests in parallel and clean the fixtures directory if successful
rake parallel_spec_standalone  # Parallel spec tests
rake release_checks            # Runs all necessary checks on a module in preparation for a release
rake rubocop                   # rubocop is not available in this installation
rake spec                      # Run spec tests and clean the fixtures directory if successful
rake spec:simplecov            # Run spec tests with ruby simplecov code coverage
rake spec_clean                # Clean up the fixtures directory
rake spec_clean_symlinks       # Clean up any fixture symlinks
rake spec_list_json            # List spec tests in a JSON document
rake spec_prep                 # Create the fixtures directory
rake spec_standalone           # Run RSpec code examples
rake syntax                    # Syntax check Puppet manifests and templates
rake syntax:hiera              # Syntax check Hiera config files
rake syntax:manifests          # Syntax check Puppet manifests
rake syntax:templates          # Syntax check Puppet templates
rake validate                  # Check syntax of Ruby files and call :syntax and :metadata_lint

Wie verffentlicht man erfolgreich Module und welchen Mehrwert bietet es?

Wie strukturiert man in der Firma seinen Code sinnvoll?

Anforderungen:

  • Irgendwie muss man die ganzen Komponentenmodule seinen Systemen zuweisen
  • Man mchte ffentliche Komponentenmodule parallel zu selbst entwickelten nutzen
  • Einige Systeme sind sehr hnlich, aber doch anders
    • Jeder server hat SSH Passwort Authentifizierung deaktiviert, nur einer nicht
  • Leute mchten Daten schreiben, aber sollen keinen Puppet Code modifizieren mssen/drfen
    • Z.b. festlegen welche Version von interner Software wo luft

Dies lsst sich mit dem Roles and Profiles Pattern lsen

  • Ein Komponentenmodul kapselt Funktionalitt um eine einzige Komponente zu verwalten
  • Ein Profil enthlt "Business-Logik"
    • Es kann die Reihenfolge von Komponentenmodulen setzen
      • z.B. epel Komponentenmodul vor Bird Komponentenmodul ausfhren
    • Es holt sich Business Daten via Hiera
    • Mehrere solche Profile werden in einer Rolle gekapselt
    • Ein Profil kann in mehreren Rollen sein
    • Einem System wird immer nur eine Rolle zugewiesen
    • Profile und Rollen sind jeweils eigene Klassen

(Copyright Craig Dunn)

Wie sieht ein gutes Komponentenmodul aus

  • include modul funktioniert und installiert mir eine Komponente mit sinnvollen und sicheren Standardwerten
  • Es gibt eine README.md
  • Es gibt eine Lizenz
  • Es enthlt keine Business-Logik
    • Irgendetwas, was firmenspezifisch ist
    • Das Modul sollte in jeder Umgebung funktionieren
    • Ansonsten wird das Roles and Profiles Pattern nicht eingehalten
  • Es gibt Unit- und Acceptance Tests
  • Aktuelle Style Guidelines werden eingehalten
  • Parameter mit puppet-strings dokumentiert

Mehrwert durch die Verffentlichung von Komponentenmodulen

  • Ein internes Modul nachtrglich verffentlichen kann Security Probleme mitbringen
    • Es kann potentiell Business-Daten enthalten (Passwrter, IP-Adressen...)
  • Ist an Modul von Anfang an ffentlich:
    • achtet man auf eine sichere Implementierung
    • Enthlt es nie Business-Logik. Diese wird dann im Profil implementiert. Dadurch is das Modul wiederverwendbar
  • Sofern Dokumentation vorhanden ist, wird das Modul von anderen benutzt
    • Man bekommt pltzlich Bug Reports und Feature Requests, die potentiell mehr / unvorgergesehene Arbeit erzeugen
    • Man bekommt auch Pull Requests mit neuen Features und auch Bug Fixes

Es kommt vor, dass man ein ffentliches Modul patchen muss. Man muss versuchen diese Patches Upstream gemerged zu bekommen. Andernfalls difft der Fork immer mehr von Upstream ab und man landet in der Abhngigkeitshlle. Bei Modulen von Vox Pupuli / Puppet wird tendenziell schneller reagiert als bei Modulen mit einzelnen Maintainern. Puppet hat viele Mitarbeiter mit Commit Rechten fr Ihre Module, Vox Pupuli hat > 140 (unregelmige) Maintainer. Auerdem gibt es hier Esakalationsmglichkeiten.

Mehrwert durch Communities

  • Vox Pupuli, Foreman, CERN, CamptoCamp, Puppet Inc und weitere Gruppen / Organisationen / Firmen pflegen viele Komponentenmodule
  • Ein Team kmmert sich um alle generischen Datein in den Modulen
    • Einheitliche Testmatrix
    • Einheitliches Testsetup
    • Einheitliches Gemfile
  • Die ganze Community hilft beim beantworten von Issues / Pull Requests
  • Oftmals findet man hier schon ein fertiges Modul fr seinen Usecase

modulesync

  • modulesync wurde von Puppet Angestellten entwickelt
  • Von Anfang an Open Source, mittlerweile von Vox Pupuli betreut
  • In einem Git Repository liegen Templates, diese werden auf alle verwalteten Module angewand
  • nderungen kann man auf Modul Ebene berschreiben
  • Eine Hand voll Leute knnen damit >120 Module verwalten
  • Modulesync definiert auch die komplette Testmatrix fr alle Module
  • Viele Firmen nutzen die Vox Pupuli Konfigurationen fr interne Module / man kann modulesync aber auch unabhngig benutzen

Weiterfhrende Dokumentation

Grundlagen fr Continuous Integration

  • Jede nderung sollte getestet werden
  • Testergebnisse sollten mglichst schnell sichbar sein
  • Tests mssen reproduzierbar sein
  • Tests mssen in einer sauberen Umgebung ausgefhrt werden, z.B. nspawn/Docker Container oder einer VM
  • Tests mssen auf einer zentralen Platform ausgefhrt werden
    • Jenkins
    • Gitlab-CI
    • Travis
  • Je mehr ffentliche Module man nutzt, desto weniger muss man lokal testen
    • Die einzelnen Communities haben eine eigene Testinfrastruktur mit passender testmatrix
  • Acceptance Tests fr Controlrepos sind komplex zu bauen. Onceover hilft dabei
    • Ordentliche Tests in allen Komponentenmodulen ist wesentlich einfacher
    • Acceptance Tests in jedem Komponentenmodul sollte Daten aus den eigenen Profilen enthalten
  • Prft jede metadata.json:
    • Alle bentigten Module mssen als Dependencies gelistet sein
    • Alle Betriebssysteme mssen dort gelistet sein
  • Spec Tests mssen rspec-puppet-facts nutzen
  • Alle genutzten Betriebsysteme mssen in facterdb sein
  • Irgendwo muss noch ein Peer Review vorkommen

Grundlagen fr interne CI

  • Man bentigt eine Testmatrix. Fr Unit Tests (im Optimalfall):
    • Gegen alle Ruby Versionen die man nutzt
    • Gegen alle Puppet Versionen die man nutzt
    • Gegen alle Betriebssysteme die man nutzt
  • Automatische Lizenzprfung aller Abhngigkeiten
  • CPU Leistung: Viel hilft viel!
    • Wenn genug Leistung zur Verfgung steht, kann man fr jeden Test eine Dockerinstanz parallel starten
  • Abhngigkeiten: Fehler frh erkennen
    • In der Regel nutzt man fr Unit Tests die Master Branches der Abhngigkeiten, um noch nicht releaste Inkompatibilitten frh zu erkennen
    • Fr Acceptance Tests nutzt man die neusten Releases der Abhngigkeiten
  • Bei Neuen Modulversionen:
    • Die Abhngigkeiten in der ganzen Environment prfen mit puppet module list --environment production --tree
    • In /var/log/puppetlabs/puppetserver/puppetserver.log nach Warnungen / Fehlern schauen

Vorteile einer CI Pipeline

  • Steigerung der Codequalitt
  • Erzwingen einer mglichst einheitlichen Codebasis
  • Potentielle Fehler/Bugs/unerwnschtes Verhalten erkennen bevor es passiert
  • Inkompatibilitten in der Zukunft erkennen und vorbeugen, damit diese nicht eintreten
  • Gibt Mitarbeitern mehr Selbstbewusstsein nderungen zu machen
    • Verringert auch die Einstiegshrde fr andere Administratoren

Anforderungen an eine lokale CI/CD/CD Platform

  • Ergebnisse mssen schnell und einfach ersichtlich sein
  • Testumgebungen mssen schnell verfgbar sein
    • R10k nutzen zum ausrollen von Environments
    • tar.gz Artefakte oder git tags/commits deployen, keine branches
    • Git Server Webhooks nehmen und Testenvironments zu erstellen sobald Commits / Branches gepusht werden
      • Puppet Webhook Server + Choria / mcollective / Bolt zum ausrolen

SSH Multiplexing aktivieren um git clones zu beschleunigen:

class profiles::ssh2git {
 # /root/.ssh/config entry to access git.internal
 ssh::client::config::user { 'gitaccess':
   ensure        => present,
   user          => 'root',
   user_home_dir => '/root',
   options       => {
     'Host git.internal' => {
       'User'           => 'git',
       'IdentityFile'   => '~/.ssh/id_ed25519...',
       'ControlMaster'  => 'auto',
       'ControlPath'    => '~/.ssh/ssh-%r@%h:%p',
       'ControlPersist' => '10m'
     },
   },
 }
 sshkey { 'git.internal':
   ensure       => 'present',
   target       => '/root/.ssh/known_hosts',
   type         => 'ecdsa-sha2-nistp256',
   key          => 'DATA',
 }
}

r10k mit mehreren Workern starten:

# puppet/r10k from Vox Pupuli
class { 'r10k':
  version   => '3.5.0',
  pool_size => 10,
}

CI Dokumentation

Grundlagen Continuous Delivery und Continuous Deployment

Continuous Delivery

  • Continuous Delivery - nach einem erfolgreichen CI Durchlauf Buildartefakte bauen und in einem Repository speichern
  • Artefakte knnen verschiedenste Formen haben
    • Ruby gem / Python Package
    • Docker Image
    • rpm / deb Paket
    • Puppet Modul
    • Ein generisches .tar.gz Archiv

Continuous Delivery fr Puppet Module

Es gibt viele Mglichkeiten Puppet Module zu speichern.

Folgende Projekte untersttzen Puppet Modul Releases(.tar.gz Archive):

Alternativ kann man mit git tags / commit ids im Puppetfile arbeiten.

Continuous Deployment

  • Continuous Deployment - Build Artefakte mglichst automatisiert in die Produktivumgebung bringen

Mit Puppet eine groe Menge an Scripten als File Resources verteilen ist ein Antipattern. Diese sollte man als Artefakte Paketieren. Puppet richtet dann das Repository auf den Zielsystemen ein. Dies gillt fr alle Artefakte, welche Puppet deployen soll.

Bei vielen Projekten bietet sich ein gitflow-workflow an:

  • Develop Umgebung luft auf einem individuellen Dev Branch
  • Test Umgebung luft auf dem Develop Branch
  • Staging/Integreation Umgebung luft auf Master Branch
  • Git Tags basieren auf Master Branch. Diese werden nach Produktion deployed

Dies funktioniert sehr gut fr intern entwickelte Anwendungen die auf anderen internen Tools aufsetzen und wiederum von anderen Teams genutzt werden. Fr jede Umgebung bentigt man eigene Repositories und Maschinen/Server/Docker Images. Puppet kann solche Umgebungen deployen. Puppet Code selbst mit so einem Workflow zu verwalten funktioniert in der Regel nicht / bringt viel zu viel Overhead mit sich.

Fr Puppet hat sich in den meisten Organisationen ein Git Feature Branch Workflow als beste Lsung etabliert.

  • Im Control-Repository ist der Standardbranch production. Dieser wird als Environment auf normalen Nodes genutzt
  • Zum testen / entwickeln erzeugt man einen Feature Branch im Control-Repository + ggf im entsprechenden Modul
  • Push eines Branches im Control-Repo erzeugt via hooks die Environment auf den Puppetservern
  • Bei Merges wird Production neu deployed

Review der Puppetumgebung

Dedizierter Vortrag ber Puppetserver Skalierung

Grundstzliches zum Tuning

  • PuppetDB / Puppetserver CA / Compile Puppetserver / Foreman / PostgreSQL / Choria haben verschiedene Anforderungen an Hardware und kann man gut auf einzelnen Systemen installieren
  • Ein verteiltes System ist immer nur so stark wie ihr schwchstes Glied
  • Tuning Optionen sind immer stark abhngig von der Anzahl der Resources pro Node / Runinterval / Funktionen
    • Die Werte sollten deshalb nicht blind bernommen werden
    • Es sollte immer nur ein Wert gleichzeitig gendert werden um die Auswirkungen besser zu verstehen

PuppetDB

Hiera Tuningoptionen fr puppetlabs/puppetdb:

---
puppetdb::server::java_args:
  '-Xmx': '8192m'
  '-Xms': '2048m'
puppetdb::server::node_ttl: '14d',
puppetdb::server::node_purge_ttl: '14d',
puppetdb::server::report_ttl: '999d'
# default is 50
puppetdb::server::max_threads: 100
# default is processorcount / 2
puppetdb::server::command_threads: %{facts.processors.count}
# default is 4, have your database in mind
puppetdb::server::concurrent_writes: 8
puppetdb::server::automatic_dlo_cleanup: true

PostgreSQL

Optionen fr puppetlabs/postgresql:

Anzahl der Verbindungen erhhen:

postgresql::server::config_entry{'max_connections':
  value => 400,
}

Laufenden PostgreSQL Server analysieren und eine optimierte Konfiguration generieren:

pgtune -i /var/lib/pgsql/10/data/postgresql.conf -o postgresql.conf

Fr PostgreSQL empfiehlt sich deren eigenes Yum Repository. Die Upstream Pakete erlauben es beliebige Versionen parallel zu installieren. Auerdem bekommt das Yum Repository am schnellsten Sicherheitsupdates. PostgreSQL hat in jeder neuen Version viele Geschwindigkeitsoptimierungen. Es sollte immer geprft werden mit welcher neusten PostgreSQL Version PuppetDB funktioniert und diese dann genutzt werden. PuppetDB 6 und 7 in Puppet Enterprise nutzen PostgreSQL 11. Nutzer von PuppetDB 7 haben auch berichtet, dass sie erfolgreich PostgreSQL 13 einsetzen.

Neben dem autovacuum, welches als gelscht markierte Tuples entfernt, bietet sich auch die Nutzung von pg_repack an. Fr Puppet Enterprise wird dies mit dem pe_databases Modul konfiguriert. pg_repack kann Tabellen und Indexe aufrumen sowie die PostgreSQL Daten im Dateisystem neu ordnen. Somit bentigen Queries weniger IO.

Hier die 3 Timer + Services aus einer PE Umgebung extrahiert.

# /etc/systemd/system/pe_databases-catalogs.service
[Unit]
Description=Service to repack PE database tables
Wants=pe_databases-catalogs.timer

[Service]
User=pe-postgres
Group=pe-postgres
Type=oneshot
ExecStart=/opt/puppetlabs/server/apps/postgresql/11/bin/pg_repack -d pe-puppetdb --jobs 3 -t catalogs -t catalog_resources -t catalog_inputs -t edges -t certnames

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/pe_databases-catalogs.timer
[Unit]
Description=Timer to trigger repacking PE database tables

[Timer]
OnCalendar=Sun,Thu *-*-* 04:30:00
Persistent=true

[Install]
WantedBy=timers.target

# /etc/systemd/system/pe_databases-facts.service
[Unit]
Description=Service to repack PE database tables
Wants=pe_databases-facts.timer

[Service]
User=pe-postgres
Group=pe-postgres
Type=oneshot
ExecStart=/opt/puppetlabs/server/apps/postgresql/11/bin/pg_repack -d pe-puppetdb --jobs 3 -t factsets -t fact_paths

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/pe_databases-facts.timer
[Unit]
Description=Timer to trigger repacking PE database tables

[Timer]
OnCalendar=Tue,Sat *-*-* 04:30:00
Persistent=true

[Install]
WantedBy=timers.target

# /etc/systemd/system/pe_databases-other.service
[Unit]
Description=Service to repack PE database tables
Wants=pe_databases-other.timer

[Service]
User=pe-postgres
Group=pe-postgres
Type=oneshot
ExecStart=/opt/puppetlabs/server/apps/postgresql/11/bin/pg_repack -d pe-puppetdb --jobs 3 -t producers -t resource_params -t resource_params_cache

[Install]
WantedBy=multi-user.target

# /etc/systemd/system/pe_databases-other.timer
[Unit]
Description=Timer to trigger repacking PE database tables

[Timer]
OnCalendar=*-*-20 05:30:00
Persistent=true

[Install]
WantedBy=timers.target

Foreman

Hiera Optionen fr theforeman/foreman:

---
# default is 5
foreman::db_pool: 20
foreman::keepalive: true
foreman::max_keepalive_requests: 1000
foreman::keepalive_timeout: 180

Foreman luft via Passenger. Dieser wird mit puppetlabs/apache aufgesetzt. Multithreading hochdrehen:

---
apache::mod::passenger::passenger_max_pool_size: %{facts.processors.count}
apache::mod::passenger::passenger_min_instances: %{facts.processors.count}

Foreman kann memcached als Cache nutzen:

Via Puppet installieren:

# https://forge.puppet.com/saz/memcached
include memcached
include foreman::plugin::memcache

Via Hiera einstellen:

---
# 50GB of cache
memcached::max_memory: 51200
foreman::plugin::memcache::hosts:
  - 127.0.0.1

Puppetserver

Puppetlabs bietet im Modul puppetlabs/puppet_metrics_dashboard einen Monitoring Stack fr Puppetserver. Dieser bietet JVM Metriken via JMX und Puppetserver Metriken via Graphite.

  • Eine JVM Instanz pro (logischen) CPU Kern funktioniert gut
    • Auf modernen CPUs auch gern 2 Instanzen pro Kern
  • ~800-1500 Resources pro katalog vertragen 2GB Heap pro JVM Instanz (server_jvm_max_heap_size)
  • Puppetserver kann zum starten weniger Ram allokieren, dies verkrzt die Bootstrap Zeit
  • Puppetserver hat einen Class Cache, welchen man aktivieren kann
  • Jede JVM Instanz hat einen Cache, dieser wird besser je lnger er luft
    • Serverseitige Funktionen mit memory Leaks fhren zu Problemen
    • Jeder Restart ttet den Cache
    • server_max_requests_per_instance auf unendlich setzen oder mindestens 500.000
      • Die Option startet die JVM Instanz neu nachdem die Anzahl der Requests bearbeitet wurde, dies resettet den Cache
      • Man sollte die Option also nur setzen wenn man irgendwo im Code Memory leaks einer Puppet Funktion vermutet
  • Mehrere Puppetserver kann man via DNS Round Robin skalieren
  • HAProxy/Nginx als Proxy davor funktioniert besser als Round Robin
    • Whrend eines Agent runs sollte der Agent immer mit dem gleichen Backend sprechen, der Loadbalancer/Proxy muss dies beachten
  • nginx wurde gern zum terminieren von TLS Verbindungen direkt auf Puppetservern genutzt
  • file Reports sind unntig und bentigen oft IO/s und Inodes (grep ^reports /etc/puppetlabs/puppet/puppet.conf)
  • Jede file Ressource mit einer Puppetserver URL (puppet:///) kann zu einem eigenen HTTP Request vom Agent zum Puppetserver fhren
    • source => puppet:///modules/... durch content => file(${module_name}/) ersetzen
    • Damit liest der Puppetserver die Datei ein whrend der Katalog kompiliert wird und bindet diese dort ein
    • Nachteil: Katalog wird grer; Vorteil: Weniger HTTP Verbindungen. Gerade bei Textdatein lohnt sich dies
    • Groe Binrdatein sollten damit nicht verteilt werden. Diese sollten immer anders bertragen werden (z.b. sauber paketiert)

Hiera Optionen fr theforeman/puppet:

$cpu_count_twice = $facts['processors']['count'] * 2
$cpu_count = $facts['processors']['count'] * 1
class{'puppet':
  server_jvm_min_heap_size               => "${cpu_count}G",
  server_jvm_max_heap_size               => "${cpu_count_twice}G",
  server_max_requests_per_instance       => 500000,
  server_max_queued_requests             => $cpu_count,
  server_environment_class_cache_enabled => true,
  server_jvm_extra_args                  => ['-XX:ReservedCodeCacheSize=2G'],
}

Upgrades und kompatible Versionen

Folgende Puppet Komponenten sind untereinander Kompatibel

Puppet Agent Puppetserver PuppetDB
6.x 6.x 6.x
5.x 6.x 6.x
4.x 6.x 6.x
7.0.0 6.14.1 6.13.1
7.0.0 6.14.1 7.0.0
6.19.1 6.14.1 7.0.0

Puppet 6 zu 7 Upgrade

  • Puppet Agent 7 funktioniert mit Puppetserver 6 / PuppetDB 6
  • Puppet Agent 7 funktioniert mit Puppetserver 6 / PuppetDB 7

Es empfiehlt sich folgender Upgrade Pfad:

  • Puppet 7 zur CI Pipeline hinzufgen und sicherstellen, dass die Module mit Puppet 7 funktionieren
  • Die einzelnen Agents auf die neusten Puppet 6 Version updaten
    • Wenn dies erfolgreich war, die Agents auf Version 7 updaten
  • PuppetDB von 6 auf 7 Updaten
    • Whrend des Updates erfolgen Datenbank Migrationen. Je nach Anzahl der Reports kann dies mehrere Stunden dauern
    • Whrend der Migration ist PuppetDB nicht nutzbar
    • Man kann vor der Migration die TTL fr Reports heruntersetzen und diese damit lschen. Dies reduziert die Downtime
    • Puppetserver knnen danach geupdated werden

Puppet 7 Bugs

Liste an bekannten Bugs, welche groe Auswirkungen haben knnten bei einem Upgrade (Stand 2020-11-24):

Seit Q2 2021 sind keine offenen Bugs bekannt die ein Upgrade von Puppet 6 zu Puppet 7 behindern

Puppet Tipps und Tricks

crl_refresh_interval aktivieren

Auf sehr vielen System wird das Puppet Agent Zertifikat fr einen lokalen Webserver zweckentfremdet. Oft ebenfalls mit Klientzertifikatsvalidierung. Dies funktioniert nur sinnvoll mit einer aktuellen CRL (Certificate Revocation List

  • Liste der von der Puppetserver CA zurckgezogenen Zertifikaten). Beim
    initialen Puppet Lauf wird die CRL vom Puppetserver heruntergeladen, danach
    aber nie aktualisiert. Viele Leute nutzen dafr einen systemd timer um die
    Datei periodisch herunterzuladen. Puppet kann dies seit Version
    6.5.0
    selbst periodisch aktualisieren.

ReservedCodeCacheSize erhhen

Es gibt viele Mythen ber die korrekten Optionen fr die JVM. Die Kurzfassung: -XX:ReservedCodeCacheSize=2G sollte immer der Puppetserver JVM mitgegeben werden. Details dazu gibt es unter PUP-10225 sowie SERVER-2771. Dies behebt 99% der Performanceprobleme die Leute nach dem Upgrade von Puppetserver 5 haben. Langfristig soll die Option standardmig im Puppetserver gesetzt sein. Puppet Inc ist leider etwas trge was das updaten der Doku/Pakete angeht. Nhere Informationen zu der Option gibt es in der offiziellen Java Dokumentation. Auerdem hat Baeldung dazu noch einen Artikel Der Blog ist eine sehr gute Anlaufstelle fr Artikel ber Java, JVM und Spring.

Der Default Wert betrgt, je nach Java Version, 48MB. Dies ist fr Java Applikationen oftmals vollkommen ausreichend. Fr Jruby wird allerdings wesentlich mehr bentigt.

Code Cache Nutzung protokollieren

Um die Ramnutzung etwas transparenter zu gestalten kann man die JVM Option -XX:+PrintCodeCache setzen. Damit loggt diese die Nutzung/Auslastung des Code Caches.

Garbage Collection Logging aktivieren

Puppetserver und PuppetDB werden innerhalb der JVM ausgefhrt. Diese fhrt regelmig eine Garbage Collection durch. Hierbei werden nicht mehr bentigte Objekte aus dem Arbeitspeicher entfernt. Je mehr Aktivit innerhalb der JVM existiert und je nher der genutzte Ram an der Heap Grenze ist, desto agressiver und fter arbeitet der Garbage Collector. In der Regel luft dieser periodisch zum Puppetserver/PuppetDB. Sollte er Ram nicht freigeben knnen kann es vorkommen, dass er die Applikation kurzzeitiig pausiert. All diese Informationen kann die JVM in eine Logdatei schreiben. Dies ist ntzlich um die Arbeitspeichernutzung zu prfen und ggf den Heap zu vergrern/verringern. Aktiviert wird es mit folgender Option: -Xlog:gc*:file=/gc.log::filecount=16,filesize=20m Dies aktiviert das Logging in die Datei gc.log. Sobald die Datei 20MB Gre erreicht wird die rotiert. Es werden 16 Datein vorgehalten. Fr Puppetserver empfiehlt sich der Pfad /var/log/puppetlabs/puppetserver/puppetserver_gc.log, fr PuppetDB /var/log/puppetlabs/puppetdb/puppetdb_gc.log.

Es gibt verschiedene Tools, welche die Logs auswerten knnen. Eine simple Version ist der Upload auf https://gceasy.io/.

JVM Heap Abbilder schreiben

Sobald die JVM versucht mehr Arbeitsspeicher zu nutzen als verfgbar/Heap erlaubt, luft die JVM in einen Out of Memory Fehler und wird beendet. Sofern dies passiert kann die JVM ein Abbild des Heaps auf das Dateisystem schreiben. Out of Memory Fehler werden provoziert wenn Heap massiv zu klein konfiguriert ist oder ein Puppet Modul irgendeine Funktion bereitstellt die Memory Leaks verursacht. Wenn max_requests_per_instance im Puppetserver gesetzt ist werden Memory Leaks eventuell verschleiert weil die einzelnen JVM Instanzen regelmig neugestartet werden. Die erzeugten Abbilder knnen mit verschiedenen Tools analysiert und visualisiert werden.

dns_alt_names beim initialen Puppet run setzen

Damit mindestens Webbrowser TLS Zertifikate als valide empfinden muss ein FQDN als Subject Alternative Name im Zertifikat gesetzt werden. Chrome erfordert dies seit Version 58. Puppet setzt bis Puppetserver 6.15.3 ausschlielich den alten Common Name. Als Workaround kann man den initialen Puppet run starten mit: puppet agent -t --dns_alt_names=$(hostname -f). Sofern ein Server mehrere FQDNs hat die auf ihn zeigen kann man der Option auch eine Kommaseparierte Liste mitgeben. Seit Puppetserver 6.15.3 bzw. 7.1.0 setzt die Puppetserver CA den Common Name ebenfalls als Subject Alternative Name.

Java 11 und nicht Java 8 nutzen

Je nach Version vom Puppetserver und PuppetDB werden diese mit Java 8 ausgefhrt. Diese Version ist sehr sehr alte. Puppetserver 6 und PuppetDB 6 untersttzen diese auch Java 11. Dies sollte unbedingt genutzt werden. Es empfiehlt sich regelmig die Release Notes zu prfen. Sobald eine neuere Java Version untersttzt wird sollte auf diese gewechselt werden. Beide Dienste funktionieren sehr gut mit OpenJDK/AdoptJDK. Es wird kein Java von Oracle bentigt.

$trusted['certname'] und nicht $facts['networking']['fqdn'] nutzen

Oftmals wird innerhalb der Puppet DSL der FQDN vom Agent bentigt. Hierzu gibt es viele Optionen. Veraltet sind:

  • $fqdn
  • $::fqdn
  • $facts['fqdn']

Diese drei optionen sind veraltet. Alternativ soll $facts['networking']['fqdn'] genutzt werden. Dies liefert den FQDN zurck. Dieser kann aber auf dem Quellsystem sehr einfach gendert und manipuliert werden. In den meisten Fllen ist $trusted['certname'] die bessere Option. Dies ist der Common Name aus dem Zertifikat des Agents. In der Regel entspricht dies dem FQDN des Agents whrend des ersten Puppet runs.

trusted_external_command nutzen um Inventarsysteme einzubinden

Oft hat man Innerhalb einer Firma ein zentrales Inventarsystem. Leider meistens sogar mehrere. Oft enthalten diese Informationen die man auch innerhalb einer Puppet Umgebung nutzen mchte. Oft werden z.b. die Teamzugehrigkeit oder offene Problemtickets in der motd eines Servers verlinkt. Mit der trusted_external_command Option kann man auf dem Puppetserver ein Script hinterlegen. Diesem wird als erster Parameter der Common Name des anfragenden Agents bergeben. Das Script kann sich dann zu externen Systemen verbinden und dort die Informationen ermitteln. Puppet erwartet als Antwort einen JSON Hash. Dieser wird in den Hash $trusted['externa'] eingefgt und ist innerhalb des Puppet Codes verfgbar. Puppet Code kann $trusted nicht berschreiben, nur lesen.

Ein gutes Beispiel hierfr ist das servicenow Modul von Puppet Inc. ServiceNow ist ein cloudbasiertes Inventarsystem. Das Script fr den trusted_external_command gibt es hier.

Achtung: Die Lizenz erlaubt nur eine Nutzung mit Puppet Enterprise.

server_max_open_files erhhen

Jeder Prozess darf unter Linux eine bestimmte Anzahl offener Dateideskriptoren haben. Dies sind zum groen Teil geffnete Datein und TCP Sockets. Das Limit lsst sich mit ulimit -Sn auslesen und betrgt auf den meisten Systemen 1024 fr normale Benutzer (Soft Limit). Diese knnen es manuell auf den Wert von ulimit -Hn erhhen (Hard Limit). Ein Puppetserver mit vielen JVM Instanzen, der eventuell mit mehreren externen Diensten (Report Prozessor, trusted_external_command...) kommuniziert, bentigt oftmals mehr offene Dateideskriptoren. Die aktuell offenne Dateideskriptoren lassen sich wie folgt ermitteln: find /proc/$(pgrep -f puppetserver)/fd | wc -l Mit dem puppetserver Puppet Modul lsst sich das limit erhhen:

puppet::server_max_open_files: 16384

Es gibt noch ein globales Limit welches der Linux Kernel vorgibt. Dies erhlt man mit sysctl fs.file-max. Es kann ebenfalls ber Puppet erhht werden:

sysctl { 'fs.file-max':
  ensure => 'present',
  value => '9923372036854775807',
  target => '/etc/sysctl.d/99-puppet.conf',

Sofern dies ntig ist deuted es immer auf ein Problem auf dem Server hin! Weitere Informationen findet man in der Linux Kernel Dokumentation.

digest_algorithm von md5 auf sha256 ndern

digest_algorithm bestimmt das Hashverfahren mit dem Datein vergleichen werden. Puppetserver erzeugt Prfsummen fr Datein auf dem Puppetserver. Der Agent fhrt das gleiche lokal durch und genderte Datein zu erkennen. Bis einschlielich Puppet 6 wird hier das veraltete md5 genutzt. Seit Puppet 7 ist der Standardwert sha256. ltere Puppet 4/5/6 Umgebungen sollten ebenfalls auf sha256 gendert werden. Sofern bentigt, kann man dies auch auf sha512 ndern. Dies ist eventuell fr einige Zertifizierungen/Audits notwendig. Die Option wird in der puppet.conf gesetzt.

key_type von rsa auf ec wechseln

Standardmig nutzt Puppet Agent veraltete Zertifikate mit dem RSA Verfahren. Seit Puppet 6.5.0 kann man aber aber Zertifikate auf Basis von Elliptischen Kurven nutzen. Dafr muss in der puppet.conf vor dem ersten Puppet Run (Bevor ein Zertifikat vorhanden ist) die Option key_type auf ec gesetzt werden. Zertifikate auf Basis Elliptischer Kurven gelten als Zukunftssicher und bentigen weniger Speicherplatz.

graph Option aktivieren

Der Puppet agent wendet bei jedem Lauf einen Katalog an, den zuvor der Puppetserver kompiliert hat. Dieser besteht aus einem gerichteten Graphen. Alle Ressources die angewendet werden sollen werden untereinander auf implizite und explizite Abhngigkeiten geprft und in eine Reihenfolge gebracht. Manchmal gibt es Probleme den Katalog auf einem Node anzuwenden. Dazu kann der Agent den Graph lokal speichern in verschiedenen Formaten. Die Option ist standardmig deaktiviert, sollte aber aktiviert sein um auch einmalig aufgetretene Fehler im nachhinein noch zu analysieren.

Directed acyclic Graph bei Wikipedia

show_diff aktivieren

Wenn Puppet eine Datei ndern, sei es mit der Concat Resource oder weil die ganze Datei vom Puppetserver kommt oder aus einem Template generiert wird, kann Puppet einen diff anzeigen, wenn show_diff=true gesetzt ist. In dem Fall wird der diff aber auch im Report gespeichert und damit zum Puppetserver zurckgeschickt. Wenn man Reports verarbeitet, z.b. mit Foreman, kann man sich hier die diffs anzeigen lassen. ist show_diff nicht gesetzt oder false kann man im Report nur erkennen das eine Datei gendert wurde, aber nicht wie. Es empfiehlt sich daher die Option zu aktivieren. Reports sollten dann allerdings nicht unverschlsselt bertragen werden da diffs potentiell sensitive Informationen enthalten knnen.

resubmit_facts aktivieren

In einer Agent/Server Umgebung werden Facts auf dem Agent ermittelt und zum Server geschickt. Im Gegenzug bekommt der Agent den kompilierten Katalog zurck und wendet ihn an. Am Ende wird ein Report zum Server geschickt. Es ist mglich, dass der Katalog Einfluss auf Werte irgendwelcher Facts hat (z.B. die Anzahl offener Updates wenn der Katalog Updates bestimmter Pakete erzwingt). Somit sind Facts in der PuppetDB eventuell nicht aktuell nachdem ein Katalog angewand wurde. Sofern man viel mit PuppetDB Queries innerhalb der Puppet Codebasis agiert und Facts anderer Node ausliest, oder sich viele Reports mit eigenen PuppetDB Queries erzeugt ist es sinnvoll dem Agent mitzuteilen, dass er Facts nach dem anwenden des Katalogs nochmal zum Server schicken soll. Dies kann man mit der Option resubmit_facts aktivieren. Somit verdoppelt sich allerdings die Last durch Facts auf der Puppetdb.

summarize aktivieren

Damit wird am Ende eines Agent runs eine Zusammenfassung ausgegeben

Application:
   Initial environment: function
   Converged environment: function
         Run mode: user
Changes:
            Total: 1
Events:
          Success: 1
            Total: 1
Resources:
          Changed: 1
      Out of sync: 1
            Total: 826
Time:
      Concat file: 0.00
   Concat fragment: 0.00
         Schedule: 0.00
             User: 0.00
            Mount: 0.00
   Ssh authorized key: 0.00
           Notify: 0.00
             Exec: 0.00
             Cron: 0.00
              Pam: 0.00
      Ini setting: 0.01
         Shellvar: 0.06
           Sysctl: 0.09
             File: 0.20
          Package: 0.27
          Service: 0.32
   Config retrieval: 1.21
          Vcsrepo: 1.47
         Last run: 1649238895
   Transaction evaluation: 3.93
   Catalog application: 4.01
       Filebucket: 0.00
            Total: 4.05
Version:
           Config: 4d3c463 - Tim Meusel, Fri Apr 1 14:42:05 2022 +0200 : Add test foo
           Puppet: 7.14.0

write-catalog-summary aktivieren

Damit legt Puppet /opt/puppetlabs/puppet/cache/state/{last_run_report,last_run_summary}.yaml an. Beide Datein enthalten Informationen ber den letzten Puppet Run, die Laufzeit einzelner Ressourcen und vorhandene Tags.

strict_variables

Wenn die Option aktiv ist, wird ein Compile Error bei der Verwendung nicht initialisierter Puppet Variablen erzeugt. Upstream Doku

strict auf error setzen

Damit wird Puppet Code validiert und ein Compile Error erzeugt, sofern es Fehler gibt. Upstream Doku

trace

Sollte es irgendwelche Ruby Fehler geben, wird ein Trace davon ausgegeben.

Puppet Agent via Timer steuern

Standardmig luft Puppet als Agent, in einem 30 Minuten Interval. Mit der splay Option lassen sich die Agents auch etwas verteilen, es kommt aber trotzdem oft zu einem Schwarmverhalten. Dem kann man entgegen wirken, in dem man den Puppet Agent nicht als Daemon, sondern mit System Timern laufen lsst.

$puppet_timer_runinterval = 30 # run interval in minutes
$puppet_timer_command = '/opt/puppetlabs/bin/puppet agent --onetime --summarize --no-splay --verbose --no-daemonize --detailed-exitcode --show-diff'
$first_run = fqdn_rand($puppet_timer_runinterval)
$second_run = $first_run + $puppet_timer_runinterval
# lint:ignore:strict_indent
$_timer = @("EOT")
# THIS FILE IS MANAGED BY PUPPET
[Unit]
Description=Systemd Timer for Puppet Agent

[Timer]
Persistent=true
OnCalendar=*-*-* *:${first_run},${second_run}:00

[Install]
WantedBy=timers.target
| EOT

$_service = @("EOT")
# THIS FILE IS MANAGED BY PUPPET
[Unit]
Description=Systemd Timer Service for Puppet Agent
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=${puppet_timer_command}
SuccessExitStatus=2
User=root
Group=root
| EOT
# lint:endignore:strict_indent

# we should not use the name puppet or puppet-agent. That .service might already exist
systemd::timer { 'puppet-timer.timer':
  timer_content   => $_timer,
  service_content => $_service,
  active          => true,
  enable          => true,
}

PDF

pandoc ermglicht es aus dieser markdown Datei eine pdf zu generieren. Die gngigen Linux Distributionen haben pandoc in ihren Repositories. Der simpelste Aufruf lautet wie folgt:

pandoc --from markdown README.md --output puppet.pdf

Und fr die puppet.pdf hier im Repo:

pandoc README.md --output puppet.pdf "-fmarkdown-implicit_figures -o" --from=markdown -V geometry:margin=.4in --toc --highlight-style=espresso

Lizenz

Dieses Dokument steht unter der CC BY-NC-SA 4.0 Lizenz. Codebeispiele sind unter der GNU Affero General Public License v3.0 lizensiert. Fr kommerzielle Anfragen, Nachfragen zu Consulting oder Feedback kontaktieren sie bitte [email protected].

Anmerkungen