mysql-proxy und DNS-Round-Robin

Diesen Beitrag schrieb ich 7 Jahre und 6 Tage zuvor; die nachfolgenden Ausführungen müssen heute nicht unbedingt noch genau so funktionieren. Behalte das beim Lesen (und vor allem: beim Nachmachen!) bitte stets im Hinterkopf.

Geschätzte Lesezeit: 2 Minuten

Weitere Beiträge der Artikelserie „MySQL NDB Cluster“ findest du an dieser Stelle.

Eine einfache Lastverteilung auf meinem MySQL-NDB-Cluster möchte ich mittels mysql-proxy umsetzen; ein schmales Paket, das jedoch genau das tut, was ich haben möchte. Ich installiere es auf beiden Management Nodes. Darüber hinaus benötigen wir für die Konfiguration des Dienstes eine mysql-proxy.conf, die wir nach /etc schieben und chmod 0600 setzen (!), sowie eine mysql-proxy, die ihren Platz in /etc/default findet.

$ apt-get install mysql-proxy
$ wget https://raw.githubusercontent.com/netzwerkgoettin/misc/master/mysql/mysql-proxy -O /etc/default/mysql-proxy
$ wget https://raw.githubusercontent.com/netzwerkgoettin/misc/master/mysql/mysql-proxy.conf -O /etc/mysql-proxy.conf
$ chmod 0600 /etc/mysql-proxy.conf

Im ersten Artikel zu dem Thema hatte ich bereits einen Grundstein für dieses Setup gelegt: auf allen Data Nodes wurde dem mysql.server jeweils seine bind-address in der /etc/my.cnf mitgegeben, so dass der Dienst auf Port 3306 der bind-address zu erreichen ist. Auf dieses Feature ist mysql-proxy angewiesen: er läuft auf den Management Nodes seinerseits auf Port 3306 (proxy-address in /etc/mysql-proxy.conf) und stellt bei Anfragen die Verbindung zu den Data Nodes her; diese proxy-address muss natürlich die von außen erreichbare sein, denn auf sie sollen sich unsere Clients ja späterhin verbinden können:

  • management1: proxy-address = 192.168.2.13:3306
  • management2: proxy-address = 192.168.2.14:3306

Und nun kann – wiederum auf beiden Management Nodes – der Dienst gestartet werden. Ein schüchterner Blick ins Logfile verrät uns bestenfalls, dass alles läuft :

root@management1:~# /etc/init.d/mysql-proxy start
[...]
2015-05-07 13:58:35: (message) mysql-proxy 0.8.1 started
2015-05-07 13:58:35: (debug) max open file-descriptors = 1024
2015-05-07 13:58:35: (message) proxy listening on port 192.168.2.13:3306
2015-05-07 13:58:35: (message) added read/write backend: 10.0.2.10:3306
2015-05-07 13:58:35: (message) added read/write backend: 10.0.2.11:3306

Yes! Das ist genau das, was wir haben wollten – beide Data Nodes sind als Backend registriert, und die anfallende Last wird gleichmäßig zwischen beiden verteilt – und das von beiden Management Nodes aus. Konfigurieren wir nun unsere Anwendungen, können wir beispielsweise green1.intern als DB-Host angeben, das würde management1 entsprechen; charmanter wäre es allerdings, ganz global ein mysql.intern zu definieren und darunter alle Management Nodes zusammenzufassen.

Diese Lösung hat ihre Schwächen, das ist klar; beim sogenannten DNS Round Robin werden nacheinander alle A-Records für einen Eintrag abgeklappert – unabhängig davon, ob die nun gerade erreichbar sind oder nicht, die Namensauflösung wird zuerst gemacht. Antwortet der Host dann nicht, läuft der Request ins Leere. Unschön, aber irgendwann muss man auf der Spielwiese ja auch mal eine Grenze ziehen (Download der graphischen Darstellung als PDF) :D Für ein Produktivsystem würde ich eine andere Lösung erarbeiten. In meinem bind habe ich mir fürs erste einfach die entsprechenden A-Records gesetzt:

;; mysql cluster
mysql         IN  A     192.168.2.13
              IN  A     192.168.2.14

Sobald auf beiden Management Nodes der Dienst mysql-proxy gestartet ist, können fröhliche ping-Versuche auf mysql.intern gestartet werden… Bei mir funktionierte es auf Anhieb, mal antwortete ein Host, mal der andere. Versuchen wir nun, uns auf Port 3306 zu verbinden:

root@pelle:/etc/bind# telnet mysql.intern 3306
Trying 192.168.2.13...
Connected to mysql.intern.
Escape character is '^]'.
DHost 'management1' is not allowed to connect to this MySQL serverConnection closed by foreign host.

Sauber! Unser Cluster antwortet – es lehnt die Verbindung zwar ab, aber er antwortet :D Was wir nun tun müssen ist, einen entsprechenden Proxy-User anzulegen, dem es erlaubt ist, sich zu verbinden. Machen wir das mal so:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.6.24-ndb-7.4.6-cluster-gpl MySQL Cluster Community Server (GPL)
...
mysql> CREATE USER 'proxy'@'10.0.2.%'
    -> IDENTIFIED BY 'nLj8eShazP6I';
Query OK, 0 rows affected (0.01 sec)
 
mysql> FLUSH PRIVILEGES
Query OK, 0 rows affected (0.00 sec)

Hierbei ist zu beachten, dass der User auf allen angeschlossenen data nodes verfügbar sein muss; entweder muss er also überall manuell angelegt werden, oder aber wir haben für eine Verteilung der Daten gesorgt. Und wie gestaltet sich ein neuerlicher Verbindungsversuch?

root@pelle:/etc/bind# telnet mysql 3306
Trying 192.168.2.14...
Connected to mysql.intern.
Escape character is '^]'.
J
5.6.24-ndb-7.4.6-cluster-gplNP&mu#L4?`e\{xgzPb{c_

Das ist der Punkt, an dem ich management1 noch ein munin und allen anderen ein munin-node verpasse, um das Verhalten der Kisten beobachten zu können, denn dann wird es spannend: es können testweise die ersten Datenbanken in das System hineingefüttert werden