MariaDB
 sql >> Datenbank >  >> RDS >> MariaDB

Datenbankautomatisierung mit Puppet:Bereitstellen von MySQL- und MariaDB-Replikation

Puppet ist ein Open-Source-Systemverwaltungstool zur Zentralisierung und Automatisierung des Konfigurationsmanagements. Automatisierungstools helfen dabei, manuelle und sich wiederholende Aufgaben zu minimieren, und können viel Zeit sparen.

Puppet arbeitet standardmäßig in einem Server/Agent-Modell. Agenten holen sich ihren „Katalog“ (endgültiger Soll-Zustand) vom Master und wenden ihn lokal an. Dann melden sie sich beim Server zurück. Der Katalog wird basierend auf „Fakten“, die die Maschine an den Server sendet, Benutzereingaben (Parameter) und Modulen (Quellcode) berechnet.

In diesem Blog zeigen wir Ihnen, wie Sie MySQL/MariaDB-Instanzen über Puppet bereitstellen und verwalten. Es gibt eine Reihe von Technologien rund um MySQL/MariaDB wie Replikation (Master-Slave, Galera oder Gruppenreplikation für MySQL), SQL-fähige Load Balancer wie ProxySQL und MariaDB MaxScale, Sicherungs- und Wiederherstellungstools und viele mehr, die wir in diesem Artikel behandeln werden Blog-Reihe. Es gibt auch viele Module in Puppet Forge, die von der Community erstellt und gepflegt werden, die uns helfen können, den Code zu vereinfachen und das Rad nicht neu erfinden zu müssen. In diesem Blog konzentrieren wir uns auf die MySQL-Replikation.

puppetlabs/mysql

Dies ist derzeit das beliebteste Puppet-Modul für MySQL und MariaDB (und wahrscheinlich das beste auf dem Markt). Dieses Modul verwaltet sowohl die Installation als auch die Konfiguration von MySQL und erweitert Puppet, um die Verwaltung von MySQL-Ressourcen wie Datenbanken, Benutzern und Berechtigungen zu ermöglichen.

Das Modul wird offiziell vom Puppet-Team gepflegt (über das Github-Repository von Puppetlabs) und unterstützt alle Hauptversionen von Puppet Enterprise 2019.1.x, 2019.0.x, 2018.1.x, Puppet>=5.5.10 <7.0.0 auf RedHat, Ubuntu, Plattformen Debian, SLES, Scientific, CentOS, OracleLinux. Der Benutzer hat die Möglichkeit, MySQL, MariaDB und Percona Server zu installieren, indem er das Paket-Repository anpasst

Das folgende Beispiel zeigt, wie Sie einen MySQL-Server bereitstellen. Installieren Sie auf dem Puppet Master das MySQL-Modul und erstellen Sie die Manifestdatei:

(puppet-master)$ puppet module install puppetlabs/mysql
(puppet-master)$ vim /etc/puppetlabs/code/environments/production/manifests/mysql.pp

Fügen Sie die folgenden Zeilen hinzu:

node "db1.local" {
  class { '::mysql::server':
    root_password => 't5[sb^D[+rt8bBYu',
    remove_default_accounts => true,
    override_options => {
      'mysqld' => {
        'log_error' => '/var/log/mysql.log',
        'innodb_buffer_pool_size' => '512M'
      }
      'mysqld_safe' => {
        'log_error' => '/var/log/mysql.log'
      }
    }
  }
}

Führen Sie dann auf dem Puppet-Agent-Knoten den folgenden Befehl aus, um den Konfigurationskatalog anzuwenden:

(db1.local)$ puppet agent -t

Bei der ersten Ausführung erhalten Sie möglicherweise die folgende Fehlermeldung:

Info: Certificate for db1.local has not been signed yet

Führen Sie einfach den folgenden Befehl auf dem Puppet-Master aus, um das Zertifikat zu signieren:

(puppet-master)$ puppetserver ca sign --certname=db1.local
Successfully signed certificate request for db1.local

Versuchen Sie es erneut mit dem Befehl "puppet agent -t", um die Verbindung mit dem signierten Zertifikat erneut zu initiieren.

