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

Ausführen eines MariaDB Galera-Clusters ohne Container-Orchestrierungstools:Teil Eins

Container-Orchestrierungstools vereinfachen den Betrieb eines verteilten Systems, indem Container bereitgestellt und erneut bereitgestellt und auftretende Fehler behandelt werden. Möglicherweise müssen Anwendungen verschoben werden, z. B. um Aktualisierungen, Skalierung oder zugrunde liegende Hostausfälle zu handhaben. Das klingt zwar großartig, funktioniert aber nicht immer gut mit einem stark konsistenten Datenbank-Cluster wie Galera. Sie können Datenbankknoten nicht einfach verschieben, sie sind keine zustandslosen Anwendungen. Auch die Reihenfolge, in der Sie Vorgänge auf einem Cluster ausführen, ist von großer Bedeutung. Beispielsweise muss der Neustart eines Galera-Clusters vom fortschrittlichsten Knoten ausgehen, sonst gehen Daten verloren. Daher zeigen wir Ihnen, wie Sie Galera Cluster auf Docker ohne ein Container-Orchestrierungstool ausführen, damit Sie die vollständige Kontrolle haben.

In diesem Blogbeitrag werden wir untersuchen, wie Sie einen MariaDB Galera-Cluster auf Docker-Containern mit dem Standard-Docker-Image auf mehreren Docker-Hosts ausführen können, ohne die Hilfe von Orchestrierungstools wie Swarm oder Kubernetes. Dieser Ansatz ähnelt dem Ausführen eines Galera-Clusters auf Standardhosts, aber das Prozessmanagement wird über Docker konfiguriert.

Bevor wir weiter ins Detail gehen, gehen wir davon aus, dass Sie Docker installiert, SElinux/AppArmor deaktiviert und die Regeln in iptables, firewalld oder ufw (je nachdem, was Sie verwenden) gelöscht haben. Im Folgenden sind drei dedizierte Docker-Hosts für unseren Datenbankcluster aufgeführt:

  • host1.local - 192.168.55.161
  • host2.local - 192.168.55.162
  • host3.local - 192.168.55.163

Netzwerk mit mehreren Hosts

Zunächst einmal ist das standardmäßige Docker-Netzwerk an den lokalen Host gebunden. Docker Swarm führt eine weitere Netzwerkschicht namens Overlay Network ein, die das Container-Internetworking auf mehrere Docker-Hosts in einem Cluster namens Swarm erweitert. Lange bevor diese Integration eingeführt wurde, wurden viele Netzwerk-Plugins entwickelt, um dies zu unterstützen - Flannel, Calico, Weave sind einige davon.

Hier verwenden wir Weave als Docker-Netzwerk-Plugin für Multi-Host-Netzwerke. Dies liegt hauptsächlich daran, dass es einfach installiert und ausgeführt werden kann, und dass der DNS-Resolver unterstützt wird (Container, die unter diesem Netzwerk ausgeführt werden, können den Hostnamen des anderen auflösen). Es gibt zwei Möglichkeiten, Weave zum Laufen zu bringen – systemd oder über Docker. Wir werden es als systemd-Einheit installieren, also ist es unabhängig vom Docker-Daemon (andernfalls müssten wir zuerst Docker starten, bevor Weave aktiviert wird).

  1. Laden Sie Weave herunter und installieren Sie es:

    $ curl -L git.io/weave -o /usr/local/bin/weave
    $ chmod a+x /usr/local/bin/weave
  2. Erstellen Sie eine systemd-Unit-Datei für Weave:

    $ cat > /etc/systemd/system/weave.service << EOF
    [Unit]
    Description=Weave Network
    Documentation=http://docs.weave.works/weave/latest_release/
    Requires=docker.service
    After=docker.service
    [Service]
    EnvironmentFile=-/etc/sysconfig/weave
    ExecStartPre=/usr/local/bin/weave launch --no-restart $PEERS
    ExecStart=/usr/bin/docker attach weave
    ExecStop=/usr/local/bin/weave stop
    [Install]
    WantedBy=multi-user.target
    EOF
  3. Definieren Sie IP-Adressen oder Hostnamen der Peers in /etc/sysconfig/weave:

    $ echo 'PEERS="192.168.55.161 192.168.55.162 192.168.55.163"' > /etc/sysconfig/weave
  4. Starten und aktivieren Sie Weave beim Booten:

    $ systemctl start weave
    $ systemctl enable weave

