NGINX: динамический upstream

Автор: | 12/04/2017
 

Имеется upstream в NGINX-е:

...
upstream jm-website-test {
 server jm-website-test.trafficmanager.net;
}
...

Проблема заключается в имени – jm-website-test.trafficmanager.net, значение которого меняется во время деплоя в зависимости от активного ендпоинта на Azure Traffic Manager:

[simterm]

$ dig +short jm-website-test.trafficmanager.net
google.com.
172.217.20.174

[/simterm]

Сейчас оно является алиасом на условную blue-ноду – google.com (на деле что-то вроде preview-blue.jm-website-sw-staging.domain.tld), а во время деплоя – blue-ендпоинт Traffic Manager-а будет отключен, а green – включен, и jm-website-test.trafficmanager.net будет указывать на green-ноду – yahoo.com. Такой себе blue/green деплой, только в Azure.

upstream передаётся в proxy_pass в виде имени upstream:

...
    location / {
    ...
        proxy_pass http://jm-website-test$request_uri;
    }
...

При таком подходе – NGINX выполняет разрешение имени в server апстрима только при рестарте или перезагрзуке конфигурации, и далее использует только его, т.е. трафик будет направляться на blue-ноду, пока NIGNX не будет перезапущен с restart или reload.

Сейчас – NGINX отдаёт содержимое blue-ноды:

[simterm]

# curl jm-website-test.domain.tld
...
  <title>Error 404 (Not Found)!!1</title>
  <style>
...
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>

[/simterm]

Меняем ендпоинты на Traffic Manager, ждём пару минут – проверяем:

[simterm]

# dig +short jm-website-test.trafficmanager.net
yahoo.com.

[/simterm]

DNS уже обновились, а NGINX продолжает отдавать старый контент:

[simterm]

# curl jm-website-test.domain.tld
...
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>

[/simterm]

Для того, что бы NGINX проверял значение по заданному TTL – задаём NGINX явное указание на resolver и через valid указываем TTL равным 10 секундам:

server {
    resolver 8.8.8.8 valid=10s;
    ...

А имя jm-website-test.trafficmanager.net – вынесем в переменную, которую будем передавать в proxy_pass:

...
#        proxy_pass http://jm-website-test$request_uri;
        set $jm_test_tm jm-website-test.trafficmanager.net;
        proxy_pass http://$jm_test_tm;
    }
...

Сохраняем, проверяем, перезагружаем:

[simterm]

root@jgr-gw:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@jgr-gw:~# service nginx reload
 * Reloading nginx configuration nginx

[/simterm]

Проверяем.

С активной blue-нодой (google):

[simterm]

# curl -L jm-website-test.domain.tld
...
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>

[/simterm]

OK, Google.

Через Portal переключаем ендпоинт Traffic Manager на “green-ноду” – yahoo:

Ждём пару минут, проверяем:

[simterm]

# dig +short jm-website-test.trafficmanager.net
yahoo.com.

[/simterm]

[simterm]

# curl -L jm-website-test.domain.tld
...      body {
          background: #fafafc url(https://s.yimg.com/nn/img/sad-panda-201402200631.png) 50% 50%;
...

[/simterm]

Готово – ответ от Yahoo – нашей “green-ноды”.

Больше деталей – в блоге NGINX.