web-dev-qa-db-ja.com

proxy_passを実行するたびにnginxにDNS(動的ホスト名の)を強制的に解決させる方法は?

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アドレスへのリクエストが発生します。

Nginxが古いIPアドレスをキャッシュしないようにするにはどうすればよいですか?

58
xiamx

興味深い質問であり、うまく機能しないAFAIKです。 pstream モジュールを使用し、フェイルオーバーのディレクティブを使用して、ハックとして機能するかどうかを確認できます。

2018編集:多くの変更。 answer by @ohaal をチェックして、これに関する実際の情報を取得します。

9
coredump

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

proxy_passで変数を使用すると、DNS名の再解決が強制されます NGINXは静的構成とは異なる方法で変数を処理するため。 NGINX proxy_passドキュメント から:

パラメータ値には変数を含めることができます。この場合、アドレスがドメイン名として指定されていると、記述されているサーバーグループ間で名前が検索され、見つからない場合はリゾルバーを使用して決定されます。

例えば:

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

注:リゾルバー(つまり、使用するネームサーバー)が利用可能であり、これが機能するように構成されている必要があります(および/etc/hostsファイル内のエントリはルックアップで使用されません)。

デフォルトでは、NGINXキャッシュのバージョン1.1.9以降のバージョンは、TTL応答の値 とオプションの validを使用して応答しますパラメータ は、キャッシュ時間を上書きできるようにします。

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

バージョン1.1.9以前では、キャッシュ時間の調整は不可能であり、nginxは常に5分間キャッシュされた応答をキャッシュしました。 =。

97
ohaal

ガンスブレストのコメントと大げさな答えには貴重な情報があります。

しかし、2016年に投稿されたこのnginxの公式記事について言及することが重要だと思います。この問題に関するnginxの動作と可能な解決策を明確に説明しています: https://www.nginx.com/blog/dns-service-discovery -nginx-plus /

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

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

PS:コメントを投稿しますが、まだ十分なポイントがありません...

9
Jack B.

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
3
wonton

私はスクリプトをハッキングして、上流のconf.dフォルダーでdnsの変更を監視し、検出時に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
0
mushuweasel