Wiederholen Sie die obigen 4 Schritte auf allen Docker-Hosts. Überprüfen Sie dies mit dem folgenden Befehl, sobald Sie fertig sind:

$ weave status

Die Anzahl der Peers ist das, worauf wir achten. Es sollte 3:

sein
          ...
          Peers: 3 (with 6 established connections)
          ...

Betreiben eines Galera-Clusters

Jetzt ist das Netzwerk bereit, es ist Zeit, unsere Datenbankcontainer zu feuern und einen Cluster zu bilden. Die Grundregeln sind:

  • Container muss unter --net=weave erstellt werden, um Multi-Host-Konnektivität zu haben.
  • Container-Ports, die veröffentlicht werden müssen, sind 3306, 4444, 4567, 4568.
  • Das Docker-Image muss Galera unterstützen. Wenn Sie Oracle MySQL verwenden möchten, dann holen Sie sich die Codership-Version. Wenn Sie Perconas möchten, verwenden Sie stattdessen dieses Bild. In diesem Blogbeitrag verwenden wir MariaDBs.

Die Gründe, warum wir uns für MariaDB als Anbieter von Galera-Clustern entschieden haben, sind:

  • Galera ist in MariaDB eingebettet, beginnend mit MariaDB 10.1.
  • Das MariaDB-Image wird von den Docker- und MariaDB-Teams gepflegt.
  • Eines der beliebtesten Docker-Images da draußen.

Das Bootstrapping eines Galera-Clusters muss nacheinander durchgeführt werden. Zunächst muss der aktuellste Knoten mit „wsrep_cluster_address=gcomm://“ gestartet werden. Starten Sie dann die verbleibenden Knoten mit einer vollständigen Adresse, die aus allen Knoten im Cluster besteht, z. B. "wsrep_cluster_address=gcomm://node1,node2,node3". Um diese Schritte mithilfe von Containern auszuführen, müssen wir einige zusätzliche Schritte ausführen, um sicherzustellen, dass alle Container homogen ausgeführt werden. Der Plan ist also:

  1. Wir müssten mit 4 Containern in dieser Reihenfolge beginnen - mariadb0 (Bootstrap), mariadb2, mariadb3, mariadb1.
  2. Container mariadb0 wird dasselbe datadir und configdir wie mariadb1 verwenden.
  3. Verwenden Sie mariadb0 auf Host1 für den ersten Bootstrap, starten Sie dann mariadb2 auf Host2, mariadb3 auf Host3.
  4. Entfernen Sie mariadb0 auf host1, um Platz für mariadb1 zu machen.
  5. Zu guter Letzt starten Sie mariadb1 auf host1.

Am Ende des Tages hätten Sie einen Galera-Cluster mit drei Knoten (mariadb1, mariadb2, mariadb3). Der erste Container (mariadb0) ist ein vorübergehender Container nur für Bootstrapping-Zwecke und verwendet die Cluster-Adresse „gcomm://“. Es teilt das gleiche Daten- und Konfigurationsverzeichnis mit mariadb1 und wird entfernt, sobald der Cluster gebildet ist (mariadb2 und mariadb3 sind aktiv) und die Knoten synchronisiert sind.

Standardmäßig ist Galera in MariaDB deaktiviert und muss mit einem Flag namens wsrep_on aktiviert werden (auf ON gesetzt) ​​und wsrep_provider (auf den Galera-Bibliothekspfad gesetzt) ​​plus eine Reihe von Galera-bezogenen Parametern. Daher müssen wir eine benutzerdefinierte Konfigurationsdatei für den Container definieren, um Galera korrekt zu konfigurieren.

