Як змусити nginx вирішувати DNS (динамічного імені хоста) кожного разу, коли ви робите proxy_pass?


52

Я використовую nginx / 0.7.68, що працює на CentOS, із такою конфігурацією:

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_pass- запис DNS, IP-адрес якого часто змінюється. Nginx кешує застарілу IP-адресу, що призводить до запиту на неправильну IP-адресу.

Як я можу зупинити nginx від кешування IP-адреси, коли вона застаріла?


переглядаючи джерело nginx, здається, що nginx важко кодується, щоб кешувати рішення для їх TTL - що таке TTL у ваших динамічних dns?
lunixbochs

TTL в моїй ddns - 60-ті, значення за замовчуванням dyndns.com
xiamx


Відповіді:


8

Це інтригуюче питання, і AFAIK не спрацює добре. Ви можете спробувати використати модуль висхідного потоку та використовувати директиви для відмови, щоб побачити, чи працює він як хак.

2018 редакція: багато чого змінилося. Перевірте відповідь від @ohaal, щоб отримати реальну інформацію про це.


1
дивно, коли я змінився на верхній течії, все працювало так, як очікувалося. Тоді я
позначу

1
Згідно з документацією, є спеціальний serverпрапор вище за течією, resolveякий доступний лише в комерційній версії (див. Nginx.org/en/docs/http/ngx_http_upstream_module.html#server )
omribahumi

1
@gansbrest, здається, що цей сайт є якимось спам-сайтом? Я б попросив видалити свою відповідь.
majikman

90

Прийнята відповідь не працювала для мене на nginx / 1.4.2.

Використання змінної proxy_passпримушує перерозділити імена DNS, оскільки NGINX по-різному ставиться до змінних до статичної конфігурації. З документації NGINXproxy_pass :

Значення параметра може містити змінні. У цьому випадку, якщо адреса вказана як доменне ім'я, ім'я шукається серед описаних груп серверів і, якщо його не знайдено, визначається за допомогою роздільної здатності.

Наприклад:

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

Примітка: Розв’язувач (тобто сервер імен, який потрібно використовувати) ОБОВ'ЯЗКОВО повинен бути доступним і налаштованим, щоб це працювало (а записи всередині /etc/hostsфайлу не використовуються при пошуку).

За замовчуванням версії 1.1.9 або новіших версій кешу NGINX відповідають з використанням значення TTL відповіді та необов'язкового validпараметра дозволяє переохочувати час кешу:

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

Перед версією 1.1.9 налаштування часу кешування було неможливим, і nginx завжди кешував відповіді тривалістю 5 хвилин. .


Хіба це не змусить dns-запит на кожен запит? це звучить як жахлива вистава ...
lucascaro

Ні, читайте джерело. In such setup ip address of "foo.example.com" will be looked up dynamically and result will be cached for 5 minutes.Я додав це до відповіді для наочності.
ohaal

13
Провівши більшу частину мого дня на цьому - на Ubuntu 12.04 з nginx 1.1.19, setвсередині locationне працює належним чином. Остерігайтеся
omribahumi

Це рішення працювало зі мною, проте я не міг знайти посилання на 5 хвилин TTL. nginx.org/uk/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;
Монтаро

4
Примітка. Для докера DNS-роздільник розміщений у 127.0.0.11, тому для розробки я використовую це:resolver 127.0.0.11 [::1]:5353 valid=15s;
Dalibor Filus

9

Цінна інформація є в коментарях до gansbrest та у відповіді.

Але я думаю, що важливо згадати цю офіційну статтю nginx, опубліковану в 2016 році, вона чітко пояснює поведінку nginx з цього приводу та можливі рішення: https://www.nginx.com/blog/dns-service-discovery-nginx-plus /

Нам дійсно потрібно "Встановити доменне ім'я в змінну" і використовувати директиву на резолюцію .

однак використання змінної змінює поведінку перезапису. Можливо, вам доведеться скористатись директивою переписувати, це залежить від вашого місця розташування та налаштування проксі-пароля.

PS: опублікував би коментар, але ще недостатньо балів ...


1

відповідь ohaal приймає більшість із нас там, але є випадок, коли резолютор DNS не працює у 127.0.0.1 (наприклад, коли ви знаходитесь у спеціальному контейнерному середовищі)

У цьому випадку ви можете змінити конф resolver ${DNS_SERVER};. Nginx на . Потім перед запуском nginx запустіть

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

Я зламав разом сценарій для перегляду вхідних потоків папки conf.d для зміни dns та перезавантаження nginx після виявлення. Це перший прохід, і він, безумовно, може бути вдосконалений (наступний пропуск, я буду використовувати nginx -T для розбору конкретно upstreams. Ця ж ідея може бути використана для директив 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.