113 votes

Comment forcer nginx à résoudre les DNS (d'un nom d'hôte dynamique) à chaque fois qu'il utilise le proxy_pass ?

J'utilise nginx/0.7.68, fonctionnant sous 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

El proxy_pass est à un enregistrement DNS dont l'IP change fréquemment. Nginx met en cache l'adresse IP périmée, ce qui entraîne une requête vers la mauvaise adresse IP.

Comment puis-je empêcher nginx de mettre en cache l'adresse IP, lorsqu'elle est périmée ?

166voto

ohaal Points 2162

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

Utilisation 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. De la NGINX proxy_pass documentation :

La valeur du paramètre peut contenir des variables. Dans ce cas, si une adresse est spécifiée comme un nom de domaine, le nom est recherché parmi les groupes de serveurs décrits et, s'il n'est pas trouvé, il 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 à l'intérieur d'un serveur de noms). /etc/hosts ne sera pas utilisé dans une recherche).

Par défaut, la version 1.1.9 ou les versions ultérieures de NGINX mettent en cache les réponses en utilisant la valeur TTL d'une réponse. et une option valid parámetro permet de remplacer la durée du 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 met toujours les réponses en cache pour une durée de 5 minutes. .

16voto

Jack B. Points 131

Il y a des informations précieuses dans le commentaire de gansbrest et la réponse de ohaal.

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

Nous devons en effet "mettre le nom de domaine dans une variable" et utiliser la fonction résolveur directive.

Toutefois, 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 du proxy_pass.

PS : j'aurais bien posté un commentaire mais je n'ai pas encore assez de points...

12voto

wonton Points 201

La réponse d'ohaal permet à la plupart d'entre nous d'y arriver, mais il existe un cas où le résolveur DNS ne se trouve pas à 127.0.0.1 (par exemple lorsque vous êtes dans un environnement conteneurisé spécial).

Dans ce cas, vous pouvez changer le conf de 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

Notez, que vous avez besoin du gettext installé, car il fournit le envsubst commandement.

11voto

coredump Points 12455

C'est une question intrigante et, selon moi, cela ne fonctionnera pas bien. Vous pouvez essayer d'utiliser le en amont et utiliser les directives de basculement pour voir si cela fonctionne comme un hack.

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

2voto

mushuweasel Points 121

J'ai bricolé un script pour regarder les amonts d'un dossier conf.d pour les changements dns et recharger nginx sur détection. C'est une première passe, et sûrement peut être amélioré (prochaine passe, je vais utiliser nginx -T pour parser les upstreams spécifiquement. 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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X