Beginnen wir mit dem ersten Container, mariadb0. Erstellen Sie eine Datei unter /containers/mariadb1/conf.d/my.cnf und fügen Sie die folgenden Zeilen hinzu:

$ mkdir -p /containers/mariadb1/conf.d
$ cat /containers/mariadb1/conf.d/my.cnf
[mysqld]

default_storage_engine          = InnoDB
binlog_format                   = ROW

innodb_flush_log_at_trx_commit  = 0
innodb_flush_method             = O_DIRECT
innodb_file_per_table           = 1
innodb_autoinc_lock_mode        = 2
innodb_lock_schedule_algorithm  = FCFS # MariaDB >10.1.19 and >10.2.3 only

wsrep_on                        = ON
wsrep_provider                  = /usr/lib/galera/libgalera_smm.so
wsrep_sst_method                = xtrabackup-v2

Da das Image nicht mit MariaDB Backup geliefert wird (was die bevorzugte SST-Methode für MariaDB 10.1 und MariaDB 10.2 ist), werden wir vorerst bei xtrabackup-v2 bleiben.

Um den ersten Bootstrap für den Cluster durchzuführen, führen Sie den Bootstrap-Container (mariadb0) auf host1 mit „datadir“ und „conf.d“ von mariadb1 aus:

$ 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" \
        --env MYSQL_USER=proxysql \
        --env MYSQL_PASSWORD=proxysqlpassword \
        --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:// \
        --wsrep_sst_auth="root:PM7%[email protected]^1" \
        --wsrep_node_address=mariadb0.weave.local

Die im obigen Befehl verwendeten Parameter sind:

  • --name , erstellt den Container namens "mariadb0",
  • --hostname , weist dem Container einen Hostnamen "mariadb0.weave.local" zu,
  • --net , platziert den Container im Weave-Netzwerk für die Unterstützung von Netzwerken mit mehreren Hosts,
  • --veröffentlichen , macht die Ports 3306, 4444, 4567, 4568 auf dem Container für den Host verfügbar,
  • $(weave dns-args) , konfiguriert den DNS-Resolver für diesen Container. Dieser Befehl kann als "--dns=172.17.0.1 --dns-search=weave.local.",
  • in Docker übersetzt werden
  • --env MYSQL_ROOT_PASSWORD , das MySQL-Root-Passwort,
  • --env MYSQL_USER , erstellt einen "proxysql"-Benutzer, der später mit ProxySQL für das Datenbank-Routing verwendet wird,
  • --env MYSQL_PASSWORD , das "proxysql"-Benutzerkennwort,
  • --volume /containers/mariadb1/datadir:/var/lib/mysql , erstellt /containers/mariadb1/datadir falls nicht vorhanden und ordnet es /var/lib/mysql (MySQL datadir) des Containers zu (für den Bootstrap-Knoten könnte dies übersprungen werden),
  • --volume /containers/mariadb1/conf.d:/etc/mysql/mariadb.conf.d , mountet die Dateien im Verzeichnis /containers/mariadb1/conf.d des Docker-Hosts in den Container unter /etc/mysql/mariadb.conf.d.
  • mariadb:10.2.15 , verwendet das MariaDB 10.2.15-Image von hier,
  • --wsrep_cluster_address , Galera-Verbindungszeichenfolge für den Cluster. „gcomm://“ bedeutet Bootstrap. Für die restlichen Container verwenden wir stattdessen eine vollständige Adresse.
  • --wsrep_sst_auth , Authentifizierungszeichenfolge für SST-Benutzer. Verwenden Sie denselben Benutzer wie root,
  • --wsrep_node_address , dem Hostnamen des Knotens, in diesem Fall verwenden wir den von Weave bereitgestellten FQDN.

Der Bootstrap-Container enthält mehrere wichtige Dinge:

  • Der Name, der Hostname und die wsrep_node_address sind mariadb0, aber es verwendet die Volumes von mariadb1.
  • Die Clusteradresse lautet "gcomm://"
  • Es gibt zwei zusätzliche --env Parameter - MYSQL_USER und MYSQL_PASSWORD. Dieser Parameter erstellt zusätzliche Benutzer für unsere Proxysql-Überwachungszwecke.