Die obige Definition installiert die standardmäßigen MySQL-bezogenen Pakete, die im Betriebssystem-Distributions-Repository verfügbar sind. Unter Ubuntu 18.04 (Bionic) würden Sie beispielsweise MySQL 5.7.26-Pakete installieren:

(db1.local) $ dpkg --list | grep -i mysql
ii  mysql-client-5.7                5.7.26-0ubuntu0.18.04.1           amd64        MySQL database client binaries
ii  mysql-client-core-5.7           5.7.26-0ubuntu0.18.04.1           amd64        MySQL database core client binaries
ii  mysql-common                    5.8+1.0.4                         all          MySQL database common files, e.g. /etc/mysql/my.cnf
ii  mysql-server                    5.7.26-0ubuntu0.18.04.1           all          MySQL database server (metapackage depending on the latest version)
ii  mysql-server-5.7                5.7.26-0ubuntu0.18.04.1           amd64        MySQL database server binaries and system database setup
ii  mysql-server-core-5.7           5.7.26-0ubuntu0.18.04.1           amd64        MySQL database server binaries

Sie können sich für andere Anbieter wie Oracle, Percona oder MariaDB mit zusätzlicher Konfiguration im Repository entscheiden (Einzelheiten finden Sie im Abschnitt README). Die folgende Definition installiert die MariaDB-Pakete aus dem MariaDB apt-Repository (erfordert apt Puppet-Modul):

$ puppet module install puppetlabs/apt
$ vim /etc/puppetlabs/code/environments/production/manifests/mariadb.pp
# include puppetlabs/apt module
include apt

# apt definition for MariaDB 10.3
apt::source { 'mariadb':
  location => 'http://sgp1.mirrors.digitalocean.com/mariadb/repo/10.3/ubuntu/',
  release  => $::lsbdistcodename,
  repos    => 'main',
  key      => {
    id     => 'A6E773A1812E4B8FD94024AAC0F47944DE8F6914',
    server => 'hkp://keyserver.ubuntu.com:80',
  },
  include => {
    src   => false,
    deb   => true,
  },
}

# MariaDB configuration
class {'::mysql::server':
  package_name     => 'mariadb-server',
  service_name     => 'mysql',
  root_password    => 't5[sb^D[+rt8bBYu',
  override_options => {
    mysqld => {
      'log-error' => '/var/log/mysql/mariadb.log',
      'pid-file'  => '/var/run/mysqld/mysqld.pid',
    },
    mysqld_safe => {
      'log-error' => '/var/log/mysql/mariadb.log',
    },
  }
}

# Deploy on db2.local
node "db2.local" {
Apt::Source['mariadb'] ->
Class['apt::update'] ->
Class['::mysql::server']
}

Beachten Sie den key->id-Wert, wo es eine spezielle Möglichkeit gibt, die 40-stellige ID abzurufen, wie in diesem Artikel gezeigt:

$ sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
$ apt-key adv --list-public-keys --with-fingerprint --with-colons
uid:-::::1459359915::6DC53DD92B7A8C298D5E54F950371E2B8950D2F2::MariaDB Signing Key <[email protected]>::::::::::0:
sub:-:4096:1:C0F47944DE8F6914:1459359915::::::e::::::23:
fpr:::::::::A6E773A1812E4B8FD94024AAC0F47944DE8F6914:

Wobei sich der ID-Wert in der Zeile befindet, die mit „fpr“ beginnt, also „A6E773A1812E4B8FD94024AAC0F47944DE8F6914“.

Nachdem der Puppet-Katalog angewendet wurde, können Sie als Root ohne explizites Passwort direkt auf die MySQL-Konsole zugreifen, da das Modul ~/.my.cnf automatisch konfiguriert und verwaltet. Wenn wir das Root-Passwort auf etwas anderes zurücksetzen möchten, ändern Sie einfach den root_password-Wert in der Puppet-Definition und wenden Sie den Katalog auf den Agentenknoten an.

Bereitstellung der MySQL-Replikation

Um ein MySQL Replication-Setup bereitzustellen, muss man mindestens zwei Konfigurationstypen erstellen, um die Master- und Slave-Konfiguration zu trennen. Beim Master ist die Nur-Lese-Funktion deaktiviert, um das Lesen/Schreiben zu ermöglichen, während die Slaves mit aktivierter Nur-Lese-Funktion konfiguriert werden. In diesem Beispiel verwenden wir die GTID-basierte Replikation, um die Konfiguration zu vereinfachen (da die Konfiguration aller Knoten sehr ähnlich wäre). Wir möchten die Replikationsverbindung zum Master direkt nach dem Hochfahren des Slaves initiieren.

