Automatizzare Barman con Puppet: it2ndq/barman (parte tre)

robotNella seconda parte di questa serie di articoli abbiamo configurato via Puppet due virtual machine con un server PostgreSQL e un server Barman in modo che il secondo potesse eseguire il backup della prima. Tuttavia, era comunque richiesto l’intervento umano per effettuare lo scambio delle chiavi SSH e una buona parte del manifesto era utilizzata per rendere disponibili gli accessi ai due server.
In questa terza e ultima parte dell’articolo vedremo come configurare una terza VM che faccia da Puppet Master e come utilizzarla per semplificare la configurazione di PostgreSQL e Barman.

L’intero codice usato in questo tutorial è presente su GitHub all’indirizzo https://github.com/2ndquadrant-it/vagrant-puppet-barman.

Configurare il Puppet Master: Vagrant

Innanzitutto, occorre modificare il Vagrantfile per avviare una terza macchina, chiamata puppet, che sarà il nostro Puppet Master. Questa macchina dovrà essere subito raggiungibile dagli agenti Puppet presenti su ognuna delle VM create, per cui, all’interno del primo script che lanciamo, configuriamo una entry per il suo indirizzo in /etc/hosts.

Sempre nello script inline dobbiamo abilitare l’agente Puppet. Questo è infatti disabilitato di default nelle distribuzioni derivate da Debian.

Infine, all’interno del Vagrantfile, andiamo ad effettuare una distinzione fra master e agenti. Il primo caricherà la propria configurazione direttamente da file, gli agenti lo faranno chiedendola al master e inviandogli i dati che devono scambiarsi con gli altri nodi. Per quest’ultima ragione un agente è impostato per girare anche sul master.

Il Vagrantfile prodotto è il seguente:

Vagrant.configure("2") do |config|
  {
    :puppet => {
      :ip      => '192.168.56.220',
      :box     => 'ubuntu/trusty64',
      :role    => 'master'
    },
    :pg => {
      :ip      => '192.168.56.221',
      :box     => 'ubuntu/trusty64',
      :role    => 'agent'
    },
    :backup => {
      :ip      => '192.168.56.222',
      :box     => 'ubuntu/trusty64',
      :role    => 'agent'
    }
  }.each do |name,cfg|
    config.vm.define name do |local|
      local.vm.box = cfg[:box]
      local.vm.hostname = name.to_s + '.local.lan'
      local.vm.network :private_network, ip: cfg[:ip]
      family = 'ubuntu'
      bootstrap_url = 'https://raw.github.com/hashicorp/puppet-bootstrap/master/' + family + '.sh'

      # Run puppet-bootstrap and enable the Puppet agent
      local.vm.provision :shell, :inline => <<-eos
        if [ ! -e /var/tmp/.bash.provision.done ]; then
          echo "192.168.56.220  puppet.local.lan        puppet puppetdb puppetdb.local.lan" >> /etc/hosts
          curl -L #{bootstrap_url} | bash
          puppet agent --enable
          touch /var/tmp/.bash.provision.done
        fi
      eos

      if cfg[:role] == 'master'
        # Puppet master needs RAM
        local.vm.provider "virtualbox" do |v|
          v.memory = 1024
        end

        # Provision the master with Puppet
        local.vm.provision :puppet do |puppet|
          puppet.manifests_path = "manifests"
          puppet.module_path = [".", "modules"]
          puppet.manifest_file = "site.pp"
          puppet.options = [
           '--verbose',
          ]
        end
      end

      # Puppet agents should be provisioned by the master
      local.vm.provision :puppet_server do |puppet|
        puppet.options = [
         '--verbose',
        ]
      end

    end
  end
end

Configurare il Puppet Master: Puppet

Una volta in possesso del Vagrantfile è il momento di andare a modificare il manifesto Puppet per attivare il master.
Prima di fare questo, però, è necessario installare altri due moduli: puppetlabs/puppetdb e stephenrjonson/puppet.

puppetlabs/puppetdb configura PuppetDB. PuppetDB utilizza un database PostgreSQL per raccogliere i fatti e le risorse esportate dai vari nodi dell’infrastruttura, in modo che questi possano scambiarsi informazioni e configurarsi uno in base agli altri.
stephenrjonson/puppet permette di configurare un server Puppet Master con Apache e Passenger, nonché di configurare gli agenti sui vari nodi della rete.

Modifichiamo quindi il Puppetfile in:

forge 'https://forgeapi.puppetlabs.com'
mod 'it2ndq/barman'
mod 'puppetlabs/postgresql'
mod 'puppetlabs/puppetdb'
mod 'stephenrjohnson/puppet'

Rispetto all’articolo precedente abbiamo rimosso la dipendenza dall’ultima versione su GitHub per il modulo it2ndq/barman, del quale è stata rilasciata la versione 1.0.0 (che utilizzeremo) negli ultimi giorni. Eseguiamo:

$ librarian-puppet install --verbose

A questo punto possiamo andare a modificare il manifesto site.pp, aggiungendo il nodo puppet e inserendo al suo interno il seguente frammento di codice per PuppetDB e il Puppet Master:

  # Setup PuppetDB
  class { 'puppetdb': }->
  # Setup Puppet Master, Apache and Passenger
  class { 'puppet::master':
    storeconfigs => true,
    autosign     => true,
    environments => 'directory',
  }->