Überprüfen Sie dies mit dem folgenden Befehl:

$ docker ps
$ docker logs -f mariadb0

Sobald Sie die folgende Zeile sehen, zeigt dies an, dass der Bootstrap-Prozess abgeschlossen und Galera aktiv ist:

2018-05-30 23:19:30 139816524539648 [Note] WSREP: Synchronized with group, ready for connections

Erstellen Sie das Verzeichnis, um unsere benutzerdefinierte Konfigurationsdatei in den verbleibenden Hosts zu laden:

$ mkdir -p /containers/mariadb2/conf.d # on host2
$ mkdir -p /containers/mariadb3/conf.d # on host3

Kopieren Sie dann die my.cnf, die wir für mariadb0 und mariadb1 erstellt haben, nach mariadb2 bzw. mariadb3:

$ scp /containers/mariadb1/conf.d/my.cnf /containers/mariadb2/conf.d/ # on host1
$ scp /containers/mariadb1/conf.d/my.cnf /containers/mariadb3/conf.d/ # on host1

Erstellen Sie als Nächstes zwei weitere Datenbankcontainer (mariadb2 und mariadb3) auf host2 bzw. host3:

$ docker run -d \
        --name ${NAME} \
        --hostname ${NAME}.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/${NAME}/datadir:/var/lib/mysql \
        --volume /containers/${NAME}/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=${NAME}.weave.local

** Ersetzen Sie ${NAME} durch mariadb2 bzw. mariadb3.

Allerdings gibt es einen Haken. Das Entrypoint-Skript überprüft den mysqld-Dienst im Hintergrund nach der Datenbankinitialisierung, indem es den MySQL-Root-Benutzer ohne Passwort verwendet. Da Galera beim Start automatisch eine Synchronisierung über SST oder IST durchführt, ändert sich das Passwort des MySQL-Root-Benutzers und spiegelt den Bootstrap-Knoten wider. Daher würden Sie beim ersten Start den folgenden Fehler sehen:

018-05-30 23:27:13 140003794790144 [Warning] Access denied for user 'root'@'localhost' (using password: NO)
MySQL init process in progress…
MySQL init process failed.

Der Trick besteht darin, die fehlgeschlagenen Container noch einmal neu zu starten, da diesmal das MySQL-Datenverzeichnis erstellt worden wäre (beim ersten Ausführungsversuch) und den Datenbankinitialisierungsteil übersprungen hätte:

$ docker start mariadb2 # on host2
$ docker start mariadb3 # on host3

Überprüfen Sie nach dem Start die folgende Zeile:

$ docker logs -f mariadb2
…
2018-05-30 23:28:39 139808069601024 [Note] WSREP: Synchronized with group, ready for connections