Angenommen, wir haben 3 Knoten MySQL-Master-Slave-Replikation:

  • db1.local - Master
  • db2.local - Slave #1
  • db3.local - Slave #2

Um die oben genannten Anforderungen zu erfüllen, können wir unser Manifest etwa so schreiben:

# Puppet manifest for MySQL GTID-based replication MySQL 5.7 on Ubuntu 18.04 (Puppet v6.4.2) 
# /etc/puppetlabs/code/environments/production/manifests/replication.pp

# node's configuration
class mysql {
  class {'::mysql::server':
    root_password           => '[email protected]#',
    create_root_my_cnf      => true,
    remove_default_accounts => true,
    manage_config_file      => true,
    override_options        => {
      'mysqld' => {
        'datadir'                 => '/var/lib/mysql',
        'bind_address'            => '0.0.0.0',
        'server-id'               => $mysql_server_id,
        'read_only'               => $mysql_read_only,
        'gtid-mode'               => 'ON',
        'enforce_gtid_consistency'=> 'ON',
        'log-slave-updates'       => 'ON',
        'sync_binlog'             => 1,
        'log-bin'                 => '/var/log/mysql-bin',
        'read_only'               => 'OFF',
        'binlog-format'           => 'ROW',
        'log-error'               => '/var/log/mysql/error.log',
        'report_host'             => ${fqdn},
        'innodb_buffer_pool_size' => '512M'
      },
      'mysqld_safe' => {
        'log-error'               => '/var/log/mysql/error.log'
      }
    }
  }
  
  # create slave user
  mysql_user { "${slave_user}@192.168.0.%":
      ensure        => 'present',
      password_hash => mysql_password("${slave_password}")
  }

  # grant privileges for slave user
  mysql_grant { "${slave_user}@192.168.0.%/*.*":
      ensure        => 'present',
      privileges    => ['REPLICATION SLAVE'],
      table         => '*.*',
      user          => "${slave_user}@192.168.0.%"
  }

  # /etc/hosts definition
  host {
    'db1.local': ip => '192.168.0.161';
    'db2.local': ip => '192.169.0.162';
    'db3.local': ip => '192.168.0.163';
  }

  # executes change master only if $master_host is defined
  if $master_host {
    exec { 'change master':
      path    => '/usr/bin:/usr/sbin:/bin',
      command => "mysql --defaults-extra-file=/root/.my.cnf -e \"CHANGE MASTER TO MASTER_HOST = '$master_host', MASTER_USER = '$slave_user', MASTER_PASSWORD = '$slave_password', MASTER_AUTO_POSITION = 1; START SLAVE;\"",
      unless  => "mysql --defaults-extra-file=/root/.my.cnf -e 'SHOW SLAVE STATUS\G' | grep 'Slave_SQL_Running: Yes'"
    }
  }
}

## node assignment

# global vars
$master_host = undef
$slave_user = 'slave'
$slave_password = 'Replicas123'

# master
node "db1.local" {
  $mysql_server_id = '1'
  $mysql_read_only = 'OFF'
  include mysql
}

# slave1
node "db2.local" {
  $mysql_server_id = '2'
  $mysql_read_only = 'ON'
  $master_host = 'db1.local'
  include mysql
}

# slave2
node "db3.local" {
  $mysql_server_id = '3'
  $mysql_read_only = 'ON'
  $master_host = 'db1.local'
  include mysql
}

Den Agenten zwingen, den Katalog anzuwenden:

(all-mysql-nodes)$ puppet agent -t

Auf dem Master (db1.local) können wir alle verbundenen Slaves überprüfen:

mysql> SHOW SLAVE HOSTS;
+-----------+-----------+------+-----------+--------------------------------------+
| Server_id | Host      | Port | Master_id | Slave_UUID                           |
+-----------+-----------+------+-----------+--------------------------------------+
|         3 | db3.local | 3306 |         1 | 2d0b14b6-8174-11e9-8bac-0273c38be33b |
|         2 | db2.local | 3306 |         1 | a9dfa4c7-8172-11e9-8000-0273c38be33b |
+-----------+-----------+------+-----------+--------------------------------------+

