Nginx DNS Service Discovery jetzt in der Open Source Version verfügbar

Beim Aufräumen meiner Tabs bin ich über eine Meldung aus dem November des letzten Jahres gestolpert: DNS Service Discovery ist jetzt auch in der Open Source Variante von Nginx verfügbar (bis dahin nur in NginxPlus).

Natürlich konnte man auch früher schon FQDNs (statt IP-Adressen) in der Nginx-Konfiguration verwenden - aber der dazu erforderliche DNS-Lookup fand genau einmal beim Start von Nginx statt - danach nicht mehr.

Mit DNS service discovery, löst Nginx bei jedem Request den FQDN auf und ermittelt so die aktiven IP-Adressen der Backends, an die die Requests weitergeleitet werden sollen.

Zusätzlich können auch DNS SRV Records ausgewertet werden, um so z. B. Priorität, Gewicht und Port des Backends zuzuweisen:

root@nginx-revp:~# dig +short nginx-revp1.service.consul srv
1 1 80 c0a800f6.addr.prod1patroni.consul.

Es ist also "nur noch" eine dynamische DNS Komponente erforderlich, um den Loadbalancer/Reverse-Proxy dynamisch mit Informationen über verfügbare Backends zu versorgen.

Eine solche DNS Komponente wäre z. B. ein Consul-Cluster, bei welchem sich Nginx-Backends automatisch registrieren. Eine andere Variante wäre z. B. Triton-CNS.

Für Consul reicht es, auf dem jeweiligen Backend einen Consul-Client zu konfigurieren, der z. B. durch Ansible oder Terraform beim erzeugen der Backend-Instanz mit der jeweiligen IP-Adresse des Backends versehen werden könnte:

service {
  id="nginx-revp1"
  name="nginx-revp1"
  tags=["nginx"]
  meta=[
    { configured="by terraform" }
  ]
  address="192.168.0.246"
  port=80

  checks = {
    id = "nginx-revp1"
    name = "nginx-revp1"
    http = "http://127.0.0.1/"
    interval = "15s" 
  }
}

Im Consul Catalog wird der Dienst dann gelistet:

root@nginx-revp:~# consul catalog services -tags
consul           
nginx-revp1      nginx
patroni42        master,primary,replica

Durch diese Registrierung und den zugehörigen Health-Check, wird Consul alle 15 Sekunden die Verfügbarkeit des Dienstes prüfen und ihn bei einem Fehler sofort aus dem Consul DNS austragen:

root@nginx-revp:~# dig +short nginx-revp1.service.consul
192.168.0.246
root@nginx-revp:~# dig +short nginx.nginx-revp1.service.consul
192.168.0.246
root@nginx-revp:~# dig +short nginx.nginx-revp1.service.prod1patroni.consul
192.168.0.246

Ich empfehle dafür lokal statt systemd-resolved ein dnsmasq zu konfigurieren. In der Consul-Dokumentation gibt es dafür einen Abschnitt. Der Vorteil von dnsmasq gegenüber systemd-resolved ist, dass damit nur DNS-Anfragen, die für die consul-Domain bestimmt sind, an den Consul-Cluster weitergeleitet werden.

# Enable forward lookup of the 'consul' domain:
server=/consul/127.0.0.1#8600

# User Google DNS for all other domains:
server=8.8.8.8

Auf diese Weise wird die Instanz nicht unbedienbar, wenn z. B. die Consul-Konfiguration angepasst und Consul neugestartet wird.

Das schöne an Nginx DNS Service Discovery ist, dass damit auch mehrere Reverse-Proxies nebeneinander (z. B. aus Gründen der Ausfallsicherheit) laufen können, ohne dass deren Konfiguration ständig synchronisiert werden müsste - sie aktualisiert sich ja dann selbstständig per DNS.

Bei meinen Tests war die Funktion in der aktuellen Stable-Version von Nginx (1.26.x) noch nicht eingebaut. Ich mußte den "Mainline"-Kernel (1.27.3) verwenden, um die Konfiguration durchführen zu können.