An diesem Punkt laufen 3 Container, mariadb0, mariadb2 und mariadb3. Beachten Sie, dass mariadb0 mit dem Bootstrap-Befehl (gcomm://) gestartet wird, was bedeutet, dass der Container, wenn er in Zukunft automatisch von Docker neu gestartet wird, möglicherweise von der primären Komponente getrennt wird. Daher müssen wir diesen Container entfernen und durch mariadb1 ersetzen, indem wir dieselbe Galera-Verbindungszeichenfolge wie der Rest verwenden und dasselbe datadir und configdir mit mariadb0 verwenden.

Stoppen Sie zuerst mariadb0, indem Sie SIGTERM senden (um sicherzustellen, dass der Knoten ordnungsgemäß heruntergefahren wird):

$ docker kill -s 15 mariadb0

Starten Sie dann mariadb1 auf host1 mit einem ähnlichen Befehl wie mariadb2 oder mariadb3:

$ docker run -d \
        --name mariadb1 \
        --hostname mariadb1.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/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

Diesmal müssen Sie den Neustart-Trick nicht ausführen, da MySQL datadir bereits existiert (erstellt von mariadb0). Nachdem der Container gestartet wurde, vergewissern Sie sich, dass die Clustergröße 3 ist, der Status Primär sein muss und der lokale Status synchronisiert ist:

$ docker exec -it mariadb3 mysql -uroot "-pPM7%[email protected]^1" -e 'select variable_name, variable_value from information_schema.global_status where variable_name in ("wsrep_cluster_size", "wsrep_local_state_comment", "wsrep_cluster_status", "wsrep_incoming_addresses")'
+---------------------------+-------------------------------------------------------------------------------+
| variable_name             | variable_value                                                                |
+---------------------------+-------------------------------------------------------------------------------+
| WSREP_CLUSTER_SIZE        | 3                                                                             |
| WSREP_CLUSTER_STATUS      | Primary                                                                       |
| WSREP_INCOMING_ADDRESSES  | mariadb1.weave.local:3306,mariadb3.weave.local:3306,mariadb2.weave.local:3306 |
| WSREP_LOCAL_STATE_COMMENT | Synced                                                                        |
+---------------------------+-------------------------------------------------------------------------------+

An diesem Punkt sieht unsere Architektur in etwa so aus:

Obwohl der run-Befehl ziemlich lang ist, beschreibt er die Eigenschaften des Containers gut. Es ist wahrscheinlich eine gute Idee, den Befehl in ein Skript einzuschließen, um die Ausführungsschritte zu vereinfachen, oder stattdessen eine Compose-Datei zu verwenden.

Datenbankrouting mit ProxySQL

Jetzt haben wir drei Datenbankcontainer am Laufen. Die einzige Möglichkeit, auf den Cluster zuzugreifen, besteht jetzt darin, auf den veröffentlichten MySQL-Port des einzelnen Docker-Hosts zuzugreifen, der 3306 ist (dem Container 3306 zuordnen). Was passiert also, wenn einer der Datenbankcontainer ausfällt? Sie müssen die Verbindung des Clients manuell auf den nächsten verfügbaren Knoten umschalten. Je nach Anwendungskonnektor können Sie auch eine Liste von Knoten angeben und den Konnektor das Failover und Abfragerouting für Sie erledigen lassen (Connector/J, PHP mysqlnd). Andernfalls wäre es eine gute Idee, die Datenbankressourcen in einer einzigen Ressource zu vereinen, die als Dienst bezeichnet werden kann.

Hier kommt ProxySQL ins Spiel. ProxySQL kann als Abfragerouter fungieren und die Datenbankverbindungen ähnlich wie „Service“ in der Swarm- oder Kubernetes-Welt ausgleichen. Wir haben zu diesem Zweck ein ProxySQL-Docker-Image erstellt und werden das Image nach besten Kräften für jede neue Version pflegen.

Bevor wir den ProxySQL-Container ausführen, müssen wir die Konfigurationsdatei vorbereiten. Folgendes haben wir für proxysql1 konfiguriert. Wir erstellen eine benutzerdefinierte Konfigurationsdatei unter /containers/proxysql1/proxysql.cnf auf host1:

$ cat /containers/proxysql1/proxysql.cnf
datadir="/var/lib/proxysql"
admin_variables=
{
        admin_credentials="admin:admin"
        mysql_ifaces="0.0.0.0:6032"
        refresh_interval=2000
}
mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
        interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.1.30"
        connect_timeout_server=10000
        monitor_history=60000
        monitor_connect_interval=200000
        monitor_ping_interval=200000
        ping_interval_server=10000
        ping_timeout_server=200
        commands_stats=true
        sessions_sort=true
        monitor_username="proxysql"
        monitor_password="proxysqlpassword"
}
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="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 }
)
mysql_users =
(
        { username = "sbtest" , password = "password" , default_hostgroup = 10 , active = 1 }
)
mysql_query_rules =
(
        {
                rule_id=100
                active=1
                match_pattern="^SELECT .* FOR UPDATE"
                destination_hostgroup=10
                apply=1
        },
        {
                rule_id=200
                active=1
                match_pattern="^SELECT .*"
                destination_hostgroup=20
                apply=1
        },
        {
                rule_id=300
                active=1
                match_pattern=".*"
                destination_hostgroup=10
                apply=1
        }
)
scheduler =
(
        {
                id = 1
                filename = "/usr/share/proxysql/tools/proxysql_galera_checker.sh"
                active = 1
                interval_ms = 2000
                arg1 = "10"
                arg2 = "20"
                arg3 = "1"
                arg4 = "1"
                arg5 = "/var/lib/proxysql/proxysql_galera_checker.log"
        }
)

