sql >> Databasteknik >  >> RDS >> MariaDB

Köra ett MariaDB Galera Cluster utan Orchestration Tools - DB Container Management:Del två

Som vi såg i den första delen av den här bloggen, fungerar ett starkt konsekvent databaskluster som Galera inte bra med containerorkestreringsverktyg som Kubernetes eller Swarm. Vi visade dig hur du distribuerar Galera och konfigurerar processhantering för Docker, så att du behåller full kontroll över beteendet. Det här blogginlägget är en fortsättning på det, vi ska titta på drift och underhåll av klustret.

För att sammanfatta några av huvudpunkterna från del 1 av den här bloggen, distribuerade vi ett Galera-kluster med tre noder, med ProxySQL och Keepalved på tre olika Docker-värdar, där alla MariaDB-instanser körs som Docker-behållare. Följande diagram illustrerar den slutliga distributionen:

Graciös avstängning

För att utföra en graciös MySQL-avstängning är det bästa sättet att skicka SIGTERM (signal 15) till behållaren:

$ docker kill -s 15 {db_container_name}

Om du vill stänga av klustret, upprepa kommandot ovan på alla databasbehållare, en nod i taget. Ovanstående liknar att utföra "systemctl stop mysql" i systemd-tjänst för MariaDB. Att använda kommandot "docker stop" är ganska riskabelt för databastjänsten eftersom det väntar i 10 sekunders timeout och Docker kommer att tvinga SIGKILL om denna varaktighet överskrids (om du inte använder en korrekt --timeout värde).

Den sista noden som stänger av elegant kommer att ha seqno inte lika med -1 och safe_to_bootstrap flaggan är satt till 1 i /{datadir volume}/grastate.dat för Docker-värden, till exempel på host2:

$ cat /containers/mariadb2/datadir/grastate.dat
# GALERA saved state
version: 2.1
uuid:    e70b7437-645f-11e8-9f44-5b204e58220b
seqno:   7099
safe_to_bootstrap: 1

Detektera den mest avancerade noden

Om klustret inte stängdes av graciöst, eller om noden som du försökte bootstrap inte var den sista noden som lämnade klustret, skulle du förmodligen inte kunna bootstrap en av Galera-noderna och kan stöta på följande fel :

2016-11-07 01:49:19 5572 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node.
It was not the last one to leave the cluster and may not contain all the updates.
To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .

Galera hedrar noden som har safe_to_bootstrap flaggan satt till 1 som den första referensnoden. Detta är det säkraste sättet att undvika dataförlust och säkerställa att rätt nod alltid blir bootstrap.

Om du fick felet måste vi ta reda på den mest avancerade noden först innan vi plockar upp noden som den första som ska bootstrappas. Skapa en övergående behållare (med --rm flagga), mappa den till samma datadir och konfigurationskatalog för den faktiska databasbehållaren med två MySQL-kommandoflaggor, --wsrep_recover och --wsrep_cluster_address . Om vi ​​t.ex. vill veta mariadb1 senast registrerade nummer, måste vi köra:

$ docker run --rm --name mariadb-recover \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb1/datadir:/var/lib/mysql \
        --volume /containers/mariadb1/conf.d:/etc/mysql/conf.d \
        mariadb:10.2.15 \
        --wsrep_recover \
        --wsrep_cluster_address=gcomm://
2018-06-12  4:46:35 139993094592384 [Note] mysqld (mysqld 10.2.15-MariaDB-10.2.15+maria~jessie) starting as process 1 ...
2018-06-12  4:46:35 139993094592384 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
...
2018-06-12  4:46:35 139993094592384 [Note] Plugin 'FEEDBACK' is disabled.
2018-06-12  4:46:35 139993094592384 [Note] Server socket created on IP: '::'.
2018-06-12  4:46:35 139993094592384 [Note] WSREP: Recovered position: e70b7437-645f-11e8-9f44-5b204e58220b:7099

Den sista raden är vad vi letar efter. MariaDB skriver ut klustrets UUID och sekvensnumret för den senast genomförda transaktionen. Den nod som har det högsta antalet anses vara den mest avancerade noden. Eftersom vi angav --rm , kommer behållaren att tas bort automatiskt när den lämnas. Upprepa steget ovan på varje Docker-värd genom att ersätta --volymen sökväg till respektive databascontainervolymer.

När du har jämfört värdet som rapporterats av alla databasbehållare och bestämt vilken behållare som är den mest uppdaterade noden, ändra safe_to_bootstrap flagga till 1 inuti /{datadir volume}/grastate.dat manuellt. Låt oss säga att alla noder rapporterar samma exakta sekvensnummer, vi kan bara välja att mariadb3 ska bootstrappas genom att ändra safe_to_bootstrap värde till 1:

