วิธีการบังคับให้ nginx แก้ไข DNS (ของชื่อโฮสต์แบบไดนามิก) ทุกครั้งเมื่อทำ proxy_pass


52

ฉันใช้ nginx / 0.7.68 ทำงานบน CentOS ด้วยการกำหนดค่าต่อไปนี้:

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คือระเบียน DNS ที่มีการเปลี่ยนแปลง IP บ่อยครั้ง Nginx แคชที่อยู่ IP ที่ล้าสมัยส่งผลให้เกิดการร้องขอไปยังที่อยู่ IP ที่ไม่ถูกต้อง

ฉันจะหยุด nginx จากการแคชที่อยู่ IP เมื่อมันล้าสมัยได้อย่างไร?


หากมองผ่านแหล่งข้อมูล nginx จะปรากฏว่า nginx นั้นเป็นฮาร์ดโค้ดที่แคชจะแก้ไขค่า TTL ของพวกเขา - TTL บนไดนามิกไดนามิกของคุณคืออะไร
lunixbochs

TTL ใน ddns ของฉันคือ 60s ค่าเริ่มต้นของ dyndns.com
xiamx


เกี่ยวข้อง: serverfault.com/questions/560632/…
nick fox

คำตอบ:


8

มันเป็นคำถามที่น่าสนใจและ AFAIK ที่ทำงานได้ไม่ดี คุณสามารถลองใช้โมดูลอัปสตรีมและใช้คำสั่งสำหรับการเฟลโอเวอร์เพื่อดูว่ามันทำงานเหมือนแฮ็คหรือไม่

2018 แก้ไข: มีการเปลี่ยนแปลงหลายอย่าง ตรวจสอบคำตอบโดย @ohaalเพื่อรับข้อมูลจริงเกี่ยวกับเรื่องนี้


1
น่าแปลกใจเมื่อฉันเปลี่ยนเป็นอัปสตรีมทุกอย่างทำงานตามที่คาดไว้ จากนั้นฉันจะทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้อง
xiamx

1
ตามเอกสารที่มีต้นน้ำพิเศษserverธงresolveที่มีอยู่เฉพาะในรุ่นในเชิงพาณิชย์ (ดูnginx.org/en/docs/http/ngx_http_upstream_module.html#server )
omribahumi

1
@gansbrest ดูเหมือนว่าไซต์นั้นเป็นไซต์ประเภทสแปมหรือไม่ ฉันขอให้คุณลบคำตอบของคุณ
majikman

90

คำตอบที่ยอมรับไม่ได้ผลสำหรับฉันใน nginx / 1.4.2

การใช้ตัวแปรในการproxy_passบังคับให้มีการแก้ไขชื่อ DNS อีกครั้งเนื่องจาก NGINX ปฏิบัติต่อตัวแปรแตกต่างจากการกำหนดค่าแบบคงที่ จากเอกสารNGINXproxy_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.ฉันได้เพิ่มไปยังคำตอบเพื่อความชัดเจน
ohaal

13
หลังจากใช้เวลาส่วนใหญ่ของฉันไปกับสิ่งนี้ - บน Ubuntu 12.04 ด้วย nginx 1.1.19 setภายในlocationไม่ทำงานอย่างถูกต้อง ระวัง
omribahumi

วิธีนี้ใช้ได้กับฉัน แต่ฉันไม่พบการอ้างอิงสำหรับ TTL 5 นาที 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
หมายเหตุ: สำหรับนักเทียบท่ามันเป็นตัวแก้ไข DNS อยู่ที่ 127.0.0.11 ดังนั้นสำหรับการพัฒนาฉันใช้สิ่งนี้:resolver 127.0.0.11 [::1]:5353 valid=15s;
Dalibor Filus

9

มีข้อมูลที่มีค่าในความคิดเห็น gansbrest และคำตอบ ohaal

แต่ฉันคิดว่ามันเป็นสิ่งสำคัญที่จะพูดถึงบทความ nginx อย่างเป็นทางการนี้โพสต์ในปี 2559 มันอธิบายพฤติกรรมของ nginx ได้อย่างชัดเจนในเรื่องนี้และวิธีแก้ปัญหาที่เป็นไปได้: https://www.nginx.com/blog/dns-service-discovery-nginx-plus /

แน่นอนเราต้อง "ตั้งค่าชื่อโดเมนในตัวแปร" และใช้คำสั่งตัวแก้ไข

อย่างไรก็ตามการใช้ตัวแปรจะเปลี่ยนพฤติกรรมการเขียนใหม่ คุณอาจต้องใช้คำสั่งเขียนใหม่ขึ้นอยู่กับตำแหน่งและการตั้งค่า proxy_pass ของคุณ

PS: จะมีความคิดเห็น แต่ยังมีคะแนนไม่พอ ...


1

คำตอบของ ohaal ทำให้เราส่วนใหญ่อยู่ที่นั่น แต่มีกรณีที่ตัวแก้ไข DNS ไม่ทำงานที่ 127.0.0.1 (เช่นเมื่อคุณอยู่ในสภาพแวดล้อมแบบพิเศษ)

ในกรณีที่คุณอาจต้องการที่จะเปลี่ยน conf Nginx 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

ฉันแฮกสคริปต์ร่วมกันเพื่อดูโฟลเดอร์ conf.d upstreams สำหรับการเปลี่ยนแปลง DNS และโหลด nginx เมื่อตรวจจับ มันเป็นรหัสผ่านครั้งแรกและสามารถปรับปรุงได้อย่างแน่นอน (รหัสผ่านถัดไปฉันจะใช้ nginx -T เพื่อแยกวิเคราะห์ upstreams โดยเฉพาะความคิดเดียวกันนี้สามารถใช้สำหรับคำสั่ง 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.