Die obige Konfiguration wird:

  • Konfigurieren Sie zwei Hostgruppen, die Single-Writer- und die Multi-Writer-Gruppe, wie im Abschnitt "mysql_servers" definiert,
  • Lesevorgänge an alle Galera-Knoten (Hostgruppe 20) senden, während Schreibvorgänge an einen einzigen Galera-Server (Hostgruppe 10) gehen,
  • planen Sie die Datei proxysql_galera_checker.sh,
  • verwenden Sie monitor_username und monitor_password als Anmeldeinformationen für die Überwachung, die beim ersten Bootstrapping des Clusters erstellt wurden (mariadb0).

Kopieren Sie die Konfigurationsdatei für ProxySQL-Redundanz auf host2:

$ mkdir -p /containers/proxysql2/ # on host2
$ scp /containers/proxysql1/proxysql.cnf /container/proxysql2/ # on host1

Führen Sie dann die ProxySQL-Container auf Host1 bzw. Host2 aus:

$ docker run -d \
        --name=${NAME} \
        --publish 6033 \
        --publish 6032 \
        --restart always \
        --net=weave \
        $(weave dns-args) \
        --hostname ${NAME}.weave.local \
        -v /containers/${NAME}/proxysql.cnf:/etc/proxysql.cnf \
        -v /containers/${NAME}/data:/var/lib/proxysql \
        severalnines/proxysql

** Ersetzen Sie ${NAME} durch proxysql1 bzw. proxysql2.

Wir haben --restart=always angegeben um es unabhängig vom Exit-Status immer verfügbar zu machen, sowie automatischer Start, wenn der Docker-Daemon startet. Dadurch wird sichergestellt, dass sich die ProxySQL-Container wie ein Daemon verhalten.

Überprüfen Sie den Status des MySQL-Servers, der von beiden ProxySQL-Instanzen überwacht wird (OFFLINE_SOFT wird für die Single-Writer-Hostgruppe erwartet):

$ docker exec -it proxysql1 mysql -uadmin -padmin -h127.0.0.1 -P6032 -e 'select hostgroup_id,hostname,status from mysql_servers'
+--------------+----------------------+--------------+
| hostgroup_id | hostname             | status       |
+--------------+----------------------+--------------+
| 10           | mariadb1.weave.local | ONLINE       |
| 10           | mariadb2.weave.local | OFFLINE_SOFT |
| 10           | mariadb3.weave.local | OFFLINE_SOFT |
| 20           | mariadb1.weave.local | ONLINE       |
| 20           | mariadb2.weave.local | ONLINE       |
| 20           | mariadb3.weave.local | ONLINE       |
+--------------+----------------------+--------------+

An diesem Punkt sieht unsere Architektur in etwa so aus:

Alle Verbindungen, die von 6033 kommen (entweder von Host1, Host2 oder dem Netzwerk des Containers), werden mithilfe von ProxySQL auf die Backend-Datenbankcontainer verteilt. Wenn Sie auf einen einzelnen Datenbankserver zugreifen möchten, verwenden Sie stattdessen Port 3306 des physischen Hosts. Es gibt keine virtuelle IP-Adresse als einzelnen Endpunkt, der für den ProxySQL-Dienst konfiguriert ist, aber wir könnten dies durch die Verwendung von Keepalived erreichen, was im nächsten Abschnitt erklärt wird.

Virtuelle IP-Adresse mit Keepalived

Da wir ProxySQL-Container so konfiguriert haben, dass sie auf Host1 und Host2 ausgeführt werden, werden wir Keepalived-Container verwenden, um diese Hosts miteinander zu verbinden und virtuelle IP-Adressen über das Hostnetzwerk bereitzustellen. Dadurch kann sich ein einzelner Endpunkt für Anwendungen oder Clients mit der von ProxySQL unterstützten Lastausgleichsschicht verbinden.

