Hintergrund: Kubernetes, mehrere Ingresses, 3 Ingressknoten (ingress1-3.fun), ein Ingress/Service kann mit Prefixen nicht umgehen (absoluter Redirect) – daher verschiedene externe Namen und ein externer Load Balancer notwendig (webservice1+2.fun).

Superbillige Lösung:

  • 2 VMs (1 vCPU, 1 GB RAM, 10 GB Disk)
  • je eine für Zielclients erreichbare Adresse für webservice1+2.fun
  • HAProxy mit zwei frontends für webservice1+2.fun
  • keepalived mit VRRP Failover (die zwei öffentlichen Adressen)
  • Ingress Rules gehen auf die Namen, also http://webserviceX.fun/ => pod_für_webserviceX:port_für_webserviceX
/etc/haproxy/haproxy.cfg:

frontend webservice1
    bind webservice1.fun:80
    mode tcp
    default_backend backendnodes

frontend webservice2
    bind webservice2.fun:80
    mode tcp
    default_backend backendnodes

backend backendnodes
    balance source
    server node1 ingress1.fun:80 check
    server node2 ingress2.fun:80 check
    server node3 ingress3.fun:80 check

/etc/keepalived/keepalived.conf:

vrrp_instance VI_1 {
    state MASTER    # BACKUP am zweiten Knoten
    interface eth0
    virtual_router_id 51
    priority 255    # 254 am zweiten Knoten
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 12345
    }
    virtual_ipaddress {
        1.2.3.1/24          # öffentliche Adresse webservice1.fun
        1.2.3.2/24          # öffentliche Adresse webservice2.fun
    }

    notify_master "systemctl restart haproxy"
}

Durch das “notify_master” wird nach Failover der Adresse der HAProxy am jeweiligen Knoten neu gestartet und kann sich auf die virtuellen Adressen binden.

Mit “vrrp_track_process”/”track_process” oder “vrrp_script”/”track_script” könnte man noch Healthprobes (Existenz eines Prozesses – haproxy in diesem Fall oder ganzes Healthcheck Script) einführen – in der o.a. Konfiguration spricht keepalived nur an wenn VRRP Heartbeats vom MASTER nicht mehr ankommen.

Ingress spec (Controller=ingress-nginx):

spec:
  ingressClassName: nginx
  rules:
    - host: webservice1.fun
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: webservice1-server
                port:
                  number: 80

Das Ganze macht mit HTTPS dann naturgemäß 200x mal mehr Spaß 😀