Налаштування nginx не вийде з ладу, якщо хост у верхньому потоці не знайдено


117

У Docker у нас є кілька додатків рейлів під загальним доменом, і ми використовуємо nginx для направлення запитів на певні додатки.

our_dev_server.com/foo # proxies to foo app
our_dev_server.com/bar # proxies to bar

Конфігурація виглядає так:

upstream foo {
  server foo:3000;
}

upstream bar {
  server bar:3000;
}

# and about 10 more...

server {
  listen *:80 default_server;

  server_name our_dev_server.com;

  location /foo {
      # this is specific to asset management in rails dev
      rewrite ^/foo/assets(/.*)$ /assets/$1 break;
      rewrite ^/foo(/.*)$ /foo/$1 break;
      proxy_pass http://foo;
  }

  location /bar {
      rewrite ^/bar/assets(/.*)$ /assets/$1 break;
      rewrite ^/bar(/.*)$ /bar/$1 break;
      proxy_pass http://bar;
  }

  # and about 10 more...
}

Якщо одне з цих додатків не запускається, тоді nginx виходить з ладу і зупиняється:

host not found in upstream "bar:3000" in /etc/nginx/conf.d/nginx.conf:6

Нам не потрібно, щоб вони були налаштовані, але nginx виходить з ладу. Як зробити так, щоб nginx ігнорував невдалі upstreams?


1
Ви пов'язуєте контейнери додатків із контейнерами Nginx чи запускаєте їх окремо один від одного? Якщо хост всередині upstreamблоку не вирішиться під час виконання, тоді Nginx вийде із вказаною вище помилкою ...
Джастін

1
Якщо ви можете скористатися IP-адресою, це буде добре. Чи використовуватиме resolver( nginx.org/en/docs/http/ngx_http_core_module.html#resolver ) у вашому випадку?
Джастін

@Justin, у нас є кожен додаток в окремому контейнері, також nginx. Пов’язати їх із докером
Морозов

@Justin Startup порядку, nginx запускається після інших програм. Ми просто хочемо запустити лише деякі з них :)
Морозов

1
У мене є аналогічна установка (контейнер Nginx з контейнерами додатків) . Ми створили зображення Nginx, що включає proxy.shсценарій, який читає змінні середовища та динамічно додає upstreamзаписи для кожної, а потім запускає Nginx. Це чудово спрацьовує з тим, що коли ми запускаємо наш проксі-контейнер, ми можемо переходити в потрібні upstreams під час виконання. Ви можете зробити щось подібне, щоб увімкнути / вимкнути певні потоки під час запуску (або, наприклад, до моєї установки просто додати ті, які потрібні під час виконання)
Джастін,

Відповіді:


90
  1. Якщо ви можете використовувати статичний IP, тоді просто скористайтеся цим, він запуститься і повернеться 503, якщо він не відповідає.

  2. Використовуйте resolverдирективу, щоб вказати на те, що може вирішити хост, незалежно від того, він наразі працює чи ні.

  3. Вирішіть його на locationрівні, якщо ви не можете зробити вищезазначене (це дозволить Nginx запустити / запустити) :

    location /foo {
      resolver 127.0.0.1 valid=30s;
      # or some other DNS (you company/internal DNS server)
      #resolver 8.8.8.8 valid=30s;
      set $upstream_foo foo;
      proxy_pass http://$upstream_foo:80;
    }
    
    location /bar {
      resolver 127.0.0.1 valid=30s;
      # or some other DNS (you company/internal DNS server)
      #resolver 8.8.8.8 valid=30s;
      set $upstream_bar foo;
      proxy_pass http://$upstream_bar:80;
    }
    

1
ваш варіант 3 працює для мене чудово. Якщо я не вказую розв'язувач, чи знаєте ви, як довго nginx буде кешувати IP, який він вирішує?
Райлі Ларк

14
Дякую! Просто використання змінної, схоже, утримує nginx від розуму щодо цього
Blanka

1
Я виявив, що група захоплення регулярних location ~ ^/foo/(.*)$ { proxy_pass http://foo/$1; }
виразів

2
Як це працює для проксі-сервера TCP? Здається, немає можливості спробувати варіант 3 для проксі-сервера tcp.
krish7919

1
@Charlie такі помилки в nginx майже завжди пов'язані з відсутністю ";" підпишіть наприкінці рядка :)
SteveB

18

Для мене варіант 3 відповіді від @ Justin / @ duskwuff вирішив проблему, але мені довелося змінити IP- адресу резолютора на 127.0.0.11 (DNS-сервер Docker):

location /foo {
  resolver 127.0.0.11 valid=30s;
  set $upstream_foo foo;
  proxy_pass http://$upstream_foo:80;
}

location /bar {
  resolver 127.0.0.11 valid=30s;
  set $upstream_bar foo;
  proxy_pass http://$upstream_bar:80;
}

Але, як згадував @ Justin / @ duskwuff, ви можете використовувати будь-який інший зовнішній сервер DNS.


15

Основна перевага використання upstream- це визначити групу серверів, ніж їх можна прослуховувати в різних портах, а також налаштувати балансування навантаження та відмову між ними .

У вашому випадку ви визначаєте лише 1 основний сервер на верхньому потоці, тому він повинен бути вгору .

Натомість використовуйте змінні для своїх proxy_pass(-ів) і пам'ятайте, щоб обробити можливі помилки (404s, 503s), які можуть виникнути, коли цільовий сервер не працює.


1
> Натомість використовуйте змінні для своїх proxy_pass (ів) і не забудьте обробити можливі помилки (404s, 503s), які можуть виникнути, коли цільовий сервер не працює. Чи можете ви детальніше розглянути, як це зробити? Якщо я set $variable http://fooі proxy_pass $variableта тримати Foo «вгору» (щоб зберегти переваги ви згадали) , то я до сих пір б'ючи питання , згаданий ОП.
Тібор Вас

6
Як ви можете бачити в інших прикладах, це буде set $variable fooіproxy_pass http://$variable
danielgpm

2
@danielgpm Як ви заявили, використання змінної для proxy_pass прекрасно працює і вирішило мою проблему. Це допоможе іншим, якщо ви можете оновити свою відповідь і згадати це як приклад
Nitb

3
Що робити, якщо у мене їх більше, і я хочу ігнорувати ті, які неможливо вирішити?
талаби

0

У мене була та сама проблема "Хост не знайдено", тому що частина мого хоста була відображена за допомогою, $uriа не $request_uri:

proxy_pass http://one-api-service.$kubernetes:8091/auth;

І коли запит змінився на підзапит auth, він $uriвтратив своє початкове значення. Зміна відображення на використання $request_uriзамість $uriвирішеної проблеми:

map $request_uri $kubernetes {
    # ...
}

-8

Ви не можете використовувати --linkопцію, натомість ви можете використовувати відображення портів і прив’язати nginx до адреси хоста.

Приклад: запустіть перший контейнер докера з -p 180:80опцією, другий контейнер з -p 280:80опцією.

Запустіть nginx і встановіть ці адреси для проксі:

proxy_pass http://192.168.1.20:180/; # first container
proxy_pass http://192.168.1.20:280/; # second container
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.