proxy_passを行うときに毎回nginxに(動的ホスト名の)DNSを強制的に解決させる方法は?


52

CentOSで実行されているnginx / 0.7.68を次の構成で使用しています。

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は、IPが頻繁に変更されるDNSレコードに対するものです。Nginxは古いIPアドレスをキャッシュするため、誤ったIPアドレスへのリクエストが発生します。

IPアドレスが古くなった場合、nginxがIPアドレスをキャッシュしないようにするにはどうすればよいですか?


nginxソースを見ると、nginxはTTLにキャッシュ解決するようにハードコードされているようです-ダイナミックDNSのTTLは何ですか?
lunixbochs

私のddnsのTTLは60秒で、dyndns.comのデフォルト値
xiamx


回答:


8

それは興味をそそる質問であり、よくわからないのは知っている。あなたは、使用しようとすることができ、上流のモジュールを、それがハックとして動作するかどうかを確認するために、フェイルオーバーのためのディレクティブを使用します。

2018年の編集:多くのことが変更されました。これに関する実際の情報を得るには、@ ohaalによる回答を確認してください。


1
驚くことに、アップストリームに変更したとき、すべてが期待どおりに機能しました。次に、これを正解としてマークします
-xiamx

1
ドキュメントによると、商用版でのみ利用可能な特別なアップストリームserverフラグresolveがあります(nginx.org/en/docs/http/ngx_http_upstream_module.html#serverを参照)
omribahumi

1
@gansbrestそのサイトはある種のスパムサイトのようです?回答を削除するようお願いします。
マジクマン

90

nginx / 1.4.2では、受け入れられた回答が機能しませんでした。

proxy_passNGINXは変数を静的構成とは異なる方法で処理するため、変数を使用すると、DNS名の再解決が強制されます。NGINX proxy_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.わかりやすくするために、回答に追加しました。
オハール

13
私の一日の大半をこれに費やした後-Ubuntu 12.04とnginx 1.1.19では、set内部locationが正しく機能しません。注意
オムリバフミ

このソリューションは私と一緒に機能しましたが、5分間のTTLの参照が見つかりませんでした。nginx.org/en/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;
Montaro

4
注:ドッキングウィンドウのために、127.0.0.11でそれのDNSリゾルバが存在するが、その開発のために、私はこれを使用:resolver 127.0.0.11 [::1]:5353 valid=15s;
ダリボルFilus

9

gansbrestのコメントとohaalの回答には貴重な情報があります。

しかし、2016年に投稿されたこの公式のnginxの記事に言及することは重要だと思い ます。 /

実際、「変数にドメイン名を設定」し、リゾルバーディレクティブを使用する必要があります

ただし、変数を使用すると、書き換え動作が変更されます。rewriteディレクティブを使用する必要がある場合があります。これは、場所とproxy_passの設定によって異なります。

PS:コメントは投稿できたでしょうが、まだ十分なポイントがありません...


1

ohaalの答えは私たちのほとんどをそこに連れて行きますが、DNSリゾルバが127.0.0.1に住んでいない場合があります(たとえば、特別なコンテナ化された環境にいるとき)

その場合、nginx confをに変更することもできますresolver ${DNS_SERVER};。次に、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

私は、dnsの変更を上流のconf.dフォルダーで監視し、検出時にnginxをリロードするスクリプトを一緒にハッキングしました。これは最初のパスであり、確実に改善できます(次のパスでは、nginx -Tを使用してアップストリームを具体的に解析します。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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.