Image by Riedelmeier @ https://pixabay.com

Externe Openshift Loadbalancers met HAProxy

Één van de dingen waar je tegenaan loopt als je een OpenShift cluster wilt uitrollen op je eiegen infrastructuur, en dus niet in de publieke cloud, is het opzetten van een goede externe loadbalancer voor de verschillende diensten op het cluster. Het is mogelijk om een self-hosted load-balancer met keepalived en haproxy te draaien op je cluster zelf, maar dit wordt door Red Hat alleen maar officieel ondersteund op UPI VMWare installaties.

In dit artikel leggen we uit wat je moet configureren aan de hand van een voorbeeld haproxy.cfg.

Onderdelen

Er zijn twee verschillende load-balancers nodig, maar deze kun je op dezelfde HAProxy instantie draaien (mits je DNS goed staat):

  1. Een load-balancer voor de api.<cluster>.<domain> en api-int.<cluster>.<domain> domeinen.

    Deze load-balancer doet poort 6443/tcp voor de Kubernetes API en poort 22623/tcp voor de MachineConfig service op het cluster.

  2. Een load-balancer voor het domein *.apps.<cluster>.<domain>.

    Deze load-balancer moet de poorten 80/tcp en 443/tcp doorzetten naar de nodes waar de OpenShift Ingress Routers op draaien.

In principe kunnen DNS alle drie van deze domeinen naar hetzelfde IP adres wijzen, aangezien er geen poort conflicten zijn.

Vereisten

Een goede externe load-balancer voor OpenShift moet aan een aantal vereisten voldoen:

  • Layer 4 / TCP modus, dus geen HTTP(S) interceptie
  • Snelle en juiste healthchecks, kapotte nodes/diensten moeten snel achter de load-balancer vandaan verwijderd worden.

Health Checks

De volgende health-checks zijn beschikbaar op de OpenShift onderdelen:

Component Poort Pad Protocol
API 6443/tcp /readyz HTTPS
MachineConfig 22623/tcp /healthz HTTPS
Ingress 1936/tcp /healthz HTTPS

N.B. De health-checks voor de Ingress Router zitten op een andere poort (1936/tcp) dan de poorten waar de echte service op zit. Dit is de HAProxy status poort.

Check Interval

Het default check interval van HAProxy is twee seconden. Dit is een goed interval om de Kubernetes API beschikbaar te houden in het geval van een probleem op een node, of om de Ingress Router bereikbaar te houden. Het interval kan lager gezet worden, maar veel hoger is niet aan te raden.

Voorbeeld Configuratie

De volgende voorbeeld haproxy.cfg gaat uit van een cluster met negen vaste nodes (master01..master03, infra01..infra03, en worker01..worker03), en één bootstrap node. Tijdens de initiële isntallatie moeten de regels voor de bootstrap node nog in de config staan. Na afloop van de installatie kunnen deze verwijderd worden.

 1global
 2  log 127.0.0.1 local0 debug
 3  stats socket /var/lib/haproxy/stats mode 660 level admin expose-fd listeners
 4  stats timeout 30s
 5defaults
 6  timeout connect 2s
 7  timeout client 36000s
 8  timeout server 36000s
 9  timeout client-fin 1s
