sql >> Databasteknik >  >> RDS >> MariaDB

Databasautomatisering med Puppet:Implementering av MySQL &MariaDB-replikering

Puppet är ett systemhanteringsverktyg med öppen källkod för att centralisera och automatisera konfigurationshantering. Automationsverktyg hjälper till att minimera manuella och repetitiva uppgifter och kan spara mycket tid.

Puppet fungerar som standard i en server/agentmodell. Agenter hämtar sin "katalog" (slutligt önskat tillstånd) från mastern och tillämpar den lokalt. Sedan rapporterar de tillbaka till servern. Katalogen beräknas beroende på "fakta" som maskinen skickar till servern, användarinmatning (parametrar) och moduler (källkod).

I den här bloggen kommer vi att visa dig hur du distribuerar och hanterar MySQL/MariaDB-instanser via Puppet. Det finns ett antal tekniker kring MySQL/MariaDB som replikering (master-slave, Galera eller gruppreplikering för MySQL), SQL-medvetna lastbalanserare som ProxySQL och MariaDB MaxScale, verktyg för säkerhetskopiering och återställning och många fler som vi kommer att täcka i detta bloggserie. Det finns också många moduler tillgängliga i Puppet Forge byggda och underhållna av communityn som kan hjälpa oss att förenkla koden och undvika att uppfinna hjulet på nytt. I den här bloggen kommer vi att fokusera på MySQL-replikering.

puppetlabs/mysql

Detta är den mest populära Puppet-modulen för MySQL och MariaDB (och förmodligen den bästa på marknaden) just nu. Den här modulen hanterar både installation och konfiguration av MySQL, samt utökar Puppet för att tillåta hantering av MySQL-resurser, såsom databaser, användare och anslag.

Modulen underhålls officiellt av Puppet-teamet (via puppetlabs Github repository) och stöder alla större versioner av Puppet Enterprise 2019.1.x, 2019.0.x, 2018.1.x, Puppet>=5.5.10 <7.0.0 på RedHat, Ubuntu, Debian, SLES, Scientific, CentOS, OracleLinux-plattformar. Användaren har alternativ att installera MySQL, MariaDB och Percona Server genom att anpassa paketförrådet

Följande exempel visar hur man distribuerar en MySQL-server. Installera MySQL-modulen på puppet master och skapa manifestfilen:

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

Lägg till följande rader:

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'
      }
    }
  }
}

Kör sedan följande kommando på marionettagentnoden för att tillämpa konfigurationskatalogen:

(db1.local)$ puppet agent -t

Vid första körningen kan du få följande felmeddelande:

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

Kör bara följande kommando på Puppet Master för att signera certifikatet:

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

Försök igen med kommandot "puppet agent -t" för att återuppta anslutningen med det signerade certifikatet.

Ovanstående definition kommer att installera de vanliga MySQL-relaterade paketen som finns tillgängliga i OS-distributionsförrådet. Till exempel, på Ubuntu 18.04 (Bionic), skulle du få MySQL 5.7.26-paket installerade:

(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

Du kan välja andra leverantörer som Oracle, Percona eller MariaDB med extra konfiguration på förvaret (se avsnittet README för detaljer). Följande definition kommer att installera MariaDB-paketen från MariaDB apt repository (kräver 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']
}

Notera nyckel->id-värdet, där det finns ett speciellt sätt att hämta ID:t på 40 tecken som visas i den här artikeln:

$ 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:

Där id-värdet finns på raden startas med "fpr", vilket är 'A6E773A1812E4B8FD94024AAC0F47944DE8F6914'.

Efter att Puppet-katalogen har tillämpats kan du komma åt MySQL-konsolen direkt som root utan explicit lösenord eftersom modulen konfigurerar och hanterar ~/.my.cnf automatiskt. Om vi ​​skulle vilja återställa root-lösenordet till något annat, ändra helt enkelt root_password-värdet i Puppet-definitionen och tillämpa katalogen på agentnoden.

MySQL-replikeringsdistribution

För att distribuera en MySQL-replikeringsinställning måste man skapa minst två typer av konfigurationer för att separera master- och slavkonfiguration. Mastern kommer att ha skrivskyddat inaktiverat för att tillåta läs/skriva medan slavar kommer att konfigureras med skrivskyddat aktiverat. I det här exemplet kommer vi att använda GTID-baserad replikering för att förenkla konfigurationen (eftersom alla noders konfiguration skulle vara väldigt lika). Vi kommer att vilja initiera replikeringslänken till mastern direkt efter att slaven är uppe.

Antag att vi har tre noder MySQL master-slave replikering:

  • db1.local - master
  • db2.local - slav #1
  • db3.local - slav #2

För att uppfylla ovanstående krav kan vi skriva ner vårt manifest till något så här:

# 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
}