Abbiamo così configurato il Puppet Master per accettare automaticamente connessioni da tutte le macchine (autosign) e distribuire i cataloghi, i fatti e le risorse esportate (storeconfig).
Infine, utilizziamo i directory environment di Puppet per distribuire il catalogo agli agenti. La directory standard per gli ambienti è /etc/puppet/environments e l’ambiente di default è production. Inseriamo quindi i nostri manifesti e moduli al suo interno. Poiché Vagrant già condivide la directory in cui si trova il Vagrantfile con le macchine create, possiamo fare un link simbolico a questa directory:

  # Have the manifest and the modules available for the master to distribute
  file {
    ['/etc/puppet/environments', '/etc/puppet/environments/production']:
      ensure => directory;
    '/etc/puppet/environments/production/modules':
      ensure => 'link',
      target => '/vagrant/modules';
    '/etc/puppet/environments/production/manifests':
      ensure => 'link',
      target => '/vagrant/manifests';
  }

A questo punto, su ogni nodo dell’infrastruttura, dovremo configurare l’agente. Esplicitiamo il Puppet Master, l’environment e il modo in cui deve essere eseguito. Eseguire l’agente via cron occupa meno risorse che farlo girare come demone:

  # Configure Puppet Agent
  class { 'puppet::agent':
    puppet_run_style => 'cron',
    puppet_server    => 'puppet.local.lan',
    environment      => 'production',
  }

Iniziamo adesso a condividere risorse fra i vari nodi. Poiché i nodi pg e backup avranno bisogno di comunicare fra loro via SSH, dovranno sapere qual è l’ip dell’altro server e averne la chiave all’interno di known_hosts. Provvediamo quindi ad esportare e raccogliere queste risorse su ogni nodo, ad esempio:

  @@host { 'backup_host':
    ensure       => 'present',
    name         => $::fqdn,
    host_aliases => $::hostname,
    ip           => '192.168.56.222',
  }

  @@sshkey { "${::hostname}_ecdsa":
    host_aliases => [ $::hostname, $::fqdn ],
    type         => 'ecdsa-sha2-nistp256',
    key          => $::sshecdsakey,
  }

  # Collect:
  Host <<| |>>
  Sshkey <<| |>>

barman::autoconfigure

Adesso, siamo liberi di andare a configurare il server PostgreSQL e il server Barman. Con la possibilità di usare l’autoconfigure, questa parte diventa molto più semplice rispetto all’articolo precedente.

Per il nodo backup basta infatti indicare di usare l’autoconfigure e quale ip deve esportare. La macchina Vagrant infatti possiede due indirizzi ip e noi dobbiamo forzare l’utilizzo di 192.168.56.222. Inoltre, andiamo a usare il pacchetto di PGDG, abilitando manage_package_repo:

  class { 'barman':
    autoconfigure       => true,
    exported_ipaddress  => '192.168.56.222/32',
    manage_package_repo => true,
  }

Sul nodo pg provvediamo a installare il server PostgreSQL e a dichiarare come -il server PostgreSQL- debba essere gestito da Barman, attraverso la classe barman::postgres. Questa classe esporta il cron per l’esecuzione del comando barman backup pg e la configurazione del server per Barman, che saranno importati dal server backup tramite autoconfigure:

  # Configure PostgreSQL
  class { 'postgresql::server':
    listen_addresses     => '*',
  }

  # Export the parameters required by Barman
  class { 'barman::postgres':
    retention_policy        => 'RECOVERY WINDOW OF 1 WEEK',
    minimum_redundancy      => 1,
    last_backup_maximum_age => '1 WEEK',
    reuse_backup            => 'link',
    backup_hour             => 1,
    backup_minute           => 0,
  }

Test

È possibile testare tutto quello che abbiamo visto finora clonando il progetto su GitHub ed eseguendo, all’interno della directory creata:

$ librarian-puppet install --verbose
$ vagrant up
$ vagrant provision
$ vagrant provision

Il sistema deve infatti effettuare tre provision (il primo è all’interno del primo vagrant up) prima che tutte le risorse esportate siano raccolte dai nodi. A questo punto possiamo entrare nella macchina backup e controllare che il backup possa essere effettuato:

$ vagrant ssh backup
root@backup:~# barman backup all
Starting backup for server pg in /var/lib/barman/pg/base/20150320T114208
Backup start at xlog location: 0/2000028 (000000010000000000000002, 00000028)
Copying files.
Copy done.
Backup size: 18.7 MiB. Actual size on disk: 18.7 MiB (-0.00% deduplication ratio).
Asking PostgreSQL server to finalize the backup.
Backup end at xlog location: 0/20000B8 (000000010000000000000002, 000000B8)
Backup completed
Processing xlog segments for pg
        Older than first backup. Trashing file 000000010000000000000001 from server pg
        000000010000000000000002
        000000010000000000000002.00000028.backup

Conclusioni

Anche se la configurazione iniziale di un Puppet Master può essere laboriosa, i vantaggi sono enormi. Non solo la configurazione di Barman è più semplice, ma qualunque altra aggiunta all’infrastruttura ne risulta estremamente semplificata. Ad esempio, aggiungere un server Icinga o Nagios diventa molto più semplice quando ogni singolo server può esportare i servizi che devono essere monitorati (check_postgres o barman check --nagios).

Inoltre, nell’esempio abbiamo utilizzato un solo server PostgreSQL e un solo server Barman, ma in caso di infrastrutture complesse con molti database server è possibile dichiarare più server Barman e utilizzare host_group per identificare i server Postgres dei quali i diversi server Barman devono fare il backup.

Concludo con un ringraziamento speciale a Alessandro Franceschi per l’idea iniziale di aggiungere un sistema di autoconfigurazione al modulo Barman.

This Post Has 0 Comments

Leave A Reply