GCEのDNSサーバ

nginxをリバースプロキシとして使っておりプロキシ先をホスト名で指定しているケースで、プロキシ先のインスタンスを復元するなどしてIPアドレスが変わると、nginxからプロキシ先に接続できなくなりHTTP 502エラーになってしまいます。

これはnginxがプロキシ先のIPアドレスをキャッシュしているためなので再起動すれば治るが、configにresolverを指定しておけば再起動する必要はなくなる。

resolver: 8.8.8.8; 
proxy_pass http://dev-nyan-app01:8080;

resolverを指定しておくと、TTLが切れた時に再度名前解決に行くようになる。

で、ここからが本題。nginxをGCPのCompute Engine上で動かしている場合、resolverに何を指定すればいいんじゃろか??と思って調べたのがこの記事のお話。8.8.8.8はグローバルなDNSなのでVPC内のホスト名を解決できるわけがありません。

なおOSはUbuntu 18.04である。Ubuntuが見ているDNSを調べればええやというわけで、とりあえず /etc/resolve.conf を確認

$ < /etc/resolv.conf  grep namesever
nameserver 127.0.0.53

このIPアドレスIPv4ループバックアドレスである。ループバックアドレスというと127.0.0.1 のような気がするが、IPv4では 127.0.0.0/8 全てがループバックアドレスとして予約されている。なぜこんな広大な空間を確保してしまったのか・・・

それはともかく、つまりローカルにDNSサーバが立っており、そこを見に行っているということだ。ssコマンドで調べてみると・・・

$ ss -lt
...
LISTEN            0                 4096                           127.0.0.53%lo:domain                              0.0.0.0:*
...

これはsystemdが提供するlocal dns stub listenerというDNSサーバで、ここに名前解決の問い合わせを投げると代わりに本物DNSサーバに問い合わせして返してくれるプロキシのようなものらしい。

実際のDNSサーバは以下のコマンドで調べられる

$ systemd-resolve --status
...
  Current DNS Server: 169.254.169.254
...

このIPアドレスGCPVPC上にあるメタデータサーバを示すアドレスである。メタデータサーバはインスタンスの情報、リージョンやら何やらを取得するためのサーバだが、GCPではこれがDNSを兼ねているようだ。

なおAWSやAzureも同じIPアドレスメタデータサーバに使っているらしい。このアドレスに特殊な意味はないのでおそらくどれかがどれかを真似したのだろう。ただAWSDNSサーバはこれではなく、ネットワークアドレス+2(ネットワークアドレスが10.0.0.0/8ならば10.0.0.2)となっているそうだ。

で、resolverに何指定すればいいのか、の件については、127.0.0.53169.254.169.254の好きな方を指定すればいいと思います。なおTTLは30秒になっています。