Achten Sie besonders auf den Abschnitt „exec { 'change master' :“, wo dies bedeutet, dass ein MySQL-Befehl ausgeführt wird, um den Replikationslink zu initiieren, wenn die Bedingung erfüllt ist. Alle von Puppet ausgeführten „exec“-Ressourcen müssen idempotent sein, d. h. die Operation, die denselben Effekt hat, egal ob Sie sie einmal oder 10.001 Mal ausführen. Es gibt eine Reihe von Bedingungsattributen, die Sie verwenden können, wie "unless", "onlyif" und "create", um den korrekten Zustand zu gewährleisten und zu verhindern, dass Puppet Ihre Einrichtung durcheinander bringt. Sie können diesen Abschnitt löschen/kommentieren, wenn Sie den Replikationslink manuell initiieren möchten.

MySQL-Verwaltung

Dieses Modul kann verwendet werden, um eine Reihe von MySQL-Verwaltungsaufgaben auszuführen:

  • Konfigurationsoptionen (ändern, anwenden, benutzerdefinierte Konfiguration)
  • Datenbankressourcen (Datenbank, Benutzer, Zuschüsse)
  • Sicherung (erstellen, planen, Benutzer sichern, speichern)
  • einfache Wiederherstellung (nur mysqldump)
  • Installation/Aktivierung von Plugins

Datenbankressource

Wie Sie im obigen Beispielmanifest sehen können, haben wir zwei MySQL-Ressourcen – mysql_user und mysql_grant – definiert, um Benutzer zu erstellen und dem Benutzer Berechtigungen zu erteilen. Wir können auch die Klasse mysql::db verwenden, um sicherzustellen, dass eine Datenbank mit zugeordneten Benutzern und Berechtigungen vorhanden ist, zum Beispiel:

  # make sure the database and user exist with proper grant
  mysql::db { 'mynewdb':
    user          => 'mynewuser',
    password      => 'passw0rd',
    host          => '192.168.0.%',
    grant         => ['SELECT', 'UPDATE']
  } 

Beachten Sie, dass bei der MySQL-Replikation alle Schreibvorgänge nur auf dem Master ausgeführt werden müssen. Stellen Sie also sicher, dass die obige Ressource dem Master zugewiesen ist. Andernfalls kann es zu fehlerhaften Transaktionen kommen.

Sichern und Wiederherstellen

Üblicherweise ist nur ein Backup-Host für den gesamten Cluster erforderlich (es sei denn, Sie replizieren eine Teilmenge von Daten). Wir können die Klasse mysql::server::backup verwenden, um die Backup-Ressourcen vorzubereiten. Angenommen, wir haben die folgende Deklaration in unserem Manifest:

  # Prepare the backup script, /usr/local/sbin/mysqlbackup.sh
  class { 'mysql::server::backup':
    backupuser     => 'backup',
    backuppassword => 'passw0rd',
    backupdir      => '/home/backup',
    backupdirowner => 'mysql',
    backupdirgroup => 'mysql',
    backupdirmode  => '755',
    backuprotate   => 15,
    time           => ['23','30'],   #backup starts at 11:30PM everyday
    include_routines  => true,
    include_triggers  => true,
    ignore_events     => false,
    maxallowedpacket  => '64M',
    optional_args     => ['--set-gtid-purged=OFF'] #extra argument if GTID is enabled
  }

Puppet konfiguriert alle Voraussetzungen, bevor ein Backup ausgeführt wird – Erstellen des Backup-Benutzers, Vorbereiten des Zielpfads, Zuweisen von Besitz und Berechtigungen, Einstellen des Cron-Jobs und Einrichten der Backup-Befehlsoptionen zur Verwendung im bereitgestellten Backup-Skript unter /usr/local /sbin/mysqlbackup.sh. Es ist dann Sache des Benutzers, das Skript auszuführen oder zu planen. Um eine sofortige Sicherung zu erstellen, rufen Sie einfach auf:

$ mysqlbackup.sh

Wenn wir den eigentlichen mysqldump-Befehl basierend auf dem Obigen extrahieren, sieht er so aus:

$ mysqldump --defaults-extra-file=/tmp/backup.NYg0TR --opt --flush-logs --single-transaction --events --set-gtid-purged=OFF --all-databases

Für diejenigen, die andere Backup-Tools wie Percona Xtrabackup, MariaDB Backup (nur MariaDB) oder MySQL Enterprise Backup verwenden möchten, bietet das Modul die folgenden privaten Klassen:

  • mysql::backup::xtrabackup (Percona Xtrabackup und MariaDB Backup)
  • mysql::backup::mysqlbackup (MySQL Enterprise-Sicherung)

Beispieldeklaration mit Percona Xtrabackup:

  class { 'mysql::backup::xtrabackup':
    xtrabackup_package_name => 'percona-xtrabackup',
    backupuser     => 'xtrabackup',
    backuppassword => 'passw0rd',
    backupdir      => '/home/xtrabackup',
    backupdirowner => 'mysql',
    backupdirgroup => 'mysql',
    backupdirmode  => '755',
    backupcompress => true,
    backuprotate   => 15,
    include_routines  => true,
    time              => ['23','30'], #backup starts at 11:30PM
    include_triggers  => true,
    maxallowedpacket  => '64M',
    incremental_backups => true
  }

Das Obige plant zwei Backups, ein vollständiges Backup jeden Sonntag um 23:30 Uhr und ein inkrementelles Backup jeden Tag außer sonntags zur gleichen Zeit, wie die Cron-Job-Ausgabe zeigt, nachdem das obige Manifest angewendet wurde:

(db1.local)$ crontab -l
# Puppet Name: xtrabackup-weekly
30 23 * * 0 /usr/local/sbin/xtrabackup.sh --target-dir=/home/backup/mysql/xtrabackup --backup
# Puppet Name: xtrabackup-daily
30 23 * * 1-6 /usr/local/sbin/xtrabackup.sh --incremental-basedir=/home/backup/mysql/xtrabackup --target-dir=/home/backup/mysql/xtrabackup/`date +%F_%H-%M-%S` --backup

Weitere Details und verfügbare Optionen für diese Klasse (und andere Klassen) finden Sie in der Optionsreferenz hier.

Für den Wiederherstellungsaspekt unterstützt das Modul nur die Wiederherstellung mit der Sicherungsmethode mysqldump, indem die SQL-Datei mithilfe der Klasse mysql::db direkt in die Datenbank importiert wird, zum Beispiel:

mysql::db { 'mydb':
  user     => 'myuser',
  password => 'mypass',
  host     => 'localhost',
  grant    => ['ALL PRIVILEGES'],
  sql      => '/home/backup/mysql/mydb/backup.gz',
  import_cat_cmd => 'zcat',
  import_timeout => 900
}

Die SQL-Datei wird nur einmal und nicht bei jedem Durchlauf geladen, es sei denn, force_sql => true wird verwendet.

Konfigurationsoptionen

In diesem Beispiel haben wir manage_config_file => true mit override_options verwendet, um unsere Konfigurationszeilen zu strukturieren, die später von Puppet ausgegeben werden. Jede Änderung an der Manifestdatei spiegelt nur den Inhalt der Ziel-MySQL-Konfigurationsdatei wider. Dieses Modul lädt weder die Konfiguration in die Laufzeit noch startet es den MySQL-Dienst neu, nachdem es die Änderungen in die Konfigurationsdatei gepusht hat. Es liegt in der Verantwortung des Systemadministrators, den Dienst neu zu starten, um die Änderungen zu aktivieren.

Um eine benutzerdefinierte MySQL-Konfiguration hinzuzufügen, können wir zusätzliche Dateien in "includedir" platzieren, standardmäßig /etc/mysql/conf.d. Dadurch können wir Einstellungen überschreiben oder zusätzliche hinzufügen, was hilfreich ist, wenn Sie override_options nicht in der Klasse mysql::server verwenden. Die Verwendung der Puppet-Vorlage wird hier dringend empfohlen. Platzieren Sie die benutzerdefinierte Konfigurationsdatei im Modulvorlagenverzeichnis (standardmäßig , /etc/puppetlabs/code/environments/production/modules/mysql/templates) und fügen Sie dann die folgenden Zeilen in das Manifest ein:

# Loads /etc/puppetlabs/code/environments/production/modules/mysql/templates/my-custom-config.cnf.erb into /etc/mysql/conf.d/my-custom-config.cnf

file { '/etc/mysql/conf.d/my-custom-config.cnf':
  ensure  => file,
  content => template('mysql/my-custom-config.cnf.erb')
}

Um versionsspezifische Parameter zu implementieren, verwenden Sie die version-Direktive, zum Beispiel [mysqld-5.5]. Dies ermöglicht eine Konfiguration für verschiedene MySQL-Versionen.

Puppet vs. ClusterControl

Wussten Sie, dass Sie mit ClusterControl auch die Bereitstellung der MySQL- oder MariaDB-Replikation automatisieren können? Sie können das ClusterControl Puppet-Modul verwenden, um es zu installieren, oder es einfach von unserer Website herunterladen.

Im Vergleich zu ClusterControl können Sie folgende Unterschiede erwarten:

  • Eine kleine Lernkurve, um Puppet-Syntaxen, -Formatierungen und -Strukturen zu verstehen, bevor Sie Manifeste schreiben können.
  • Manifest muss regelmäßig getestet werden. Es kommt sehr häufig vor, dass Sie einen Kompilierungsfehler im Code erhalten, besonders wenn der Katalog zum ersten Mal angewendet wird.
  • Puppet geht davon aus, dass die Codes idempotent sind. Die Bedingung test/check/verify fällt in die Verantwortung des Autors, um zu vermeiden, dass ein laufendes System durcheinandergebracht wird.
  • Puppet erfordert einen Agenten auf dem verwalteten Knoten.
  • Abwärtsinkompatibilität. Einige alte Module liefen auf der neuen Version nicht korrekt.
  • Datenbank-/Hostüberwachung muss separat eingerichtet werden.

Der Bereitstellungsassistent von ClusterControl leitet den Bereitstellungsprozess:

Alternativ können Sie die ClusterControl-Befehlszeilenschnittstelle namens „s9s“ verwenden, um ähnliche Ergebnisse zu erzielen. Der folgende Befehl erstellt einen Drei-Knoten-MySQL-Replikationscluster (vorausgesetzt, dass passwortlos für alle Knoten zuvor konfiguriert wurde):

$ s9s cluster --create \
  --cluster-type=mysqlreplication \
      --nodes=192.168.0.41?master;192.168.0.42?slave;192.168.0.43?slave;192.168.0.44?master; \
  --vendor=oracle \
  --cluster-name='MySQL Replication 8.0' \
  --provider-version=8.0 \
  --db-admin='root' \
  --db-admin-passwd='$ecR3t^word' \
  --log
Zugehörige Ressourcen Puppet-Modul für ClusterControl – Hinzufügen von Verwaltung und Überwachung zu Ihren vorhandenen Datenbankclustern So automatisieren Sie die Bereitstellung von MySQL Galera-Clustern mithilfe der s9s-Befehlszeilenschnittstelle und Chef A DevOps Guide to Database Infrastructure Automation for eCommerce – Replay &Slides

Die folgenden MySQL/MariaDB-Replikationskonfigurationen werden unterstützt:

  • Master-Slave-Replikation (datei-/positionsbasiert)
  • Master-Slave-Replikation mit GTID (MySQL/Percona)
  • Master-Slave-Replikation mit MariaDB GTID
  • Master-Master-Replikation (semisynchron/asynchron)
  • Master-Slave-Kettenreplikation (semi-sync/async)

Nach der Bereitstellung können Knoten/Cluster von ClusterControl überwacht und vollständig verwaltet werden, einschließlich automatischer Fehlererkennung, Master-Failover, Slave-Hochstufung, automatischer Wiederherstellung, Sicherungsverwaltung, Konfigurationsverwaltung und so weiter. All dies ist in einem Produkt gebündelt. Die Community Edition (für immer kostenlos!) bietet Bereitstellung und Überwachung. Im Durchschnitt ist Ihr Datenbank-Cluster innerhalb von 30 Minuten betriebsbereit. Was es braucht, ist nur passwortloses SSH zu den Zielknoten.

Im nächsten Teil führen wir Sie durch die Galera-Cluster-Bereitstellung mit demselben Puppet-Modul. Bleiben Sie dran!