sql >> Database teknologi >  >> RDS >> MariaDB

Databaseautomatisering med Puppet:Implementering af MySQL &MariaDB-replikering

Puppet er et open source-systemstyringsværktøj til centralisering og automatisering af konfigurationsstyring. Automatiseringsværktøjer hjælper med at minimere manuelle og gentagne opgaver og kan spare en masse tid.

Puppet fungerer som standard i en server/agent-model. Agenter henter deres "katalog" (endelig ønskede tilstand) fra masteren og anvender det lokalt. Så rapporterer de tilbage til serveren. Kataloget beregnes afhængigt af "fakta", som maskinen sender til serveren, brugerinput (parametre) og moduler (kildekode).

I denne blog viser vi dig, hvordan du implementerer og administrerer MySQL/MariaDB-instanser via Puppet. Der er en række teknologier omkring MySQL/MariaDB såsom replikering (master-slave, Galera eller gruppereplikering til MySQL), SQL-bevidste load balancers som ProxySQL og MariaDB MaxScale, backup- og gendannelsesværktøjer og mange flere, som vi vil dække i dette blog serie. Der er også mange moduler tilgængelige i Puppet Forge bygget og vedligeholdt af fællesskabet, som kan hjælpe os med at forenkle koden og undgå at genopfinde hjulet. I denne blog vil vi fokusere på MySQL-replikering.

puppetlabs/mysql

Dette er det mest populære Puppet-modul til MySQL og MariaDB (og sandsynligvis det bedste på markedet) lige nu. Dette modul administrerer både installationen og konfigurationen af ​​MySQL, samt udvider Puppet til at tillade administration af MySQL-ressourcer, såsom databaser, brugere og bevillinger.

Modulet vedligeholdes officielt af Puppet-teamet (via puppetlabs Github repository) og understøtter alle større versioner af 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 platforme. Brugeren har muligheder for at installere MySQL, MariaDB og Percona Server ved at tilpasse pakkelageret

Følgende eksempel viser, hvordan man implementerer en MySQL-server. Installer MySQL-modulet på dukkemesteren og opret manifestfilen:

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

Tilføj følgende linjer:

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 derefter følgende kommando på puppet agent noden for at anvende konfigurationskataloget:

(db1.local)$ puppet agent -t

Ved første kørsel får du muligvis følgende fejl:

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

Bare kør følgende kommando på Puppet Master for at underskrive certifikatet:

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

Prøv igen med kommandoen "puppet agent -t" for at genstarte forbindelsen med det signerede certifikat.

Ovenstående definition vil installere de standard MySQL-relaterede pakker, der er tilgængelige i OS distributionslager. For eksempel, på Ubuntu 18.04 (Bionic), vil du få MySQL 5.7.26-pakker installeret:

(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ælge andre leverandører som Oracle, Percona eller MariaDB med ekstra konfiguration på lageret (se afsnittet README for detaljer). Følgende definition vil installere MariaDB-pakkerne fra MariaDB apt-lageret (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']
}

Vær opmærksom på nøgle->id-værdien, hvor der er en særlig måde at hente 40-tegns-id'et på som vist i denne artikel:

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

Hvor id-værdien er i linjen, startede med "fpr", som er 'A6E773A1812E4B8FD94024AAC0F47944DE8F6914'.

Efter at Puppet-kataloget er anvendt, kan du få direkte adgang til MySQL-konsollen som root uden eksplicit adgangskode, da modulet konfigurerer og administrerer ~/.my.cnf automatisk. Hvis vi ønsker at nulstille root-adgangskoden til noget andet, skal du blot ændre root_password-værdien i Puppet-definitionen og anvende kataloget på agentnoden.

MySQL-replikeringsimplementering

For at implementere en MySQL-replikeringsopsætning skal man oprette mindst to typer konfiguration for at adskille master- og slavekonfiguration. Masteren vil have skrivebeskyttet deaktiveret for at tillade læsning/skrivning, mens slaver vil blive konfigureret med skrivebeskyttet aktiveret. I dette eksempel skal vi bruge GTID-baseret replikering til at forenkle konfigurationen (da alle noders konfiguration ville være meget ens). Vi vil gerne starte et replikeringslink til masteren lige efter at slaven er oppe.

Det antages, at vi har 3 noder MySQL master-slave replikering:

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

For at opfylde ovenstående krav kan vi skrive vores manifest ned til noget som dette:

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

Tving agenten til at anvende kataloget:

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

På masteren (db1.local) kan vi verificere alle de tilsluttede slaver:

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

Vær ekstra opmærksom på "exec { 'change master' :" sektionen, hvor det betyder, at en MySQL-kommando vil blive udført for at starte replikeringslinket, hvis betingelsen er opfyldt. Alle "exec"-ressourcer, der udføres af Puppet, skal være idempotente, hvilket betyder den operation, der vil have samme effekt, uanset om du kører den én gang eller 10.001 gange. Der er en række tilstandsattributter, du kan bruge som "medmindre", "kun hvis" og "opret" for at sikre den korrekte tilstand og forhindre Puppet i at rode med din opsætning. Du kan slette/kommentere den sektion, hvis du ønsker at starte replikeringslinket manuelt.

MySQL Management

Dette modul kan bruges til at udføre en række MySQL-administrationsopgaver:

  • konfigurationsmuligheder (ændre, anvende, tilpasset konfiguration)
  • databaseressourcer (database, bruger, bevillinger)
  • sikkerhedskopiering (opret, planlæg, sikkerhedskopier bruger, lagring)
  • simpel gendannelse (kun mysqldump)
  • installation/aktivering af plugins

Databaseressource

Som du kan se i eksempelmanifestet ovenfor, har vi defineret to MySQL-ressourcer - mysql_user og mysql_grant - for at oprette henholdsvis bruger og tildele privilegier til brugeren. Vi kan også bruge mysql::db-klassen til at sikre, at en database med tilhørende bruger og privilegier er til stede, for eksempel:

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

Bemærk, at i MySQL-replikering skal alle skrivninger kun udføres på masteren. Så sørg for, at ovenstående ressource er tildelt masteren. Ellers kan fejltransaktioner forekomme.

Sikkerhedskopiering og gendannelse

Normalt kræves der kun én backup-vært for hele klyngen (medmindre du replikerer et undersæt af data). Vi kan bruge mysql::server::backup-klassen til at forberede backup-ressourcerne. Antag, at vi har følgende erklæring i vores 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 vil konfigurere alle forudsætningerne, før du kører en sikkerhedskopi - oprettelse af backup-brugeren, forberede destinationsstien, tildele ejerskab og tilladelse, indstille cron-jobbet og konfigurere backup-kommandoindstillingerne til brug i det medfølgende backup-script placeret på /usr/local /sbin/mysqlbackup.sh. Det er derefter op til brugeren at køre eller planlægge scriptet. For at lave en øjeblikkelig backup skal du blot kalde:

$ mysqlbackup.sh

Hvis vi udtrækker den faktiske mysqldump-kommando baseret på ovenstående, ser den sådan ud:

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

For dem, der ønsker at bruge andre sikkerhedskopieringsværktøjer som Percona Xtrabackup, MariaDB Backup (kun MariaDB) eller MySQL Enterprise Backup, giver modulet følgende private klasser:

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

Eksempel på erklæring 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
  }

Ovenstående vil planlægge to sikkerhedskopier, en fuld sikkerhedskopiering hver søndag kl. 23.30 og en trinvis sikkerhedskopiering hver dag undtagen søndag på samme tid, som vist ved cron-joboutput, efter at ovenstående manifest er anvendt:

(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

For flere detaljer og tilgængelige muligheder for denne klasse (og andre klasser), tjek indstillingsreferencen her.

For gendannelsesaspektet understøtter modulet kun gendannelse med mysqldump backup-metoden ved at importere SQL-filen direkte til databasen ved hjælp af mysql::db-klassen, for eksempel:

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 vil kun blive indlæst én gang og ikke ved hver kørsel, medmindre enforce_sql => true bruges.

Konfigurationsmuligheder

I dette eksempel brugte vi manage_config_file => true med override_options til at strukturere vores konfigurationslinjer, som senere vil blive skubbet ud af Puppet. Enhver ændring af manifestfilen vil kun afspejle indholdet af MySQL-målkonfigurationsfilen. Dette modul vil hverken indlæse konfigurationen i runtime eller genstarte MySQL-tjenesten efter at have skubbet ændringerne ind i konfigurationsfilen. Det er systemadministratorens ansvar at genstarte tjenesten for at aktivere ændringerne.

For at tilføje brugerdefineret MySQL-konfiguration kan vi placere yderligere filer i "includedir", som standard er /etc/mysql/conf.d. Dette giver os mulighed for at tilsidesætte indstillinger eller tilføje yderligere, hvilket er nyttigt, hvis du ikke bruger override_options i mysql::serverklassen. Det anbefales stærkt at gøre brug af Puppet-skabelonen her. Placer den tilpassede konfigurationsfil under modulskabelonbiblioteket (standard til , /etc/puppetlabs/code/environments/production/modules/mysql/templates) og tilføj derefter følgende linjer 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')
}

For at implementere versionsspecifikke parametre skal du bruge versionsdirektivet, for eksempel [mysqld-5.5]. Dette tillader én konfiguration for forskellige versioner af MySQL.

Puppet vs ClusterControl

Vidste du, at du også kan automatisere MySQL- eller MariaDB-replikeringsimplementeringen ved at bruge ClusterControl? Du kan bruge ClusterControl Puppet-modulet til at installere det, eller blot ved at downloade det fra vores hjemmeside.

Sammenlignet med ClusterControl kan du forvente følgende forskelle:

  • Lidt af en indlæringskurve til at forstå marionetsyntakser, formatering, strukturer, før du kan skrive manifester.
  • Manifest skal testes regelmæssigt. Det er meget almindeligt, at du får en kompileringsfejl på koden, især hvis kataloget anvendes for første gang.
  • Puppet antager, at koderne er idempotente. Test/tjek/bekræft tilstanden falder ind under forfatterens ansvar for at undgå at rode med et kørende system.
  • Puppet kræver en agent på den administrerede node.
  • Inkompatibilitet bagud. Nogle gamle moduler ville ikke køre korrekt på den nye version.
  • Database-/værtsovervågning skal konfigureres separat.

ClusterControls implementeringsguide guider implementeringsprocessen:

Alternativt kan du bruge ClusterControl kommandolinjegrænseflade kaldet "s9s" for at opnå lignende resultater. Følgende kommando opretter en MySQL-replikeringsklynge med tre noder (forudsat adgangskodeløs til alle noder er konfigureret på forhånd):

$ 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
Relaterede ressourcer Puppet Module for ClusterControl - Tilføjelse af administration og overvågning til dine eksisterende databaseklynger Sådan automatiseres implementeringen af ​​MySQL Galera Cluster ved hjælp af s9s CLI og Chef En DevOps-guide til databaseinfrastrukturautomatisering til e-handel - Genafspilning og slides

Følgende MySQL/MariaDB-replikeringsopsætninger understøttes:

  • Master-slave-replikering (fil-/positionsbaseret)
  • Master-slave-replikering med GTID (MySQL/Percona)
  • Master-slave-replikering med MariaDB GTID
  • Master-master-replikering (semi-sync/async)
  • Master-slave-kædereplikation (semi-sync/async)

Efter implementeringen kan noder/klynger overvåges og administreres fuldt ud af ClusterControl, inklusive automatisk fejlregistrering, master-failover, slavepromovering, automatisk gendannelse, backupstyring, konfigurationsstyring og så videre. Alle disse er samlet i ét produkt. Fællesskabsudgaven (gratis for evigt!) tilbyder implementering og overvågning. I gennemsnit vil din databaseklynge være oppe og køre inden for 30 minutter. Det, den har brug for, er kun adgangskodefri SSH til målknuderne.

I den næste del vil vi guide dig gennem Galera Cluster-implementeringen ved hjælp af det samme Puppet-modul. Hold dig opdateret!


  1. Sådan konverteres et Unix-tidsstempel til en dato/tidsværdi i SQL Server

  2. Sådan ændres kolonne fra Null til Ikke Null i SQL Server-tabel - SQL Server / T-SQL vejledning del 52

  3. Pymysql Cursor.fetchall() / Fetchone() Returnerer ingen

  4. Henter alle overordnede rækker i én SQL-forespørgsel