Як змусити 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.