Come forzare nginx a risolvere DNS (di un nome host dinamico) ogni volta che si esegue proxy_pass?


52

Sto usando nginx / 0.7.68, in esecuzione su CentOS, con la seguente configurazione:

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

È proxy_passun record DNS il cui IP cambia frequentemente. Nginx memorizza nella cache l'indirizzo IP obsoleto, generando una richiesta all'indirizzo IP errato.

Come posso impedire a nginx di memorizzare nella cache l'indirizzo IP, quando è obsoleto?


guardando attraverso la sorgente di nginx, sembra che nginx sia hardcoded per memorizzare nella cache il loro TTL - qual è il TTL sul tuo dns dinamico?
lunixboch,

TTL sul mio ddns è 60s, il valore predefinito di dyndns.com
xiamx,


Risposte:


8

È una domanda intrigante e AFAIK che non funzionerà bene. Puoi provare a utilizzare il modulo upstream e utilizzare le direttive per il failover per vedere se funziona come un hack.

Modifica del 2018: molte cose sono cambiate. Controlla la risposta di @ohaal per ottenere informazioni reali su questo.


1
sorprendentemente quando sono passato a monte, tutto ha funzionato come previsto.
Segnerò

1
Secondo la documentazione, c'è un serverflag upstream speciale resolvedisponibile solo nella versione commerciale (vedi nginx.org/en/docs/http/ngx_http_upstream_module.html#server )
omribahumi

1
@gansbrest quel sito sembra essere una specie di sito di spam? ti chiederei di rimuovere la tua risposta.
Majikman,

90

La risposta accettata non ha funzionato per me su nginx / 1.4.2.

L'uso di una variabileproxy_pass per forzare la nuova risoluzione dei nomi DNS perché NGINX tratta le variabili in modo diverso alla configurazione statica. Dalla documentazione NGINXproxy_pass :

Il valore del parametro può contenere variabili. In questo caso, se un indirizzo viene specificato come nome di dominio, il nome viene cercato tra i gruppi di server descritti e, se non trovato, viene determinato utilizzando un resolver.

Per esempio:

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

Nota: un resolver (ovvero il server dei nomi da utilizzare) DEVE essere disponibile e configurato per funzionare (e le voci all'interno di un /etc/hostsfile non verranno utilizzate in una ricerca).

Per impostazione predefinita, la versione 1.1.9 o successive della cache NGINX risponde utilizzando il valore TTL di una risposta e un validparametro facoltativo consente di sovrascrivere il tempo della cache:

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

Prima della versione 1.1.9, l'ottimizzazione del tempo di memorizzazione nella cache non era possibile e nginx memorizzava sempre nella cache le risposte per la durata di 5 minuti. .


questo non imporrebbe una query DNS su ogni singola richiesta? sembra una performance terribile ...
Lucascaro

No, leggi la fonte. In such setup ip address of "foo.example.com" will be looked up dynamically and result will be cached for 5 minutes.L'ho aggiunto alla risposta per chiarezza.
ohaal,

13
Dopo aver trascorso gran parte della mia giornata su questo - su Ubuntu 12.04 con nginx 1.1.19, setdentro locationnon funziona correttamente. Attenzione
omribahumi,

Questa soluzione ha funzionato con me, tuttavia non sono riuscito a trovare un riferimento per il 5 minuti TTL. nginx.org/it/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
Nota: per docker, il suo resolver DNS risiede al 127.0.0.11, quindi per lo sviluppo, io uso questo:resolver 127.0.0.11 [::1]:5353 valid=15s;
Dalibor Filus

9

Ci sono informazioni preziose nel commento gansbrest e nella risposta ohaal.

Ma penso che sia importante menzionare questo articolo ufficiale di nginx, pubblicato nel 2016, che spiega chiaramente il comportamento di nginx su questo argomento e le possibili soluzioni: https://www.nginx.com/blog/dns-service-discovery-nginx-plus /

Dobbiamo davvero "Impostare il nome di dominio in una variabile" e utilizzare la direttiva del resolver .

tuttavia, l'utilizzo di una variabile modifica il comportamento di riscrittura. Potrebbe essere necessario utilizzare la direttiva di riscrittura, dipende dalla posizione e dall'impostazione proxy_pass.

PS: avrebbe pubblicato un commento ma non abbastanza punti ancora ...


1

La risposta di ohaal ci porta la maggior parte di noi lì, ma c'è un caso in cui il resolver DNS non vive a 127.0.0.1 (ad esempio quando ci si trova in un ambiente containerizzato speciale)

In tal caso, potresti voler modificare la configurazione di nginx resolver ${DNS_SERVER};. Quindi, prima di avviare nginx, esegui

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

0

Ho hackerato insieme uno script per guardare una cartella conf.d upstream per le modifiche DNS e ricaricare nginx al momento del rilevamento. È un primo passaggio e sicuramente può essere migliorato (passaggio successivo, userò nginx -T per analizzare in particolare i flussi up. La stessa idea potrebbe essere usata per le direttive 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.