Bagaimana memaksa nginx untuk menyelesaikan DNS (dari nama host dinamis) setiap saat melakukan proxy_pass?


52

Saya menggunakan nginx / 0.7.68, berjalan pada CentOS, dengan konfigurasi berikut:

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

Ini proxy_passuntuk catatan DNS yang IP-nya sering berubah. Nginx melakukan cache alamat IP yang kedaluwarsa, menghasilkan permintaan ke alamat IP yang salah.

Bagaimana saya bisa menghentikan nginx dari caching alamat IP, ketika sudah usang?


melihat melalui sumber nginx, tampaknya nginx hardcoded untuk menyelesaikan cache untuk TTL mereka - apa TTL pada dns dinamis Anda?
lunixbochs

TTL pada ddns saya adalah 60-an, nilai default dyndns.com
xiamx


Jawaban:


8

Ini pertanyaan yang menarik dan AFAIK yang tidak akan bekerja dengan baik. Anda dapat mencoba menggunakan modul upstream dan menggunakan arahan untuk failover untuk melihat apakah itu berfungsi sebagai peretasan.

Sunting 2018: banyak hal berubah. Periksa jawabannya oleh @ohaal untuk mendapatkan informasi nyata tentang ini.


1
mengherankan ketika saya berubah menjadi hulu, semuanya berjalan sesuai harapan. Saya kemudian akan menandai ini sebagai jawaban yang benar
xiamx

1
Menurut dokumentasi, ada serverbendera hulu khusus resolveyang hanya tersedia dalam versi komersial (lihat nginx.org/en/docs/http/ngx_http_upstream_module.html#server )
omribahumi

1
@ gansbrest situs itu sepertinya semacam situs spam? saya akan meminta Anda menghapus respons Anda.
majikman

90

Jawaban yang diterima tidak berfungsi untuk saya di nginx / 1.4.2.

Menggunakan variabel yang proxy_passmemaksa resolusi ulang nama DNS karena NGINX memperlakukan variabel secara berbeda untuk konfigurasi statis. Dari dokumentasi NGINXproxy_pass :

Nilai parameter dapat berisi variabel. Dalam hal ini, jika alamat ditentukan sebagai nama domain, nama tersebut dicari di antara kelompok server yang dijelaskan, dan, jika tidak ditemukan, ditentukan menggunakan resolver.

Sebagai contoh:

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

Catatan: Penyelesai (yaitu server nama yang akan digunakan) HARUS tersedia dan dikonfigurasikan agar ini berfungsi (dan entri di dalam /etc/hostsfile tidak akan digunakan dalam pencarian).

Secara default, versi 1.1.9 atau versi yang lebih baru dari jawaban cache NGINX menggunakan nilai TTL dari respons dan validparameter opsional memungkinkan waktu cache ditimpa:

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

Sebelum versi 1.1.9, penyetelan waktu caching tidak dimungkinkan, dan nginx selalu menyembunyikan jawaban selama 5 menit. .


tidakkah ini memaksa permintaan dns pada setiap permintaan tunggal? kedengarannya seperti kinerja yang mengerikan ...
lucascaro

Tidak, baca sumbernya. In such setup ip address of "foo.example.com" will be looked up dynamically and result will be cached for 5 minutes.Saya telah menambahkannya ke jawaban untuk kejelasan.
ohaal

13
Setelah menghabiskan sebagian besar hari saya untuk ini - di Ubuntu 12.04 dengan nginx 1.1.19, setdi dalamnya locationtidak berfungsi dengan baik. Waspadalah
omribahumi

Solusi ini bekerja dengan saya, namun saya tidak dapat menemukan referensi untuk TTL 5 menit. 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
Catatan: untuk buruh pelabuhan, resolver DNSnya berada di 127.0.0.11, jadi untuk pengembangan, saya menggunakan ini:resolver 127.0.0.11 [::1]:5353 valid=15s;
Dalibor Filus

9

Ada informasi berharga di komentar gansbrest dan jawaban ohaal.

Tapi saya pikir penting untuk menyebutkan artikel nginx resmi ini, yang diposting pada tahun 2016, dengan jelas menjelaskan perilaku nginx tentang masalah ini dan kemungkinan solusinya: https://www.nginx.com/blog/dns-service-discovery-nginx-plus /

Kita memang harus "Mengatur Nama Domain dalam Variabel" dan menggunakan arahan resolver .

Namun, menggunakan variabel mengubah perilaku menulis ulang. Anda mungkin harus menggunakan arahan penulisan ulang, itu tergantung pada lokasi Anda dan pengaturan proxy_pass.

PS: akan memposting komentar tetapi belum cukup poin ...


1

jawaban ohaal membawa sebagian besar dari kita ke sana, tetapi ada kasus di mana resolver DNS tidak hidup di 127.0.0.1 (mis. ketika Anda berada di lingkungan kemas khusus)

Dalam hal ini, Anda mungkin ingin mengubah conf nginx menjadi resolver ${DNS_SERVER};. Lalu, sebelum Anda memulai nginx, jalankan

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

Saya telah meretas sebuah skrip untuk menonton folder conf.d upstreams untuk perubahan dns dan memuat ulang nginx saat terdeteksi. Ini merupakan pass pertama, dan tentunya dapat ditingkatkan (pass berikutnya, saya akan menggunakan nginx -T untuk mengurai upstreams secara khusus. Ide yang sama dapat digunakan untuk arahan 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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.