Jak zmusić nginx do rozpoznawania DNS (dynamicznej nazwy hosta) za każdym razem podczas wykonywania proxy_pass?

52

Używam nginx / 0.7.68, działający na CentOS, w następującej konfiguracji:

server {
    listen       80;
    server_name ***;
    index index.html index.htm index.php default.html default.htm default.php;

    location / {
            root   /***;
            proxy_pass   http://***:8888;
            index  index.html index.htm;
    }
    # where *** is my variables

Jest proxy_passto rekord DNS, którego adres IP często się zmienia. Nginx zapisuje w pamięci podręcznej nieaktualny adres IP, w wyniku czego żądanie jest wysyłane na niewłaściwy adres IP.

Jak mogę powstrzymać nginx przed buforowaniem adresu IP, gdy jest on nieaktualny?

Xiamx
źródło
przeglądając źródło nginx, wydaje się, że nginx jest zakodowany na stałe w pamięci podręcznej dla ich TTL - jaki jest TTL na dynamicznych dns?
lunixbochs
TTL na moich ddns to lata 60., domyślna wartość dyndns.com
xiamx
Zobacz także stackoverflow.com/questions/26956979/…
Cheekysoft,

Odpowiedzi:

8

To intrygujące pytanie i AFAIK, który nie zadziała dobrze. Możesz spróbować użyć modułu nadrzędnego i skorzystać z dyrektyw w celu przełączenia awaryjnego, aby sprawdzić, czy działa on jako hack.

Edycja 2018: wiele się zmieniło. Sprawdź odpowiedź @ohaal, aby uzyskać prawdziwe informacje na ten temat.

rdzeń rdzeniowy
źródło
1
zaskakująco, kiedy zmieniłem na upstream, wszystko działało zgodnie z oczekiwaniami.
Oznaczę
1
Zgodnie z dokumentacją istnieje specjalna serverflaga wysyłania, resolvektóra jest dostępna tylko w wersji komercyjnej (patrz nginx.org/en/docs/http/ngx_http_upstream_module.html#server )
omribahumi
1
@gansbrest ta strona wydaje się być rodzajem spamerskiej strony? poprosiłbym o usunięcie odpowiedzi.
majikman
90

Zaakceptowana odpowiedź nie działała dla mnie na nginx / 1.4.2.

Użycie zmiennej proxy_passwymusza ponowne rozpoznawanie nazw DNS, ponieważ NGINX traktuje zmienne inaczej niż konfiguracja statyczna. Z dokumentacji NGINXproxy_pass :

Wartość parametru może zawierać zmienne. W takim przypadku, jeśli adres jest określony jako nazwa domeny, nazwa jest przeszukiwana wśród opisanych grup serwerów, a jeśli nie zostanie znaleziona, jest określana za pomocą resolvera.

Na przykład:

server {
    ...
    resolver 127.0.0.1;
    set $backend "http://dynamic.example.com:80";
    proxy_pass $backend;
    ...
}

Uwaga: resolver (tzn. /etc/hostsUżywany serwer nazw) MUSI być dostępny i skonfigurowany, aby działał (a wpisy w pliku nie będą używane podczas wyszukiwania).

Domyślnie, wersja 1.1.9 lub nowsze wersje pamięci podręcznej NGINX odpowiadają przy użyciu wartości TTL odpowiedzi, a opcjonalny validparametr pozwala na przesłonięcie czasu pamięci podręcznej:

resolver 127.0.0.1 [::1]:5353 valid=30s;

Przed wersją 1.1.9 strojenie czasu buforowania nie było możliwe, a nginx zawsze buforował odpowiedzi przez 5 minut. .

ohaal
źródło
czy nie wymusiłoby to zapytania dns przy każdym pojedynczym żądaniu? to brzmi jak okropny występ ...
lucascaro,
Nie, przeczytaj źródło. In such setup ip address of "foo.example.com" will be looked up dynamically and result will be cached for 5 minutes.Dodałem go do odpowiedzi dla jasności.
ohaal
13
Po spędzeniu większości dnia na tym - na Ubuntu 12.04 z nginx 1.1.19, setwnętrze locationnie działa poprawnie. Uwaga
omribahumi,
To rozwiązanie działało ze mną, jednak nie mogłem znaleźć referencji na 5 minut TTL. nginx.org/en/docs/http/ngx_http_core_module.html#resolver By default, nginx caches answers using the TTL value of a response. An optional valid parameter allows overriding it: resolver 127.0.0.1 [::1]:5353 valid=30s;
Montaro
4
Uwaga: w przypadku dokera jego resolver DNS znajduje się na 127.0.0.11, więc do programowania używam tego:resolver 127.0.0.11 [::1]:5353 valid=15s;
Dalibor Filus
9

W komentarzu gansbrest i odpowiedzi na temat odpowiedzi znajduje się cenna informacja.

Ale myślę, że ważne jest, aby wspomnieć o tym oficjalnym artykule nginx, opublikowanym w 2016 roku, jasno wyjaśnia zachowanie nginx w tej sprawie i możliwe rozwiązania: https://www.nginx.com/blog/dns-service-discovery-nginx-plus /

Rzeczywiście musimy „ustawić nazwę domeny w zmiennej” i zastosować dyrektywę resolvera .

jednak użycie zmiennej zmienia zachowanie przepisywania. Może być konieczne użycie dyrektywy przepisywania, zależy to od lokalizacji i konfiguracji proxy_pass.

PS: dodałby komentarz, ale za mało punktów ...

Jack B.
źródło
1

Odpowiedź firmy ohaal zabiera większość z nas, ale zdarza się, że program rozpoznawania nazw DNS nie działa w wersji 127.0.0.1 (np. gdy znajdujesz się w specjalnym środowisku kontenerowym)

W takim przypadku możesz zmienić conf nginx na resolver ${DNS_SERVER};. Następnie, zanim uruchomisz nginx, uruchom

export DNS_SERVER=$(cat /etc/resolv.conf |grep -i '^nameserver'|head -n1|cut -d ' ' -f2)
envsubst '${DNS_SERVER} < your_nginx.conf.template > your_nginx.conf
wonton
źródło
0

Zhakowałem razem skrypt, aby oglądać folder conf.d w górę w poszukiwaniu zmian dns i przeładować nginx po wykryciu. Jest to pierwszy przebieg i na pewno można go ulepszyć (w następnym przejściu użyję nginx -T, aby parsować strumienie danych. Ten sam pomysł można zastosować w przypadku dyrektyw proxy_pass):

#!/bin/bash

get_upstreams() {
  local files=$@
  grep -hEo '(server\s+)[^:;]+' $files | cut -d' ' -f 2
}

resolve_hosts() {
  local hosts=$@
  for h in $hosts; do dig +short $h; done | sort -u
}

watch_dir=$1

[ -d $watch_dir ] || exit 2

upstreams=$(get_upstreams $watch_dir/*)
ips=$(resolve_hosts $upstreams)
if [ ! "$ips" ]; then
  echo "Found no resolvable hosts in $watch_dir files."
fi

host_hash=$(echo $ips | /usr/bin/sha512sum)

echo $host_hash
echo $ips

while [ -d $watch_dir ]; do
  sleep 30
  upstreams=$(get_upstreams $watch_dir/*)
  ips=$(resolve_hosts $upstreams)
  new_hash=$(echo $ips | /usr/bin/sha512sum)
  if [ "$host_hash" != "$new_hash" ]; then
    echo Detected an upstream address change.  $ips
    echo Reloading nginx
    echo $new_hash
    echo $ips
    /sbin/service nginx reload
    host_hash=$new_hash
  fi
done
mushuweasel
źródło