
## /etc/hosts ## IP Hostname Alias 127.0.0.1 localhost 10.0.2.10 lnv-10.intern datanode1 10.0.2.11 lnv-11.intern datanode2 10.0.2.20 lnv-20.intern management1 10.0.2.21 lnv-21.intern management2
Weitere Beiträge der Artikelserie „MySQL NDB Cluster“ findest du an dieser Stelle.
Wie einige von euch auf Twitter ja vielleicht schon am Rande mitbekommen haben beschäftige ich mich derzeit sehr intensiv mit MySQL-NDB-Cluster. Nachdem ich jetzt eine vergleichsweise lange Zeit mit der Theorie verbracht habe konnte ich inzwischen damit beginnen, ein wenig in die Praxis einzusteigen.
Das Produktivsystem werden zwei NDB-Cluster sein, die rechenzentrumsübergreifend eine Master-to-Master-Replikation fahren. Über virtuelle IPs wird die Verfügbarkeit realisiert — das System bleibt verfügbar, wenn einzelne Knoten ausfallen und sogar, wenn ein ganzer Standort ausfällt. Das greift in viele Bereiche ein und ist ein etwas umfangreicheres Projekt. Um ein Gefühl für die Sache zu bekommen, begann ich zu spielen: Cluster GREEN fand seinen Platz auf meinem MacPro, Cluster BLUE auf dem iMac und jeweils unter VirtualBox. DNS und DHCP laufen hier auf einem RaspberryPi.
Mein Beitrag erhebt keinen Anspruch auf Vollständigkeit, und insbesondere hafte ich nicht für eventuell entstehende Schäden; ich spiele meine Tutorials in aller Regel mehrfach durch, ehe ich sie veröffentliche, und das ist hier nun nicht anders — ich weise aber dennoch darauf hin, dass jeder für sich denken sollte, ehe ein Befehl in die Shell kopiert und ausgeführt wird — immer ;)
Und nun lasst uns beginnen…
Das System soll unter dem aktuellen Ubuntu Server LTS laufen; zum Zeitpunkt der Erstellung des Artikels ist das die 14.04.2. Meine Idee ist, mir eine Installation als Basis zu erstellen und diese dann zu klonen, so dass ich nicht n-mal langweilige Installationsarbeit leisten muss. Auf die Details gehe ich an dieser Stelle mal nicht ein — es ist eine Standard-Installation von Ubuntu in VirtualBox auf einem 8GB VDI mit LVM, ohne home encryption und mit SSH, Netzwerk über NAT, Audio deaktiviert, kein Floppy, kein CD-ROM. Die Hardware-„Ausstattung“ wird wie folgt sein (sollte sich jemand fragen, weshalb ich mit den 32GB RAM in meinem MacPro sehr glücklich bin: deshalb beispielsweise :D ):
Hernach erledigen wir alle Schritte, die sowohl auf den management als auch auf den data nodes anfallen: Ordner erstellen, Updates und Pakete installieren; später werden wir noch das Netzwerk umkonfigurieren, denn DHCP ist für unsere Zwecke nicht so günstig, aber für den Moment ist es ganz angenehm, wenn die Kisten Verbindung nach außen aufbauen können.
root@datanode1:~# apt-get update && apt-get upgrade root@datanode1:~# apt-get install htop libaio1 libaio-dev munin-node root@datanode1:~# mkdir /var/lib/mysql-cluster
Schon jetzt erstellen wir uns eine /etc/hosts, die für alle Hosts gelten wird:
## /etc/hosts ## IP Hostname Alias 127.0.0.1 localhost 10.0.2.10 lnv-10.intern datanode1 10.0.2.11 lnv-11.intern datanode2 10.0.2.20 lnv-20.intern management1 10.0.2.21 lnv-21.intern management2
Anschließend muss das MySQL-Cluster-Paket (zum Zeitpunkt der Erstellung dieses Artikels 7.4.6) heruntergeladen und ausgepackt werden; wir schieben es direkt nach /usr/local.
root@datanode1:~# cd /usr/local root@datanode1:/usr/local# wget https://dev.mysql.com/get/Downloads/MySQL-Cluster-7.4/mysql-cluster-gpl-7.4.6-linux-glibc2.5-x86_64.tar.gz root@datanode1:/usr/local# tar xvfz mysql-cluster-gpl-7.4.6-linux-glibc2.5-x86_64.tar.gz root@datanode1:/usr/local# rm mysql-cluster-gpl-7.4.6-linux-glibc2.5-x86_64.tar.gz
Jetzt kann die VM heruntergefahren und abgeschaltet werden: das Grundsystem ist fertig. Ich klone die Datenplatte — für das erste Management-System. Einfach nur kopieren ist nicht — beim Kopieren würde auch die UUID übernommen werden, so dass die neue Maschine nicht von der Platte würde booten können.
petzi:datanode1 spillerm$ VBoxManage clonevdi datanode1.vdi management1.vdi 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100% Clone hard disk created in format 'VDI'. UUID: cd612365-71ac-4cd1-8e1b-7b910a87e227
In VirtualBox wird jetzt eine neue Maschine angelegt (Einzelheiten siehe nebenstehenden Screenshot); dieser Maschine füttere ich das eben erstellte management1.vdi als Datenplatte ein und starte das System durch. Benötigt wird außerdem eine config.iniGITHUB, in der die grundlegende Konfiguration unseres Clusters vorgenommen wird; sie liegt in /var/lib/mysql-cluster. Wir richten uns entsprechend ein:
root@management1# cd /usr/local/ root@management1# cp mysql-cluster-gpl-7.4.6-linux-glibc2.5-x86_64/bin/ndb_mgm* /usr/bin root@management1# chmod 755 /usr/bin/ndb_mg* root@management1# mkdir -p /usr/local/mysql/mysql-cluster root@management1# rm -rf mysql-cluster-gpl-7.4.6-linux-glibc2.5-x86_64* root@management1# echo "ndb_mgmd -f /var/lib/mysql-cluster/config.ini --configdir=/var/lib/mysql-cluster/" > /etc/init.d/ndb_mgmd && chmod 755 /etc/init.d/ndb_mgmd root@management1# wget https://raw.githubusercontent.com/sysadmama/misc/master/mysql/config.ini -O /var/lib/mysql-cluster/config.ini
Abschließend muss in /etc/hostname noch der Hostname geändert werden (von datanode1 auf management1) und wir bearbeiten die /etc/network/interfaces, so dass die IP fortan nicht mehr per DHCP bezogen, sondern statisch vergeben wird; Gateway und DNS werden nicht benötigt:
## /etc/network/interfaces auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.0.2.20 netmask 255.255.255.0
Die Maschine management1 ist nun soweit vorbereitet — sie kann heruntergefahren, abgeschaltet und geklont werden.
petzi:datanode1 spillerm$ VBoxManage clonevdi management1.vdi management2.vdi 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100% Clone hard disk created in format 'VDI'. UUID: 2e91831c-238b-48be-b66a-338b482b02c3
Der Host management2 wird in VirtualBox analog zu management1 eingerichtet, die Datenplatte management2.vdi wird ihm untergeschoben und er wird hochgefahren. Hier muss nur in /etc/hostname der Hostname geändert werden (von management1 auf management2) und in /etc/network/interfaces die IP-Adresse (von 10.0.2.20 auf 10.0.2.21). Außerdem muss in /etc/mysql-proxy.conf die proxy-address angepasst werden!
Zur Sicherheit sollten nun beide management nodes einmal sauber durchgestartet werden — Netzwerk-Adapter 1 habe ich hierbei auf Internal network gesetzt, Netzwerk-Adapter 2 hingegen auf Bridged network — in meinem Fall über das WLAN-Interface des iMac. So bieten die management nodes „nach innen“ ein Interface mit einer Adresse aus dem 10.0.2.x-Netzwerk, „nach außen“ erhalten sie eine Adresse aus meinem regulären 192.168.2.x-Netzwerk, die über meinen DHCP fest vergeben wird. Zu beachten ist, dass hierfür auf beiden management nodes die /etc/network/interfaces um eth1 erweitert werden muss:
... auto eth1 iface eth1 inet dhcp
root@management1:~# /etc/init.d/ndb_mgmd start MySQL Cluster Management Server mysql-5.6.24 ndb-7.4.6
root@management1:~# ndb_mgm -- NDB Cluster -- Management Client -- ndb_mgm> show Connected to Management Server at: localhost:1186 ERROR Message: The cluster configuration is not yet confirmed by all defined management servers. This management server is still waiting for node 2 to connect.
Das ist doch mal eine klare Ansage. Nun denn: starten wir auf die gleiche Weise den Dienst auf management2!
root@management2:~# /etc/init.d/ndb_mgmd start MySQL Cluster Management Server mysql-5.6.24 ndb-7.4.6
root@management1:~# ndb_mgm -- NDB Cluster -- Management Client -- ndb_mgm> show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=3 (not connected, accepting connect from datanode1) id=4 (not connected, accepting connect from datanode2) [ndb_mgmd(MGM)] 2 node(s) id=1 @10.0.2.20 (mysql-5.6.24 ndb-7.4.6) id=2 @10.0.2.21 (mysql-5.6.24 ndb-7.4.6) [mysqld(API)] 2 node(s) id=5 (not connected, accepting connect from any host) id=6 (not connected, accepting connect from any host)
Wunderbar, beide management nodes sind up and running. Der Rest erwartungsgemäß nicht — die müssen wir ja nun aufziehen. Wir beenden die Arbeiten an den management nodes, indem wir abschließend noch auf beiden Nodes dafür sorgen, dass /etc/init.d/ndb_mgmd beim Booten ausgeführt wird.
root@management1:/usr/local# update-rc.d ndb_mgmd defaults update-rc.d: warning: /etc/init.d/ndb_mgmd missing LSB information update-rc.d: see <http://wiki.debian.org/LSBInitScripts> Adding system startup for /etc/init.d/ndb_mgmd ... /etc/rc0.d/K20ndb_mgmd -> ../init.d/ndb_mgmd /etc/rc1.d/K20ndb_mgmd -> ../init.d/ndb_mgmd /etc/rc6.d/K20ndb_mgmd -> ../init.d/ndb_mgmd /etc/rc2.d/S20ndb_mgmd -> ../init.d/ndb_mgmd /etc/rc3.d/S20ndb_mgmd -> ../init.d/ndb_mgmd /etc/rc4.d/S20ndb_mgmd -> ../init.d/ndb_mgmd /etc/rc5.d/S20ndb_mgmd -> ../init.d/ndb_mgmd
Hierzu starten wir unsere datanode1 wieder; das Netzwerk belassen wir noch auf NAT, damit wir bequemerweise die Konfigurationsdateien aus dem Netz ziehen können. Wir müssen Binaries an Ort und Stelle bewegen, Startscripte erstellen, alles einrichten. Die data nodes benötigen eine my.cnfGITHUB in /etc; sollte es bereits einen Ordner /etc/mysql geben, so ist man gut beraten, diesen umzubenennen, da er zu Konflikten führen kann. Und natürlich muss die bind-address gegebenenfalls angepasst werden!
root@datanode1:~# groupadd mysql root@datanode1:~# useradd -g mysql mysql root@datanode1:~# wget https://raw.githubusercontent.com/sysadmama/misc/master/mysql/my.cnf -O /etc/my.cnf root@datanode1:~# cd /usr/local root@datanode1:/usr/local# ln -s mysql-cluster-gpl-7.4.6-linux-glibc2.5-x86_64 mysql root@datanode1:/usr/local# cd mysql root@datanode1:/usr/local/mysql# mkdir /usr/share/mysql root@datanode1:/usr/local/mysql# cp share/english/errmsg.sys /usr/share/mysql/ root@datanode1:/usr/local/mysql# mv bin/* /usr/bin root@datanode1:/usr/local/mysql# rmdir bin/ root@datanode1:/usr/local/mysql# ln -s /usr/bin . root@datanode1:/usr/local/mysql# scripts/mysql_install_db --user=mysql --basedir=. Installing MySQL system tables... [...] root@datanode1:/usr/local/mysql# chown -R root:mysql . root@datanode1:/usr/local/mysql# chown -R mysql data/ root@datanode1:/usr/local/mysql# cp support-files/mysql.server /etc/init.d/ root@datanode1:/usr/local/mysql# chmod 755 /etc/init.d/mysql.server
An dieser Stelle würde ich empfehlen, die VM herunterzufahren, abzuschalten und wiederum zu klonen — zu datanode2. Wie gehabt: in VirtualBox eine neue VM datanode2 anlegen, datanode2.vdi als Datenplatte einfüttern, booten. Den Hostnamen anpassen, die IP — wie bei den management nodes fest vergeben. Ob ihr die Maschine dann rebootet oder von Hand umsetzt sei euch überlassen — jedenfalls können nun datanode1 und datanode2 gestartet werden, wiederum beide mit internem Netz statt NAT. Und nun wird es spannend: wir können initialisieren und dann unsere Dienste starten. Die Initialisierung muss nur dann gemacht werden, wenn
root@datanode1:~# cd /var/lib/mysql-cluster root@datanode1:/var/lib/mysql-cluster# ndbd --initial 2015-05-05 21:26:29 [ndbd] INFO -- Angel connected to '10.0.2.20:1186' 2015-05-05 21:26:29 [ndbd] INFO -- Angel allocated nodeid: 3
Dann mal spicken auf einem der management server (ja, es ist egal, welcher von beiden genutzt wird):
ndb_mgm> show Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=3 @10.0.2.10 (mysql-5.6.23 ndb-7.4.4, starting, Nodegroup: 0) id=4 (not connected, accepting connect from 10.0.2.11) [ndb_mgmd(MGM)] 2 node(s) id=1 @10.0.2.20 (mysql-5.6.23 ndb-7.4.4) id=2 @10.0.2.21 (mysql-5.6.23 ndb-7.4.4) [mysqld(API)] 2 node(s) id=5 (not connected, accepting connect from any host) id=6 (not connected, accepting connect from any host)
root@datanode2:/var/lib/mysql-cluster# ndbd --initial 2015-05-05 21:39:55 [ndbd] INFO -- Angel connected to '10.0.2.21:1186' 2015-05-05 21:39:55 [ndbd] INFO -- Angel allocated nodeid: 4
ndb_mgm> show Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=3 @10.0.2.10 (mysql-5.6.24 ndb-7.4.6, starting, Nodegroup: 0, *) id=4 @10.0.2.11 (mysql-5.6.24 ndb-7.4.6, starting, Nodegroup: 0) [ndb_mgmd(MGM)] 2 node(s) id=1 @10.0.2.20 (mysql-5.6.24 ndb-7.4.6) id=2 @10.0.2.21 (mysql-5.6.24 ndb-7.4.6) [mysqld(API)] 2 node(s) id=5 (not connected, accepting connect from any host) id=6 (not connected, accepting connect from any host)
$ /etc/init.d/mysql.server start .............................* root@datanode1:~# /usr/local/mysql/bin/mysql_secure_installation [...] Set root password? [Y/n] [...] Remove anonymous users? [Y/n] [...] Disallow root login remotely? [Y/n] [...] Remove test database and access to it? [Y/n] n [...] Reload privilege tables now? [Y/n] Y [...] Cleaning up...
MySQL-NDB-Cluster ist nun up & running.
ndb_mgm> show Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=3 @10.0.2.10 (mysql-5.6.24 ndb-7.4.6, Nodegroup: 0, *) id=4 @10.0.2.11 (mysql-5.6.24 ndb-7.4.6, Nodegroup: 0) [ndb_mgmd(MGM)] 2 node(s) id=1 @10.0.2.20 (mysql-5.6.24 ndb-7.4.6) id=2 @10.0.2.21 (mysql-5.6.24 ndb-7.4.6) [mysqld(API)] 2 node(s) id=5 @10.0.2.10 (mysql-5.6.24 ndb-7.4.6) id=6 @10.0.2.11 (mysql-5.6.24 ndb-7.4.6)
Großartig! Abschließend sorgen wir noch dafür, dass ndbd und mysql.server beim Booten automatisch gestartet werden — wiederum auf beiden data nodes. Hierzu habe ich den Aufruf /usr/bin/ndbd einfach in die /etc/rc.local geschrieben (vor das exit 0!) und mysql.server als Startscript hinzugefügt.
$ update-rc.d mysql.server defaults
Das ist die Basis: von hier aus gehen wir weiter. Die nächsten Schritte verpacke ich der Übersichtlichkeit halber in eigene Artikel, denn wie ihr seht: es entsteht ein ganz schöner Overhead. (Der nächste Schritt in meinem Cluster besteht in Distributed Privileges.) Mein MacPro langweilt sich vergleichsweise — mal sehen, ob das so bleibt… ;)
Fehler : Node 4: Forced node shutdown completed. Occured during startphase 0. Initiated by signal 9.
Lag in meinem Fall daran, dass meine data nodes gnadenlos zu wenig RAM hatten (zum Testen hatte ich es mit 512MB versucht, die Systeme belegen im Leerlauf aber schon 1GB); Ubuntu packte darauf hin sozusagen seine Prozess-Fliegenklatsche (OOM Killer) aus und erschlug wahllos Prozesse. Lässt sich beispielsweise per dmesg gut nachvollziehen.
Das passiert beispielsweise, wenn man die 32bit-Binaries auf ein 64bit-System packt und ndb_mgmd zu starten versucht: das Binary ist da, und dennoch behauptet das System No such file or directory. Mittels file /usr/bin/ndb_mgmd lässt sich der Fehler beispielsweise recht schnell eingrenzen… Kommt davon, wenn man beim Download pennt… ;)
Failed to allocate nodeid, error: 'Error: Could not alloc node id at management1 port 1186: No free node id found for ndbd(NDB).'
Diese Meldung erscheint zum Beispiel, wenn man auf einem der data nodes einen ndbd starten möchte, er jedoch schon läuft…