$ vim /containers/mariadb3/datadir/grasate.dat
...
safe_to_bootstrap: 1

Spara filen och börja starta upp klustret från den noden, som beskrivs i nästa kapitel.

Starta klustret

Bootstrapping av klustret liknar det första docker run-kommandot som vi använde när vi startade klustret för första gången. Om mariadb1 är den valda bootstrap-noden, kan vi helt enkelt köra om den skapade bootstrap-behållaren:

$ docker start mariadb0 # on host1

Annars, om bootstrap-behållaren inte finns på den valda noden, låt oss säga på host2, kör kommandot bootstrap container och mappar den befintliga mariadb2:s volymer. Vi använder mariadb0 som behållarnamn på värd2 för att indikera att det är en bootstrap-behållare:

$ docker run -d \
        --name mariadb0 \
        --hostname mariadb0.weave.local \
        --net weave \
        --publish "3306" \
        --publish "4444" \
        --publish "4567" \
        --publish "4568" \
        $(weave dns-args) \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb2/datadir:/var/lib/mysql \
        --volume /containers/mariadb2/conf.d:/etc/mysql/mariadb.conf.d \
        mariadb:10.2.15 \
        --wsrep_cluster_address=gcomm:// \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb0.weave.local

Du kanske märker att det här kommandot är något kortare jämfört med det tidigare bootstrap-kommandot som beskrivs i den här guiden. Eftersom vi redan har proxysql-användaren skapad i vårt första bootstrap-kommando, kan vi hoppa över dessa två miljövariabler:

  • --env MYSQL_USER=proxysql
  • --env MYSQL_PASSWORD=proxysqllösenord

Starta sedan de återstående MariaDB-behållarna, ta bort bootstrap-behållaren och starta den befintliga MariaDB-behållaren på bootstrap-värden. Ordningen på kommandon skulle i princip vara:

$ docker start mariadb1 # on host1
$ docker start mariadb3 # on host3
$ docker stop mariadb0 # on host2
$ docker start mariadb2 # on host2

Vid denna tidpunkt startas klustret och körs med full kapacitet.

Resurskontroll

Minne är en mycket viktig resurs i MySQL. Det är här buffertarna och cacharna lagras, och det är avgörande för MySQL att minska effekten av att träffa disken för ofta. Å andra sidan är byte dåligt för MySQL-prestandan. Som standard kommer det inte att finnas några resursbegränsningar på de körande behållarna. Behållare använder så mycket av en given resurs som värdens kärna tillåter. En annan viktig sak är filbeskrivningsgräns. Du kan öka gränsen för öppen filbeskrivning, eller "nofile" till något högre för att tillgodose antalet filer som MySQL-servern kan öppna samtidigt. Att ställa in detta till ett högt värde skadar inte.

För att begränsa minnesallokeringen och öka filbeskrivningsgränsen för vår databasbehållare, skulle man lägga till --minne , --minnesbyte och --ulimit parametrar i kommandot "docker run":

$ docker kill -s 15 mariadb1
$ docker rm -f mariadb1
$ docker run -d \
        --name mariadb1 \
        --hostname mariadb1.weave.local \
        --net weave \
        --publish "3306:3306" \
        --publish "4444" \
        --publish "4567" \
        --publish "4568" \
        $(weave dns-args) \
        --memory 16g \
        --memory-swap 16g \
        --ulimit nofile:16000:16000 \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb1/datadir:/var/lib/mysql \
        --volume /containers/mariadb1/conf.d:/etc/mysql/mariadb.conf.d \
        mariadb:10.2.15 \
        --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb1.weave.local

Observera att om --minne-byte är satt till samma värde som --minne och --minne är inställt på ett positivt heltal, kommer behållaren inte att ha tillgång till swap. Om --minne-byte inte är inställt, kommer containerbyte som standard till --minne multiplicera med 2. Om --minne och --minnesbyte är inställda på samma värde, kommer detta att förhindra behållare från att använda någon swap. Detta beror på att --minnesbyte är mängden kombinerat minne och swap som kan användas, medan --minne är bara mängden fysiskt minne som kan användas.

Vissa av behållarresurserna som minne och CPU kan styras dynamiskt med kommandot "docker update", som visas i följande exempel för att uppgradera minnet för behållaren mariadb1 till 32G i farten:

$ docker update \
    --memory 32g \
    --memory-swap 32g \
    mariadb1