Tvinga agenten att tillämpa katalogen:

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

På mastern (db1.local) kan vi verifiera alla anslutna slavar:

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 |
+-----------+-----------+------+-----------+--------------------------------------+

Var extra uppmärksam på avsnittet "exec { 'change master' :" där det betyder att ett MySQL-kommando kommer att köras för att initiera replikeringslänken om villkoret är uppfyllt. Alla "exec"-resurser som körs av Puppet måste vara idempotenta, vilket betyder operationen som kommer att ha samma effekt oavsett om du kör den en gång eller 10 001 gånger. Det finns ett antal tillståndsattribut som du kan använda som "om inte", "bara om" och "skapa" för att skydda rätt tillstånd och förhindra att Puppet krånglar till din installation. Du kan ta bort/kommentera det avsnittet om du vill initiera replikeringslänken manuellt.

MySQL-hantering

Den här modulen kan användas för att utföra ett antal MySQL-hanteringsuppgifter:

  • konfigurationsalternativ (ändra, tillämpa, anpassad konfiguration)
  • databasresurser (databas, användare, anslag)
  • säkerhetskopiering (skapa, schemalägga, säkerhetskopiera användare, lagring)
  • enkel återställning (endast mysqldump)
  • installation/aktivering av plugin

Databasresurs

Som du kan se i exempelmanifestet ovan har vi definierat två MySQL-resurser - mysql_user och mysql_grant - för att skapa användare respektive bevilja privilegier för användaren. Vi kan också använda klassen mysql::db för att säkerställa att en databas med tillhörande användare och privilegier finns, till exempel:

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

Observera att i MySQL-replikering måste alla skrivningar endast utföras på mastern. Så se till att ovanstående resurs är tilldelad mastern. Annars kan felaktig transaktion inträffa.

Säkerhetskopiera och återställa

Vanligtvis krävs bara en backup-värd för hela klustret (såvida du inte replikerar en delmängd av data). Vi kan använda mysql::server::backup-klassen för att förbereda säkerhetskopieringsresurserna. Anta att vi har följande deklaration i vårt 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 kommer att konfigurera alla förutsättningar innan du kör en säkerhetskopia - skapa backupanvändaren, förbereda destinationssökvägen, tilldela äganderätt och behörighet, ställa in cron-jobbet och ställa in backupkommandoalternativen att använda i det medföljande backupskriptet som finns på /usr/local /sbin/mysqlbackup.sh. Det är sedan upp till användaren att köra eller schemalägga skriptet. För att göra en omedelbar säkerhetskopia, anropa helt enkelt:

$ mysqlbackup.sh

Om vi ​​extraherar det faktiska mysqldump-kommandot baserat på ovanstående, så ser det ut så här:

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

För dem som vill använda andra säkerhetskopieringsverktyg som Percona Xtrabackup, MariaDB Backup (endast MariaDB) eller MySQL Enterprise Backup, tillhandahåller modulen följande privata klasser:

  • mysql::backup::xtrabackup (Percona Xtrabackup och MariaDB Backup)
  • mysql::backup::mysqlbackup (MySQL Enterprise Backup)

Exempeldeklaration med 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
  }

Ovanstående kommer att schemalägga två säkerhetskopior, en fullständig säkerhetskopiering varje söndag kl. 23:30 och en inkrementell säkerhetskopiering varje dag utom söndag vid samma tidpunkt, vilket visas av cron-jobbets utdata efter att ovanstående manifest har tillämpats:

(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

För mer information och tillgängliga alternativ för den här klassen (och andra klasser), kolla in alternativreferensen här.

För återställningsaspekten stöder modulen endast återställning med mysqldump backup-metoden, genom att importera SQL-filen direkt till databasen med klassen mysql::db, till exempel:

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
}

