Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Nginx cache pitfalls

Nginx cache pitfalls

社内LT用に作成した資料です。NginxのDNS cacheにはまった話をしました

Tsuji Daishiro

December 04, 2019
Tweet

More Decks by Tsuji Daishiro

Other Decks in Technology

Transcript

  1. Nginxのcacheにはまった話
    2019/12/4(Wed)
    mornIngTalk #4
    Future Architect Tsuji Daishiro

    View Slide

  2. 構成の概要
    ✓ Nginxはリバースプロキシ
    ✓ クライアントアプリからNginxを経由してバックエンドのHerokuアプリのAPIにアクセス
    2

    View Slide

  3. nginx.conf
    ✓ nginx.confの一部
    ✓ よくあるupstreamを使ったconfig
    3
    http {
    upstream backend {
    server sample.herokuapp.com:443;
    }
    server {
    location /hoge {
    proxy_pass https://backend;
    proxy_set_header Host sample.herokuapp.com;
    proxy_redirect off;
    }
    }
    }
    nginx.conf

    View Slide

  4. 事象
    4

    View Slide

  5. 問題の事象
    ✓ たまに404のNot Foundがレスポンスとして返ってくる
    ✓ 観測すると10回に1回程度の頻度
    ✓ 通常は “OK” などの文字列が返ってくる
    5
    404としてレスポンスが返ってきたときのBodyのHTMLの一例

    View Slide

  6. 原因
    6

    View Slide

  7. 原因
    ✓ NginxのDNSのcacheの仕様によるものだった
    ✓ https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
    7
    As NGINX starts up or reloads its configuration, it queries a DNS server to resolve backends.example.com. The DNS
    server returns the list of three backends discussed above, and NGINX uses the default Round Robin algorithm to
    load balance requests among them. NGINX chooses the DNS server from the OS configuration file /etc/resolv.conf.
    This method is the least flexible way to do service discovery and has the following additional drawbacks:
    • If the domain name can’t be resolved, NGINX fails to start or reload its configuration.
    • NGINX caches the DNS records until the next restart or configuration reload, ignoring the records’ TTL values.
    • We can’t specify another load-balancing algorithm, nor can we configure passive health checks or other
    features defined by parameters to the server directive, which we’ll describe in the next section.

    View Slide

  8. 原因
    ✓ NginxのDNSのcacheの仕様によるものだった
    ✓ https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
    8
    As NGINX starts up or reloads its configuration, it queries a DNS server to resolve backends.example.com. The DNS
    server returns the list of three backends discussed above, and NGINX uses the default Round Robin algorithm to
    load balance requests among them. NGINX chooses the DNS server from the OS configuration file /etc/resolv.conf.
    This method is the least flexible way to do service discovery and has the following additional drawbacks:
    • If the domain name can’t be resolved, NGINX fails to start or reload its configuration.
    • NGINX caches the DNS records until the next restart or configuration reload, ignoring the records’ TTL values.
    • We can’t specify another load-balancing algorithm, nor can we configure passive health checks or other
    features defined by parameters to the server directive, which we’ll describe in the next section.
    再起動やリロードするまでDNSレコードをキャッシュ。TTLは無視。

    View Slide

  9. 問題にならないケースも
    ✓ DNSレコードをキャッシュしても問題にならないケースがある
    ✓ ドメイン名に対して、名前解決先のIPアドレスが一定の場合
    9
    hoge.com
    192.168.1.1
    192.168.1.2
    固定のIPアドレスに紐づく場合など

    View Slide

  10. 今回のケース
    ✓ バックエンドのサービスがHeroku
    ✓ SaaS
    ✓ デプロイしたサービスに紐づくドメインのグローバルIPが都度変わる
    $ nslookup sample.herokuapp.com
    ✓ Internalの通信にALBをはさむ場合も同様
    10
    あるタイミングで名前解決したDNSレコードが有効とは限らない

    View Slide

  11. 何が起こっていたか
    ✓ デプロイしたサービスとは別のサービスと通信していると判断
    ✓ グローバルIPの割り当て方法について、サポートから明確な回答は得られず。
    11
    sample.heroku.com → x.x.x.x
    x.x.x.x のIPアドレスは自分たちのサービスに割り当てられて
    おらず、別のサービスに割り当てられている。
    別のサービス
    自分たちのサービス
    別のサービスと通信したときの404 Not Foundのレスポンス

    View Slide

  12. 対応策
    12

    View Slide

  13. 対応策
    ✓ 都度名前解決させる
    ✓ set, resolver, proxy_passを用いることで実装可能
    ✓ upstreamを諦める(少し頑張ればupstreamでも実装できるよう。未確認)
    13
    http {
    resolver 169.254.169.253 valid=0s;
    server {
    listen 80 default_server;
    server_name _;
    root /usr/share/nginx/html;
    location /hoge {
    set $url "https://sample.herokuapp.com/hoge";
    proxy_pass $url;
    proxy_redirect off;
    }
    }
    }
    nginx.conf

    View Slide

  14. View Slide