Erstellen Sie wie gewohnt eine benutzerdefinierte Konfigurationsdatei für unseren Keepalived-Dienst. Hier ist der Inhalt von /containers/keepalived1/keepalived.conf:

vrrp_instance VI_DOCKER {
   interface ens33               # interface to monitor
   state MASTER
   virtual_router_id 52          # Assign one ID for this route
   priority 101
   unicast_src_ip 192.168.55.161
   unicast_peer {
      192.168.55.162
   }
   virtual_ipaddress {
      192.168.55.160             # the virtual IP
}

Kopieren Sie die Konfigurationsdatei für die zweite Instanz auf host2:

$ mkdir -p /containers/keepalived2/ # on host2
$ scp /containers/keepalived1/keepalived.conf /container/keepalived2/ # on host1

Ändern Sie die Priorität von 101 auf 100 in der kopierten Konfigurationsdatei auf host2:

$ sed -i 's/101/100/g' /containers/keepalived2/keepalived.conf

**Die Instanz mit der höheren Priorität behält die virtuelle IP-Adresse (in diesem Fall Host1), bis die VRRP-Kommunikation unterbrochen wird (falls Host1 ausfällt).

Führen Sie dann den folgenden Befehl auf host1 bzw. host2 aus:

$ docker run -d \
        --name=${NAME} \
        --cap-add=NET_ADMIN \
        --net=host \
        --restart=always \
        --volume /containers/${NAME}/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf \ osixia/keepalived:1.4.4

** Ersetzen Sie ${NAME} durch keepalived1 und keepalived2.

Der run-Befehl weist Docker an:

  • --name , erstellen Sie einen Container mit
  • --cap-add=NET_ADMIN , fügen Sie Linux-Funktionen für den Bereich der Netzwerkverwaltung hinzu
  • --net=host , hängen Sie den Container an das Hostnetzwerk an. Dadurch wird die virtuelle IP-Adresse auf der Hostschnittstelle bereitgestellt, ens33
  • --restart=immer , den Container immer am Laufen halten,
  • --volume=/containers/${NAME}/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf , ordnen Sie die benutzerdefinierte Konfigurationsdatei für die Verwendung des Containers zu.

Nachdem beide Container gestartet wurden, überprüfen Sie das Vorhandensein der virtuellen IP-Adresse, indem Sie sich die physische Netzwerkschnittstelle des MASTER-Knotens ansehen:

$ ip a | grep ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 192.168.55.161/24 brd 192.168.55.255 scope global ens33
    inet 192.168.55.160/32 scope global ens33

Die Clients und Anwendungen können nun die virtuelle IP-Adresse 192.168.55.160 verwenden, um auf den Datenbankdienst zuzugreifen. Diese virtuelle IP-Adresse existiert derzeit auf host1. Wenn Host1 ausfällt, übernimmt Keepalived2 die IP-Adresse und bringt sie auf Host2 hoch. Beachten Sie, dass die Konfiguration für dieses Keepalive die ProxySQL-Container nicht überwacht. Es überwacht nur die VRRP-Ankündigung der Keepalived-Peers.

An diesem Punkt sieht unsere Architektur in etwa so aus:

Zusammenfassung

Jetzt haben wir also einen MariaDB Galera-Cluster mit einem hochverfügbaren ProxySQL-Dienst, der alle auf Docker-Containern läuft.

In Teil zwei werden wir untersuchen, wie Sie dieses Setup verwalten können. Wir werden uns ansehen, wie Operationen wie ordnungsgemäßes Herunterfahren, Bootstrapping, Erkennen des fortschrittlichsten Knotens, Failover, Wiederherstellung, Hoch-/Herunterskalieren, Upgrades, Sicherung usw. durchgeführt werden. Wir werden auch die Vor- und Nachteile dieses Setups für unseren geclusterten Datenbankdienst erörtern.

Viel Spaß beim Containerisieren!