SQL-filen laddas bara en gång och inte vid varje körning, om inte enforce_sql => true används.

Konfigurationsalternativ

I det här exemplet använde vi manage_config_file => true med override_options för att strukturera våra konfigurationslinjer som senare kommer att skjutas ut av Puppet. Alla ändringar av manifestfilen kommer endast att återspegla innehållet i målkonfigurationsfilen för MySQL. Denna modul kommer varken att ladda konfigurationen till runtime eller starta om MySQL-tjänsten efter att ha tryckt in ändringarna i konfigurationsfilen. Det är systemadministratörens ansvar att starta om tjänsten för att aktivera ändringarna.

För att lägga till anpassad MySQL-konfiguration kan vi placera ytterligare filer i "includedir", som standard är /etc/mysql/conf.d. Detta tillåter oss att åsidosätta inställningar eller lägga till ytterligare, vilket är användbart om du inte använder override_options i mysql::serverklassen. Att använda sig av Puppet-mall rekommenderas starkt här. Placera den anpassade konfigurationsfilen under modulmallkatalogen (standard till , /etc/puppetlabs/code/environments/production/modules/mysql/templates) och lägg sedan till följande rader i manifestet:

# 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')
}

För att implementera versionsspecifika parametrar, använd versionsdirektivet, till exempel [mysqld-5.5]. Detta tillåter en konfiguration för olika versioner av MySQL.

Puppet vs ClusterControl

Visste du att du också kan automatisera MySQL- eller MariaDB-replikeringsdistributionen genom att använda ClusterControl? Du kan använda ClusterControl Puppet-modulen för att installera den, eller helt enkelt ladda ner den från vår webbplats.

Jämfört med ClusterControl kan du förvänta dig följande skillnader:

  • Lite av en inlärningskurva för att förstå marionettsyntaxer, formatering, strukturer innan du kan skriva manifest.
  • Manifest måste testas regelbundet. Det är mycket vanligt att du får ett kompileringsfel på koden, särskilt om katalogen används för första gången.
  • Puppet antar att koderna är idempotenta. Test-/kontroll-/verifieringsvillkoret faller under författarens ansvar för att undvika att störa ett körande system.
  • Puppet kräver en agent på den hanterade noden.
  • Bakåtinkompatibilitet. Vissa gamla moduler skulle inte fungera korrekt på den nya versionen.
  • Databas-/värdövervakning måste ställas in separat.

ClusterControls distributionsguide vägleder distributionsprocessen:

Alternativt kan du använda ClusterControls kommandoradsgränssnitt som kallas "s9s" för att uppnå liknande resultat. Följande kommando skapar ett MySQL-replikeringskluster med tre noder (förutsatt att alla noder är konfigurerade utan lösenord):

$ 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
Relaterade resurser Puppet Module for ClusterControl – Lägga till hantering och övervakning till dina befintliga databaskluster Hur man automatiserar distributionen av MySQL Galera Cluster med s9s CLI och Chef En DevOps-guide till automatisering av databasinfrastruktur för e-handel – Replay &Slides

Följande MySQL/MariaDB-replikeringsinställningar stöds:

  • Master-slave-replikering (fil-/positionsbaserad)
  • Master-slave replikering med GTID (MySQL/Percona)
  • Master-slave-replikering med MariaDB GTID
  • Master-master-replikering (semi-sync/async)
  • Master-slave kedja replikering (semi-sync/async)

Efter distributionen kan noder/kluster övervakas och helt hanteras av ClusterControl, inklusive automatisk feldetektering, master failover, slavfrämjande, automatisk återställning, backuphantering, konfigurationshantering och så vidare. Alla dessa är samlade i en produkt. Community-utgåvan (gratis för alltid!) erbjuder distribution och övervakning. I genomsnitt kommer ditt databaskluster att vara igång inom 30 minuter. Vad den behöver är endast lösenordslös SSH till målnoderna.

I nästa del kommer vi att gå igenom Galera Cluster-distribution med samma Puppet-modul. Håll utkik!


  1. Hur konverterar man en sträng till Hex och vice versa?

  2. Huvudsaklig användning av sys.dm_os_wait_stats

  3. Hur TIMEDIFF() fungerar i MariaDB

  4. Hur man kombinerar resultat av två frågor till en enda datauppsättning