10  timeout server-fin 1s
11  mode tcp
12  maxconn 3000
13  log global
14  balance source
15
16frontend openshift-api-server
17  bind *:6443
18  default_backend openshift-api-server
19  mode tcp
20  option tcplog
21
22backend openshift-api-server
23  balance source
24  mode tcp
25  option httpchk GET /readyz HTTP/1.0
26  server bootstrap.example.com 10.1.0.29:6443 check check-ssl verify none
27  server master01.example.com 10.1.0.20:6443 check check-ssl verify none
28  server master02.example.com 10.1.0.21:6443 check check-ssl verify none
29  server master03.example.com 10.1.0.22:6443 check check-ssl verify none
30
31frontend machine-config-server
32  bind *:22623
33  default_backend machine-config-server
34  mode tcp
35  option tcplog
36
37backend machine-config-server
38  balance source
39  mode tcp
40  option httpchk GET /healthz HTTP/1.0
41  server bootstrap.example.com 10.1.0.29:22623 check check-ssl verify none
42  server master01.example.com 10.1.0.20:22623 check check-ssl verify none
43  server master02.example.com 10.1.0.21:22623 check check-ssl verify none
44  server master03.example.com 10.1.0.22:22623 check check-ssl verify none
45
46frontend ingress-http
47  bind *:80
48  default_backend ingress-http
49  mode tcp
50  option tcplog
51
52backend ingress-http
53  balance source
54  mode tcp
55  option httpchk GET /healthz HTTP/1.0
56  server infra01.example.com 10.1.0.23:80 check port 1936 check-ssl verify none
57  server infra02.example.com 10.1.0.24:80 check port 1936 check-ssl verify none
58  server infra03.example.com 10.1.0.25:80 check port 1936 check-ssl verify none
59  server worker01.example.com 10.1.0.26:80 check port 1936 check-ssl verify none
60  server worker02.example.com 10.1.0.27:80 check port 1936 check-ssl verify none
61  server worker03.example.com 10.1.0.28:80 check port 1936 check-ssl verify none
62
63
64frontend ingress-https
65  bind *:443
66  default_backend ingress-https
67  mode tcp
68  option tcplog
69
70backend ingress-https
71  balance source
72  mode tcp
73  option httpchk GET /healthz HTTP/1.0
74  server infra01.example.com 10.1.0.23:443 check port 1936 check-ssl verify none
75  server infra02.example.com 10.1.0.24:443 check port 1936 check-ssl verify none
76  server infra03.example.com 10.1.0.25:443 check port 1936 check-ssl verify none
77  server worker01.example.com 10.1.0.26:443 check port 1936 check-ssl verify none
78  server worker02.example.com 10.1.0.27:443 check port 1936 check-ssl verify none
79  server worker03.example.com 10.1.0.28:443 check port 1936 check-ssl verify none

Highlights

De belangrijklste punten uit deze config:

  • Op regels 11, 19, 24, 34, 39, 49, 54, 67, en 72 hebben we mode tcp, om de loadbalancer in layer 4 modus te zetten (en dus niet layer 7 HTTP modus)
  • Op regels 25, 40, 55, en 73 definiëren we de healthcheck als een HTTP/1.0 GET op de benodigde URLs.
  • Op elke server regel geven we met check aan dat de geconfigureerde healthcheck moet worden uitgevoerd voor deze server.
  • Op elke server regel geeft check-ssl aan dat de check over een beveiligde verbinding moet worden uitgevoerd, terwijl verify none aangeeft dat de certificaten niet hoeven te worden gecontroleerd.
  • Onder de backend ingress-http* blokken hebben we ook de worker nodes staan, terwijl een Ingress router meestal geconfigureerd wordt om alleen maar op de infra nodes te mogen draaien. Dit is expres gedaan omdat vanf de initiële installatie totdat de Ingress Router geconfigureerd wordt er een kans is dat er alleen maar op worker nodes een Ingress ROuter pod aanwezig is. Omdat de loadbalancer in dat geval zonder de worker nodes in het backend geen actieve endpoints kan vinden gaat de loadbalancer dicht, en zullen de automatische “canary” checks van bijvoorbeeld de Ingress Operator en de OpenShift Console Operator falen.

Extras

In de backend blokken kun je per server (of als default-server optie) nog de volgende opties meenemen:

default-server inter 1s fall 2 rise 3

Hiermee geven we de volgende extra opties aan:

Optie Uitleg Default
inter 1s Healthchecks elke seconde uitvoeren 2s
fall 2 Na twee gefaalde healthchecks een server uit de backend verwijderen. 3
rise 3 Pas na 3 succesvolle healthchecks de server weer in het backend stoppen. 2

Ook kan de de default-server optie gebruikt worden per backend blok om de de opties die per server gedupliceerd staan maar één keer te hoeven specificeren.

Gerelateerde posts