Glöm inte att justera my.cnf för att passa de nya specifikationerna. Konfigurationshantering förklaras i nästa avsnitt.

Konfigurationshantering

De flesta av MySQL/MariaDB-konfigurationsparametrarna kan ändras under körning, vilket innebär att du inte behöver starta om för att tillämpa ändringarna. Kolla in MariaDB-dokumentationssidan för detaljer. Parametern listad med "Dynamiskt:Ja" betyder att variabeln laddas omedelbart efter ändring utan att behöva starta om MariaDB-servern. Annars ställer du in parametrarna i den anpassade konfigurationsfilen i Docker-värden. Till exempel, på mariadb3, gör ändringarna i följande fil:

$ vim /containers/mariadb3/conf.d/my.cnf

Och starta sedan om databasbehållaren för att tillämpa ändringen:

$ docker restart mariadb3

Verifiera att behållaren startar processen genom att titta på docker-loggarna. Utför den här operationen på en nod i taget om du vill göra klusteromfattande ändringar.

Säkerhetskopiering

Att ta en logisk säkerhetskopia är ganska enkelt eftersom MariaDB-bilden också kommer med mysqldump binär. Du använder helt enkelt kommandot "docker exec" för att köra mysqldump och skicka utdata till en fil i förhållande till värdsökvägen. Följande kommando utför mysqldump backup på mariadb2 och sparar den till /backups/mariadb2 inuti host2:

$ docker exec -it mariadb2 mysqldump -uroot -p --single-transaction > /backups/mariadb2/dump.sql

Binär säkerhetskopiering som Percona Xtrabackup eller MariaDB Backup kräver processen för att komma åt MariaDB-datakatalogen direkt. Du måste antingen installera det här verktyget inuti behållaren eller genom maskinvärden eller använda en dedikerad bild för detta ändamål som "perconalab/percona-xtrabackup"-bild för att skapa säkerhetskopian och lagra den inuti /tmp/backup på Docker-värden:

$ docker run --rm -it \
    -v /containers/mariadb2/datadir:/var/lib/mysql \
    -v /tmp/backup:/xtrabackup_backupfiles \
    perconalab/percona-xtrabackup \
    --backup --host=mariadb2 --user=root --password=mypassword

Du kan också stoppa behållaren med innodb_fast_shutdown ställ in till 0 och kopiera över datadir-volymen till en annan plats i den fysiska värden:

$ docker exec -it mariadb2 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
$ docker kill -s 15 mariadb2
$ cp -Rf /containers/mariadb2/datadir /backups/mariadb2/datadir_copied
$ docker start mariadb2

Återställ

Att återställa är ganska enkelt för mysqldump. Du kan helt enkelt omdirigera stdin till behållaren från den fysiska värden:

$ docker exec -it mariadb2 mysql -uroot -p < /backups/mariadb2/dump.sql

Du kan också använda den vanliga mysql-klientens kommandorad på distans med rätt värdnamn och portvärde istället för att använda detta "docker exec"-kommando:

$ mysql -uroot -p -h127.0.0.1 -P3306 < /backups/mariadb2/dump.sql

För Percona Xtrabackup och MariaDB Backup måste vi förbereda säkerhetskopian i förväg. Detta rullar säkerhetskopieringen framåt till den tidpunkt då säkerhetskopieringen var klar. Låt oss säga att våra Xtrabackup-filer finns under /tmp/backup av Docker-värden, för att förbereda det, helt enkelt:

$ docker run --rm -it \
    -v mysql-datadir:/var/lib/mysql \
    -v /tmp/backup:/xtrabackup_backupfiles \
    perconalab/percona-xtrabackup \
    --prepare --target-dir /xtrabackup_backupfiles

Den förberedda säkerhetskopian under /tmp/backup av Docker-värden kan sedan användas som MariaDB datadir för en ny behållare eller kluster. Låt oss säga att vi bara vill verifiera återställning på en fristående MariaDB-behållare, vi skulle köra:

$ docker run -d \
    --name mariadb-restored \
    --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
    -v /tmp/backup:/var/lib/mysql \
    mariadb:10.2.15

Om du utförde en säkerhetskopiering med stopp- och kopieringsmetoden kan du helt enkelt duplicera datadirigenten och använda den duplicerade katalogen som en volymmappar till MariaDB datadir för att köras på en annan behållare. Låt oss säga att säkerhetskopian kopierades över under /backups/mariadb2/datadir_copied, vi kan köra en ny behållare genom att köra:

$ mkdir -p /containers/mariadb-restored/datadir
$ cp -Rf /backups/mariadb2/datadir_copied /containers/mariadb-restored/datadir
$ docker run -d \
    --name mariadb-restored \
    --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
    -v /containers/mariadb-restored/datadir:/var/lib/mysql \
    mariadb:10.2.15

MYSQL_ROOT_PASSWORD måste matcha det faktiska root-lösenordet för just den säkerhetskopian.

Severalnines MySQL på Docker:How to Containerize Your DatabaseUpptäck allt du behöver förstå när du överväger att köra en MySQL-tjänst ovanpå Docker containervirtualisering Ladda ner Whitepaper

Uppgradering av databasversion

Det finns två typer av uppgradering - uppgradering på plats eller logisk uppgradering.

Uppgradering på plats involverar att stänga av MariaDB-servern, ersätta de gamla binärerna med de nya binärerna och sedan starta servern på den gamla datakatalogen. När du har startat måste du köra mysql_upgrade skript för att kontrollera och uppgradera alla systemtabeller och även för att kontrollera användartabellerna.

Den logiska uppgraderingen innebär att exportera SQL från den aktuella versionen med hjälp av ett logiskt säkerhetskopieringsverktyg som mysqldump, köra den nya behållaren med de uppgraderade versionsbinärfilerna och sedan tillämpa SQL på den nya MySQL/MariaDB-versionen. Det liknar säkerhetskopierings- och återställningsmetoden som beskrivs i föregående avsnitt.

Ändå är det en bra metod att alltid säkerhetskopiera din databas innan du utför några destruktiva operationer. Följande steg krävs när du uppgraderar från den aktuella bilden, MariaDB 10.1.33 till en annan större version, MariaDB 10.2.15 på mariadb3 finns på host3:

  1. Säkerhetskopiera databasen. Det spelar ingen roll fysisk eller logisk säkerhetskopiering men den senare med mysqldump rekommenderas.

  2. Ladda ner den senaste bilden som vi vill uppgradera till:

    $ docker pull mariadb:10.2.15
  3. Sätt innodb_fast_shutdown till 0 för vår databasbehållare:

    $ docker exec -it mariadb3 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
  4. Stäng graciöst av databasbehållaren:

    $ docker kill --signal=TERM mariadb3
  5. Skapa en ny behållare med den nya bilden för vår databasbehållare. Behåll resten av parametrarna intakta förutom att använda det nya behållarnamnet (annars skulle det komma i konflikt):

    $ docker run -d \
            --name mariadb3-new \
            --hostname mariadb3.weave.local \
            --net weave \
            --publish "3306:3306" \
            --publish "4444" \
            --publish "4567" \
            --publish "4568" \
            $(weave dns-args) \
            --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
            --volume /containers/mariadb3/datadir:/var/lib/mysql \
            --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
            mariadb:10.2.15 \
            --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
            --wsrep_sst_auth="root:PM7%[email protected]^1" \
            --wsrep_node_address=mariadb3.weave.local
  6. Kör mysql_upgrade script:

    $ docker exec -it mariadb3-new mysql_upgrade -uroot -p
  7. Om inga fel inträffade, ta bort den gamla behållaren, mariadb3 (den nya är mariadb3-new):

    $ docker rm -f mariadb3
  8. Annars, om uppgraderingsprocessen misslyckas däremellan, kan vi falla tillbaka till föregående behållare:

    $ docker stop mariadb3-new
    $ docker start mariadb3

Större versionsuppgradering kan utföras på samma sätt som den mindre versionsuppgraderingen, förutom att du måste komma ihåg att MySQL/MariaDB endast stöder större uppgradering från den tidigare versionen. Om du använder MariaDB 10.0 och vill uppgradera till 10.2 måste du först uppgradera till MariaDB 10.1, följt av ytterligare ett uppgraderingssteg till MariaDB 10.2.

Notera att konfigurationsändringarna införs och fasas ut mellan större versioner.

Failover

I Galera är alla noder mästare och har samma roll. Med ProxySQL i bilden kommer anslutningar som passerar genom denna gateway att misslyckas automatiskt så länge det finns en primär komponent som körs för Galera Cluster (det vill säga en majoritet av noderna är uppe). Applikationen kommer inte att märka någon skillnad om en databasnod går ner eftersom ProxySQL helt enkelt omdirigerar anslutningarna till de andra tillgängliga noderna.

