I den første del endte vi med en fungerende cmon HA-klynge:
[email protected]:~# s9s controller --list --long
S VERSION OWNER GROUP NAME IP PORT COMMENT
l 1.7.4.3565 system admins 10.0.0.101 10.0.0.101 9501 Acting as leader.
f 1.7.4.3565 system admins 10.0.0.102 10.0.0.102 9501 Accepting heartbeats.
f 1.7.4.3565 system admins 10.0.0.103 10.0.0.103 9501 Accepting heartbeats.
Total: 3 controller(s)
Vi har tre noder i gang, den ene fungerer som leder og de resterende er følgere, som er tilgængelige (de modtager hjerteslag og svarer på dem). Den resterende udfordring er at konfigurere brugergrænsefladeadgang på en måde, der giver os mulighed for altid at få adgang til brugergrænsefladen på ledernoden. I dette blogindlæg vil vi præsentere en af de mulige løsninger, som vil give dig mulighed for at opnå netop det.
Opsætning af HAProxy
Dette problem er ikke nyt for os. Med hver replikeringsklynge, MySQL eller PostgreSQL er det ligegyldigt, der er en enkelt node, hvor vi skal sende vores skrivninger til. En måde at opnå det på ville være at bruge HAProxy og tilføje nogle eksterne kontroller, der tester nodens tilstand, og baseret på det returnerer korrekte værdier. Det er dybest set, hvad vi skal bruge til at løse vores problem. Vi vil bruge HAProxy som en gennemtestet lag 4 proxy, og vi vil kombinere den med lag 7 HTTP checks, som vi vil skrive netop til vores use case. Først og fremmest, lad os installere HAProxy. Vi samler det sammen med ClusterControl, men det kan lige så godt installeres på en separat node (ideelt set noder - for at fjerne HAProxy som det enkelte fejlpunkt).
apt install haproxy
Dette sætter HAProxy op. Når det er gjort, skal vi introducere vores konfiguration:
global
pidfile /var/run/haproxy.pid
daemon
user haproxy
group haproxy
stats socket /var/run/haproxy.socket user haproxy group haproxy mode 600 level admin
node haproxy_10.0.0.101
description haproxy server
#* Performance Tuning
maxconn 8192
spread-checks 3
quiet
defaults
#log global
mode tcp
option dontlognull
option tcp-smart-accept
option tcp-smart-connect
#option dontlog-normal
retries 3
option redispatch
maxconn 8192
timeout check 10s
timeout queue 3500ms
timeout connect 3500ms
timeout client 10800s
timeout server 10800s
userlist STATSUSERS
group admin users admin
user admin insecure-password admin
user stats insecure-password admin
listen admin_page
bind *:9600
mode http
stats enable
stats refresh 60s
stats uri /
acl AuthOkay_ReadOnly http_auth(STATSUSERS)
acl AuthOkay_Admin http_auth_group(STATSUSERS) admin
stats http-request auth realm admin_page unless AuthOkay_ReadOnly
#stats admin if AuthOkay_Admin
listen haproxy_10.0.0.101_81
bind *:81
mode tcp
tcp-check connect port 80
timeout client 10800s
timeout server 10800s
balance leastconn
option httpchk
# option allbackups
default-server port 9201 inter 20s downinter 30s rise 2 fall 2 slowstart 60s maxconn 64 maxqueue 128 weight 100
server 10.0.0.101 10.0.0.101:443 check
server 10.0.0.102 10.0.0.102:443 check
server 10.0.0.103 10.0.0.103:443 check
Du ønsker måske at ændre nogle af tingene her, f.eks. noden eller backend-navnene, som her inkluderer vores nodes IP. Du vil helt sikkert skifte servere, som du vil have inkluderet i din HAProxy.
De vigtigste bits er:
bind *:81
HAProxy vil lytte på port 81.
option httpchk
Vi har aktiveret tjek af lag 7 på backend-noderne.
default-server port 9201 inter 20s downinter 30s rise 2 fall 2 slowstart 60s maxconn 64 maxqueue 128 weight 100
Lag 7-kontrollen vil blive udført på port 9201.
Når dette er gjort, start HAProxy.
Opsætning af xinetd og Check Script
Vi vil bruge xinetd til at udføre kontrollen og returnere korrekte svar til HAProxy. Trin beskrevet i dette afsnit skal udføres på alle cmon HA-klyndeknuder.
Installer først xinetd:
[email protected]:~# apt install xinetd
Når dette er gjort, skal vi tilføje følgende linje:
cmonhachk 9201/tcp
til /etc/services - dette vil tillade xinetd at åbne en tjeneste, der lytter på port 9201. Så skal vi tilføje selve tjenestefilen. Det skal være placeret i /etc/xinetd.d/cmonhachk:
# default: on
# description: cmonhachk
service cmonhachk
{
flags = REUSE
socket_type = stream
port = 9201
wait = no
user = root
server = /usr/local/sbin/cmonhachk.py
log_on_failure += USERID
disable = no
#only_from = 0.0.0.0/0
only_from = 0.0.0.0/0
per_source = UNLIMITED
}
Til sidst har vi brug for kontrolscriptet, der kaldes af xinetd. Som defineret i servicefilen er den placeret i /usr/local/sbin/cmonhachk.py.
#!/usr/bin/python3.5
import subprocess
import re
import sys
from pathlib import Path
import os
def ret_leader():
leader_str = """HTTP/1.1 200 OK\r\n
Content-Type: text/html\r\n
Content-Length: 48\r\n
\r\n
<html><body>This node is a leader.</body></html>\r\n
\r\n"""
print(leader_str)
def ret_follower():
follower_str = """
HTTP/1.1 503 Service Unavailable\r\n
Content-Type: text/html\r\n
Content-Length: 50\r\n
\r\n
<html><body>This node is a follower.</body></html>\r\n
\r\n"""
print(follower_str)
def ret_unknown():
unknown_str = """
HTTP/1.1 503 Service Unavailable\r\n
Content-Type: text/html\r\n
Content-Length: 59\r\n
\r\n
<html><body>This node is in an unknown state.</body></html>\r\n
\r\n"""
print(unknown_str)
lockfile = "/tmp/cmonhachk_lockfile"
if os.path.exists(lockfile):
print("Lock file {} exists, exiting...".format(lockfile))
sys.exit(1)
Path(lockfile).touch()
try:
with open("/etc/default/cmon", 'r') as f:
lines = f.readlines()
pattern1 = "RPC_BIND_ADDRESSES"
pattern2 = "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
m1 = re.compile(pattern1)
m2 = re.compile(pattern2)
for line in lines:
res1 = m1.match(line)
if res1 is not None:
res2 = m2.findall(line)
i = 0
for r in res2:
if r != "127.0.0.1" and i == 0:
i += 1
hostname = r
command = "s9s controller --list --long | grep {}".format(hostname)
output = subprocess.check_output(command.split())
state = output.splitlines()[1].decode('UTF-8')[0]
if state == "l":
ret_leader()
if state == "f":
ret_follower()
else:
ret_unknown()
finally:
os.remove(lockfile)
Når du har oprettet filen, skal du sørge for, at den er eksekverbar:
chmod u+x /usr/local/sbin/cmonhachk.py
Idéen bag dette script er, at det tester nodernes status ved hjælp af kommandoen "s9s controller --list --long" og derefter tjekker det output, der er relevant for IP'en, som det kan finde på lokal node. Dette gør det muligt for scriptet at afgøre, om værten, som den udføres på, er en leder eller ej. Hvis noden er lederen, returnerer scriptet "HTTP/1.1 200 OK" kode, som HAProxy fortolker som noden er tilgængelig og dirigerer trafikken til den. Ellers returnerer det "HTTP/1.1 503 Service Unavailable", hvilket behandles som en knude, som ikke er sund, og trafikken vil ikke blive dirigeret dertil. Som et resultat, uanset hvilken node der bliver leder, vil HAProxy registrere den og markere den som tilgængelig i backend:
Du skal muligvis genstarte HAProxy og xinetd for at anvende konfigurationsændringer før alle dele vil begynde at fungere korrekt.
At have mere end én HAProxy sikrer, at vi har en måde at få adgang til ClusterControl UI, selvom en af HAProxy-noder ville fejle, men vi har stadig to (eller flere) forskellige værtsnavne eller IP til at forbinde til ClusterControl UI. For at gøre det mere behageligt vil vi implementere Keepalive oven på HAProxy. Det vil overvåge tilstanden af HAProxy-tjenester og tildele Virtual IP til en af dem. Hvis den HAProxy bliver utilgængelig, vil VIP blive flyttet til en anden tilgængelig HAProxy. Som et resultat har vi et enkelt indgangssted (VIP eller et værtsnavn knyttet til det). De trin, vi tager her, skal udføres på alle de noder, hvor HAProxy er blevet installeret.
Først, lad os installere Keepalived:
apt install keepalived
Så skal vi konfigurere det. Vi bruger følgende konfigurationsfil:
vrrp_script chk_haproxy {
script "killall -0 haproxy" # verify the pid existance
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_HAPROXY {
interface eth1 # interface to monitor
state MASTER
virtual_router_id 51 # Assign one ID for this route
priority 102
unicast_src_ip 10.0.0.101
unicast_peer {
10.0.0.102
10.0.0.103
}
virtual_ipaddress {
10.0.0.130 # the virtual IP
}
track_script {
chk_haproxy
}
# notify /usr/local/bin/notify_keepalived.sh
}
Du bør ændre denne fil på forskellige noder. IP-adresser skal konfigureres korrekt, og prioritet bør være forskellig på alle noderne. Konfigurer venligst også VIP, der giver mening i dit netværk. Du vil måske også ændre grænsefladen - vi brugte eth1, som er hvor IP'en tildeles på virtuelle maskiner oprettet af Vagrant.
Start keepalived med denne konfigurationsfil, og du burde være godt i gang. Så længe VIP er oppe på én HAProxy-node, bør du være i stand til at bruge den til at oprette forbindelse til den korrekte ClusterControl UI:
Dette fuldender vores todelte introduktion til ClusterControl højt tilgængelige klynger. Som vi sagde i begyndelsen, er dette stadig i beta-tilstand, men vi ser frem til feedback fra dine tests.