アップストリームのホストが見つからない場合にnginxがクラッシュしないように設定


117

Dockerの共通ドメインの下にいくつかのRailsアプリがあり、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に失敗したアップストリームを無視させる方法は?


1
アプリコンテナーをNginxコンテナーにリンクしていますか、それとも互いに別々に実行していますか?upstreamブロック内のホストが解決しない場合、実行時にNginxは上記のエラーで終了します...
Justin

1
IPを使用できる場合は、正常に起動します。あなたの場合、resolvernginx.org/en/docs/http/ngx_http_core_module.html#resolver)を使用するとうまくいきますか?
ジャスティン

@Justinでは、各アプリを別々のコンテナーに配置します。nginxも同様です。それらをドッカーとリンクする
モロゾフ

@Justin起動順序は問題ありません。nginxは他のアプリの後に起動します。私たちはそれらの一部のみを実行したいだけです:)
Morozov

1
私は同様の設定(アプリコンテナーを含むNginxコンテナー)を持っています。proxy.sh環境変数を読み取りupstream、それぞれに動的にエントリを追加してNginxを起動するスクリプトを含むNginxイメージを作成しました。これは、プロキシコンテナを実行するときに、実行時に必要なアップストリームを渡すことができるという点で優れています。起動時に特定のアップストリームを有効/無効にするのと同じようなことをすることができます(または私のセットアップのように実行時に必要なものを追加するだけです)
Justin

回答:


90
  1. 静的IPを使用できる場合は、それを使用するだけで起動し、503応答しない場合はsを返します。

  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をキャッシュする期間を知っていますか?
Riley Lark

14
ありがとう!変数を使用するだけで、nginxは賢くなりません
Blanka

1
私は正規表現キャプチャグループは、私は、変数をスキップすることが許可されていることが見つかりました:location ~ ^/foo/(.*)$ { proxy_pass http://foo/$1; }
ダニーKirchmeier

2
TCPプロキシではどのように機能しますか?tcpプロキシのオプション3を試す方法はないようです。
krish7919 2017年

1
@Charlie nginxでのこの種のエラーは、ほとんどの場合、「;」の欠落に関連しています。行末に署名します:)
SteveB

18

私にとっては、@ Justin / @ duskwuffからの回答のオプション3で問題が解決しましたが、リゾルバーIPを127.0.0.11(DockerのDNSサーバー)に変更する必要がありました。

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(es)の変数を使用し、ターゲットサーバーがダウンしているときに発生する可能性のあるエラー(404、503)を処理することを忘れないでください。


1
>代わりに、proxy_pass(es)に変数を使用し、ターゲットサーバーがダウンしているときに発生する可能性のあるエラー(404、503)を処理することを忘れないでください。それを行う方法について詳しく説明できますか?私が行う場合set $variable http://fooproxy_pass $variableし、「上流」FOOを維持し、その後、私はまだOPで述べた問題を打っています(あなたが言及した利点を維持します)。
ティボーヴァース

6
他の例でもわかるようにset $variable foo、andproxy_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オプション付きの最初のdockerコンテナー、オプション付きの2番目のコンテナーを実行し-p 280:80ます。

nginxを実行し、プロキシにこれらのアドレスを設定します。

proxy_pass http://192.168.1.20:180/; # first container
proxy_pass http://192.168.1.20:280/; # second container
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.