Om applikationen ansluter direkt till MariaDB som förbigår ProxySQL, måste failover utföras på applikationssidan genom att peka på nästa tillgängliga nod, förutsatt att databasnoden uppfyller följande villkor:

  • Status wsrep_local_state_comment är synkroniserad (tillståndet "Avsynkroniserad/donator" är också möjligt, bara om wsrep_sst_method är xtrabackup, xtrabackup-v2 eller mariabackup).
  • Status wsrep_cluster_status är primär.

I Galera betyder en tillgänglig nod inte att den är frisk förrän ovanstående status har verifierats.

Utskalning

För att skala ut kan vi skapa en ny behållare i samma nätverk och använda samma anpassade konfigurationsfil för den befintliga behållaren på just den värden. Låt oss till exempel säga att vi vill lägga till den fjärde MariaDB-behållaren på host3, vi kan använda samma konfigurationsfil monterad för mariadb3, som illustreras i följande diagram:

Kör följande kommando på host3 för att skala ut:

$ docker run -d \
        --name mariadb4 \
        --hostname mariadb4.weave.local \
        --net weave \
        --publish "3306:3307" \
        --publish "4444" \
        --publish "4567" \
        --publish "4568" \
        $(weave dns-args) \
        --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
        --volume /containers/mariadb4/datadir:/var/lib/mysql \
        --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
        mariadb:10.2.15 \
        --wsrep_cluster_address=gcomm://mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local,mariadb4.weave.local \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb4.weave.local

När behållaren har skapats kommer den att gå med i klustret och utföra SST. Den kan nås på port 3307 externt eller utanför Weave-nätverket, eller port 3306 inom värden eller inom Weave-nätverket. Det är inte nödvändigt att inkludera mariadb0.weave.local i klusteradressen längre. När klustret har skalats ut måste vi lägga till den nya MariaDB-behållaren i ProxySQL-lastbalanseringsuppsättningen via administratörskonsolen:

$ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (10,'mariadb4.weave.local',3306);
mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (20,'mariadb4.weave.local',3306);
mysql> LOAD MYSQL SERVERS TO RUNTIME;
mysql> SAVE MYSQL SERVERS TO DISK;

Upprepa ovanstående kommandon på den andra ProxySQL-instansen.

Slutligen för det sista steget, (du kan hoppa över den här delen om du redan körde "SAVE .. TO DISK"-satsen i ProxySQL), lägg till följande rad i proxysql.cnf för att göra den beständig under omstart av behållare på värd1 och värd2:

$ vim /containers/proxysql1/proxysql.cnf # host1
$ vim /containers/proxysql2/proxysql.cnf # host2

Och lägg till mariadb4-relaterade rader under mysql_server-direktivet:

mysql_servers =
(
        { address="mariadb1.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb2.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb3.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb4.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
        { address="mariadb1.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
        { address="mariadb2.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
        { address="mariadb3.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
        { address="mariadb4.weave.local" , port=3306 , hostgroup=20, max_connections=100 }
)

Spara filen så borde vi vara bra vid nästa omstart av behållaren.

Skala ner

För att skala ner, stänger du helt enkelt av behållaren graciöst. Det bästa kommandot skulle vara:

$ docker kill -s 15 mariadb4
$ docker rm -f mariadb4

Kom ihåg att om databasnoden lämnade klustret fult, var det inte en del av nedskalningen och skulle påverka kvorumberäkningen.

För att ta bort behållaren från ProxySQL, kör följande kommandon på båda ProxySQL-behållarna. Till exempel på proxysql1:

$ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
mysql> DELETE FROM mysql_servers WHERE hostname="mariadb4.weave.local";
mysql> LOAD MYSQL SERVERS TO RUNTIME;
mysql> SAVE MYSQL SERVERS TO DISK;

Du kan sedan antingen ta bort motsvarande post inuti proxysql.cnf eller bara lämna det så. Det kommer att upptäckas som OFFLINE från ProxySQL-synpunkt i alla fall.

Sammanfattning

Med Docker blir saker lite annorlunda än det konventionella sättet att hantera MySQL- eller MariaDB-servrar. Att hantera tillståndsfulla tjänster som Galera Cluster är inte lika lätt som tillståndslösa applikationer och kräver korrekt testning och planering.

I vår nästa blogg om detta ämne kommer vi att utvärdera för- och nackdelarna med att köra Galera Cluster på Docker utan några orkestreringsverktyg.


  1. Skapa en lagrad procedur i SQL Server 2017

  2. Konvertera 'tid' till 'datetime2' i SQL Server (T-SQL-exempel)

  3. Hur man använder ALL Logical Operator i SQL Server - SQL Server / TSQL Tutorial Del 126

  4. Oracle Floats vs Number