PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Automating Barman with Puppet:it2ndq/barman (seconda parte)

Nella prima parte di questo articolo abbiamo configurato Vagrant per eseguire due macchine virtuali Ubuntu 14.04 Trusty Tahr, rispettivamente denominate pg e backup . In questa seconda parte vedremo come utilizzare Puppet per impostare e configurare un server PostgreSQL su pg ed esegui il backup tramite Barman dal backup casella.

Pupazzo:configurazione

Dopo aver definito le macchine come nell'articolo precedente, occorre specificare i moduli Puppet richiesti che librarian-puppet gestirà per noi.

Sono necessari due moduli:

  1. puppetlabs/postgresql (http://github.com/puppetlabs/puppetlabs-postgresql/) per installare PostgreSQL su pg VM
  2. it2ndq/barman (http://github.com/2ndquadrant-it/puppet-barman) per installare Barman su backup

Entrambi i moduli verranno installati da Puppet Forge. Per puppetlabs/postgresql modulo, al momento dovremo utilizzare al massimo la versione 4.2.0, poiché l'ultima versione (4.3.0) sta violando il postgres_password parametro che useremo in seguito (vedi questa richiesta pull). Creiamo un file chiamato Puppetfile contenente questo contenuto nella directory del progetto:

forge "http://forgeapi.puppetlabs.com"
mod "puppetlabs/postgresql", "<4.3.0"
mod "it2ndq/barman"

Ora possiamo installare i moduli Puppet e le loro dipendenze eseguendo:

$ librarian-puppet install --verbose

Sebbene non sia essenziale, è preferibile utilizzare l'opzione --verbose ogni volta librarian-puppet viene utilizzato. Senza di esso il comando è molto silenzioso ed è utile avere i dettagli su ciò che sta facendo in anticipo. Ad esempio, senza usare --verbose , potresti scoprire di aver perso tempo prezioso in attesa della risoluzione di un conflitto di dipendenze, per poi vedere un errore molti minuti dopo.

Al completamento con successo del comando, un modules directory contenente il barman e postgresql moduli e le loro dipendenze (apt , concat , stdlib ) verrà creato nella nostra directory di lavoro. Inoltre, librarian-puppet creerà il Puppetfile.lock per identificare le dipendenze e le versioni dei moduli installati, bloccandoli per impedire futuri aggiornamenti. In questo modo, la successiva librarian-puppet install run installerà sempre la stessa versione dei moduli invece di eventuali aggiornamenti (nel caso sia richiesto un aggiornamento, librarian-puppet update farà il trucco).

Ora possiamo dire a Vagrant che stiamo usando un manifest Puppet per eseguire il provisioning dei server. Modifichiamo il Vagrantfile come segue:

Vagrant.configure("2") do |config|
  {
    :pg => {
      :ip      => '192.168.56.221',
      :box     => 'ubuntu/trusty64'
    },
    :backup => {
      :ip      => '192.168.56.222',
      :box     => 'ubuntu/trusty64'
    }
  }.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 = 'http://raw.github.com/hashicorp/puppet-bootstrap/master/' + family + '.sh'

      # Run puppet-bootstrap only once
      local.vm.provision :shell, :inline => <<-eos
        if [ ! -e /tmp/.bash.provision.done ]; then
          curl -L #{bootstrap_url} | bash
          touch /tmp/.bash.provision.done
        fi
      eos

      # Provision 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
  end
end

Con le righe che abbiamo appena aggiunto, abbiamo fornito a Vagrant le istruzioni per effettuare il provisioning delle VM utilizzando manifests/site.pp come manifest principale e i moduli inclusi nei modules directory. Questa è la versione finale del nostro Vagrantfile .

Ora dobbiamo creare i manifests directory:

$ mkdir manifests

e scrivici una prima versione di site.pp . Inizieremo con una configurazione molto semplice:

node backup {
  class { 'barman':
    manage_package_repo => true,
  }
}
node pg {}

Ora possiamo avviare le macchine e vederlo su backup c'è un server Barman con una configurazione predefinita (e nessun PostgreSQL su pg ancora). Accediamo a backup :

$ vagrant ssh backup

e dai un'occhiata a /etc/barman.conf :

# Main configuration file for Barman (Backup and Recovery Manager for PostgreSQL)
# Further information on the Barman project at www.pgbarman.org
# IMPORTANT: Please do not edit this file as it is managed by Puppet!
# Global options

[barman]
barman_home = /var/lib/barman
barman_user = barman
log_file = /var/log/barman/barman.log
compression = gzip
backup_options = exclusive_backup
minimum_redundancy = 0
retention_policy =
retention_policy_mode = auto
wal_retention_policy = main
configuration_files_directory = /etc/barman.conf.d

Il passaggio successivo è eseguire un'istanza PostgreSQL su pg . Dobbiamo essere a conoscenza dei parametri richiesti da Barman sul server PostgreSQL, quindi dobbiamo impostare:

  • wal_level almeno in archive livello
  • archive_mode su on
  • archive_command in modo che i WAL possano essere copiati su backup
  • una regola in pg_hba.conf per l'accesso da backup

Tutti questi parametri possono essere facilmente impostati tramite puppetlabs/postgresql modulo. Inoltre, sul server Barman, abbiamo bisogno di:

  • una stringa di connessione PostgreSQL
  • un .pgpass file per l'autenticazione
  • un comando SSH
  • per eseguire lo scambio di chiavi SSH

it2ndq/barman genera una coppia di chiavi privata/pubblica in ~barman/.ssh . Tuttavia, lo scambio automatico delle chiavi tra i server richiede la presenza di un Puppet Master che esula dagli obiettivi di questo tutorial (farà parte della prossima puntata, che sarà incentrata sulla configurazione di un Puppet Master e del barman::autoconfigure class) – quindi quest'ultimo passaggio verrà eseguito manualmente.

Modifichiamo il site.pp file come segue:

node backup {
  class { 'barman':
    manage_package_repo => true,
  }
  barman::server {'test-server':
    conninfo     => 'user=postgres host=192.168.56.221',
    ssh_command  => 'ssh [email protected]',
  }
  file { '/var/lib/barman/.pgpass':
    ensure  => 'present',
    owner   => 'barman',
    group   => 'barman',
    mode    => 0600,
    content => '192.168.56.221:5432:*:postgres:insecure_password',
  }
}

node pg {
  class { 'postgresql::server':
    listen_addresses     => '*',
    postgres_password    => 'insecure_password',
    pg_hba_conf_defaults => false,
  }
  postgresql::server::pg_hba_rule {'Local access':
    type        => 'local',
    database    => 'all',
    user        => 'all',
    auth_method => 'peer',
  }
  postgresql::server::pg_hba_rule {'Barman access':
    type        => 'host',
    database    => 'all',
    user        => 'postgres',
    address     => '192.168.56.222/32',
    auth_method => 'md5',
  }
  postgresql::server::config_entry {
    'wal_level'       : value => 'archive';
    'archive_mode'    : value => 'on';
    'archive_command' : value => 'rsync -a %p [email protected]:/var/lib/barman/test-server/incoming/%f';
  }
  class { 'postgresql::server::contrib':
    package_ensure => 'present',
  }
}

Dopo aver modificato il manifest, la disposizione deve essere ripetuta:

$ vagrant provision

Con le macchine in funzione, possiamo procedere con lo scambio delle chiavi. Accediamo a pg :

$ vagrant ssh pg

e creiamo la coppia di chiavi per postgres utente, utilizzando ssh-keygen , lasciando ogni campo vuoto quando richiesto (quindi premendo sempre invio):

[email protected]:~$ sudo -iu postgres
[email protected]:~$ ssh-keygen
[email protected]:~$ cat .ssh/id_rsa.pub

L'ultimo comando restituisce una lunga stringa alfanumerica che deve essere aggiunta al ~barman/.ssh/authorized_keys file su backup .

$ vagrant ssh backup
[email protected]:~$ sudo -iu barman
[email protected]:~$ echo "ssh-rsa ..." >> .ssh/authorized_keys

Allo stesso modo, copiamo la chiave pubblica del barman utente nelle authorized_keys file del postgres utente su pg :

[email protected]:~$ cat .ssh/id_rsa.pub
ssh-rsa ...
[email protected]:~$ logout
[email protected]:~$ logout
$ vagrant ssh pg
[email protected]:~$ sudo -iu postgres
[email protected]:~$ echo "ssh-rsa ..." >> .ssh/authorized_keys

A questo punto, effettuiamo una prima connessione in entrambe le direzioni tra i due server:

[email protected]:$ ssh [email protected]
[email protected]:$ ssh [email protected]

Possiamo eseguire barman check per verificare che Barman funzioni correttamente:

[email protected]:~$ barman check all
Server test-server:
        ssh: OK
        PostgreSQL: OK
        archive_mode: OK
        archive_command: OK
        directories: OK
        retention policy settings: OK
        backup maximum age: OK (no last_backup_maximum_age provided)
        compression settings: OK
        minimum redundancy requirements: OK (have 0 backups, expected at least 0)

Ogni riga dovrebbe leggere "OK". Ora, per eseguire un backup, esegui semplicemente:

[email protected]:$ barman backup test-server

Una configurazione realistica

La configurazione di Barman utilizzata finora è molto semplice, ma puoi facilmente aggiungere alcuni parametri a site.pp e sfrutta tutte le funzionalità di Barman, come le policy di conservazione e il nuovo backup incrementale disponibile in Barman 1.4.0.

Concludiamo questo tutorial con un caso d'uso realistico, con i seguenti requisiti:

  • un backup ogni notte all'01:00
  • la possibilità di eseguire un Point In Time Recovery in qualsiasi momento dell'ultima settimana
  • avere sempre almeno un backup disponibile
  • segnalazione di un errore tramite barman check nel caso in cui il backup più recente sia più vecchio di una settimana
  • abilitazione del backup incrementale per risparmiare spazio su disco

Usiamo il file del pupazzo risorsa per creare un .pgpass file con i parametri di connessione e un cron risorsa per generare il lavoro da eseguire ogni notte. Infine, modifichiamo il barman::server per aggiungere i parametri Barman richiesti.

Il risultato finale è:

node backup {
  class { 'barman':
    manage_package_repo => true,
  }
  barman::server {'test-server':
    conninfo                => 'user=postgres host=192.168.56.221',
    ssh_command             => 'ssh [email protected]',
    retention_policy        => 'RECOVERY WINDOW OF 1 WEEK',
    minimum_redundancy      => 1,
    last_backup_maximum_age => '1 WEEK',
    reuse_backup            => 'link',
  }
  file { '/var/lib/barman/.pgpass':
    ensure  => 'present',
    owner   => 'barman',
    group   => 'barman',
    mode    => 0600,
    content => '192.168.56.221:5432:*:postgres:insecure_password',
  }
  cron { 'barman backup test-server':
    command => '/usr/bin/barman backup test-server',
    user    => 'barman',
    hour    => 1,
    minute  => 0,
  }
}
node pg {
  class { 'postgresql::server':
    listen_addresses  => '*',
    postgres_password => 'insecure_password',
    pg_hba_conf_defaults => false,
  }
  postgresql::server::pg_hba_rule {'Local access':
    type        => 'local',
    database    => 'all',
    user        => 'all',
    auth_method => 'peer',
  }
  postgresql::server::pg_hba_rule {'Barman access':
    type        => 'host',
    database    => 'all',
    user        => 'postgres',
    address     => '192.168.56.222/32',
    auth_method => 'md5',
  }
  postgresql::server::config_entry {
    'wal_level'       : value => 'archive';
    'archive_mode'    : value => 'on';
    'archive_command' : value => 'rsync -a %p [email protected]:/var/lib/barman/test-server/incoming/%f';
  }
}

Conclusione

Con 51 righe di manifest Puppet siamo riusciti a configurare una coppia di server PostgreSQL/Barman con impostazioni simili a quelle che potremmo desiderare su un server di produzione. Abbiamo unito i vantaggi di avere un server Barman per gestire i backup con quelli di avere un'infrastruttura gestita da Puppet, riutilizzabile e versionabile.

Nel prossimo e ultimo post di questa serie di articoli vedremo come utilizzare un Puppet Master per esportare risorse tra diverse macchine, consentendo così alle VM di scambiarsi i parametri necessari per il corretto funzionamento tramite il barman::autoconfigure classe semplificando l'intero processo di configurazione.