web-dev-qa-db-fra.com

Comment forcer nginx à résoudre DNS (d'un nom d'hôte dynamique) à chaque fois que vous faites proxy_pass?

J'utilise nginx/0.7.68, fonctionnant sur CentOS, avec la configuration suivante:

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

Le proxy_pass correspond à un enregistrement DNS dont l'IP change fréquemment. Nginx met en cache l'adresse IP obsolète, entraînant une demande à la mauvaise adresse IP.

Comment puis-je empêcher nginx de mettre en cache l'adresse IP lorsqu'elle est obsolète?

58
xiamx

C'est une question intrigante et l'AFAIK ne va pas bien fonctionner. Vous pouvez essayer d'utiliser le module en amont et utiliser les directives de basculement pour voir s'il fonctionne comme un hack.

Édition 2018: beaucoup de choses ont changé. Vérifiez le réponse de @ohaal pour obtenir de vraies informations à ce sujet.

9
coredump

La réponse acceptée n'a pas fonctionné pour moi sur nginx/1.4.2.

tilisation d'une variable dans proxy_pass force la re-résolution des noms DNS car NGINX traite les variables différemment de la configuration statique. Depuis le NGINX proxy_pass documentation :

La valeur du paramètre peut contenir des variables. Dans ce cas, si une adresse est spécifiée en tant que nom de domaine, le nom est recherché parmi les groupes de serveurs décrits et, s'il n'est pas trouvé, est déterminé à l'aide d'un résolveur.

Par exemple:

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

Remarque: Un résolveur (c'est-à-dire le serveur de noms à utiliser) DOIT être disponible et configuré pour que cela fonctionne (et les entrées dans un /etc/hosts le fichier ne sera pas utilisé dans une recherche).

Par défaut, la version 1.1.9 ou les versions ultérieures du cache NGINX répondent en utilisant la valeur TTL d'une réponse et une option valid paramètre permet de remplacer le temps de cache:

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

Avant la version 1.1.9, le réglage du temps de mise en cache n'était pas possible et nginx mettait toujours les réponses en cache pendant 5 minutes. =.

97
ohaal

Il y a des informations précieuses dans le commentaire de Gansbrest et la réponse d'Ohaal.

Mais je pense qu'il est important de mentionner cet article officiel de nginx, publié en 2016, il explique clairement le comportement de nginx à ce sujet et les solutions possibles: https://www.nginx.com/blog/dns-service-discovery -nginx-plus /

Nous devons en effet "définir le nom de domaine dans une variable" et utiliser la directive resolver .

cependant, l'utilisation d'une variable modifie le comportement de réécriture. Vous devrez peut-être utiliser la directive de réécriture, cela dépend de votre emplacement et de la configuration de proxy_pass.

PS: aurait posté un commentaire mais pas encore assez de points ...

9
Jack B.

la réponse de ohaal nous emmène presque partout, mais il y a un cas où le résolveur DNS ne vit pas à 127.0.0.1 (par exemple lorsque vous êtes dans un environnement conteneurisé spécial)

Dans ce cas, vous souhaiterez peut-être modifier la conf nginx en resolver ${DNS_SERVER};. Ensuite, avant de démarrer nginx, exécutez

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
3
wonton

J'ai piraté un script pour regarder un dossier conf.d en amont pour les modifications DNS et recharger nginx lors de la détection. C'est une première passe, et peut sûrement être améliorée (prochaine passe, je vais utiliser nginx -T pour analyser spécifiquement en amont. La même idée pourrait être utilisée pour les directives 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
0
mushuweasel