はじめに
マルチクラウドの環境おいてGCPのCompute EngineからVPN接続されたAWSのRoute53のPrivate DNSで名前解決を行い、AWS EC2のインスタンスへアクセスする設定について記載していきます。
この記事ではGCPとAWSの設定がすんでいることを前提としています。VPNの設定に関しては以下の記事が参考になるかと思います。
問題点
GCPとAWSのVPNの設定を行い、いざEC2とGCE間での通信行おうとして、とりあえずpingで接続確認。IPでの接続確認はVPN設定で当然行えるのだけれど、ドメインでの接続確認が...
ping: <ホスト>: Name or service not known
上記ドメインの名前解決はAWSのRoute53のPrivate DNSに設定されていて、そこで名前解決されていない様子。ちなみにPublic DNSだと問題なく名前解決を行い接続確認が行える(当たり前だけど...)。
これは色々面倒臭そう...
AWS側の設定
まずRoute53のPrivate DNSは、対象のVPCネットワーク内でなければ参照が行えない。そのためにVPC外からPrivate DNSを参照するには、ひと工夫することが必要になってきます。以下の記事を参照すると、いくつかの方法はあるのだけれども、今回は一番簡単に出来そうなAWS Directory Service Simple AD経由で名前解決を行う方法を採用しました。
Directory Service Simple ADを利用してのPrivate DNSでの名前解決の方法はAWS Directory Service(Simple AD)を利用したオンプレミスからのPrivate Hosted Zone名前解決が参考になります。
AWSのDirectory Serviceから「ディレクトリのセットアップ」を行います。ディレクトタイプの選択で[Simple AD]を選択。
次にディレクトリの情報を入力しますが、ポイントとしてはディレクトリのDNS名を、Private DNSで設定されたドメインメイトは異なるドメイン名を入力します。
あとはVPCとサブネットの指定を行い、ディレクトリの作成を行います。
作成されたディレクトリの詳細情報を参照すると、ディレクトリに対してDNSアドレスが設定されていることが確認出来ます。VPC外のホストから、このアドレスに対してDNS名前解決を行うとPrivate DNSに設定された内容で名前解決行うことが出来ます。
試しにGCE上から以下のようにDNS指定で名前解決を行うと成功知ることが確認出来ます。
# nslookupの第2引数でDNSアドレスを指定する。
$ nslookup <ホスト> 172.31.46.186
Server: 172.31.46.186
Address: 172.31.46.186#53
Non-authoritative answer:
Name: <ホスト>
Address: 172.16.15.146
AWS側の設定はこれでOK!
GCE側の設定
次にGCE側の設定を行なっていきます。今回はGCEのブートイメージとしてDebian GNU/Linux 9 (stretch)
を前提に説明を行います。
DNSサーバのIPアドレスがわかっているんだから、あとはresolv.conf
に追記してあげればOKかなと思っていましたが...
以下を参照すると
デフォルトでは、ほとんどのLinuxディストリビューションがDHCP情報をresolv.confに格納しています。Compute Engineの各インスタンスは、DHCP リースを 24 時間ごとに更新するように設定されています。ゾーン DNSに対して有効化されているインスタンスの場合は、DHCPリースは 1 時間ごとに期限切れとなります。DHCP更新によってこのファイルが上書きされるため、それまでに行われた変更が元に戻されます。
あれ、直接書いちゃいけないってこと?
それからの四苦八苦を省略し、色々と調べた結果DHCP側の設定ファイル/etc/dhcp/dhclient.conf
を変更しなければいけないことが分かりました。
/etc/dhcp/dhclient.conf
を覗いてみると以下のような感じでDHCPへのリクエスト設定を行なっています。
・・・
send host-name = gethostname();
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, domain-search, host-name,
dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
netbios-name-servers, netbios-scope, interface-mtu,
rfc3442-classless-static-routes, ntp-servers;
・・・
このHDCPへのリクエスト結果に対して、resolv.conf
へDNSの追加を行うには、設定ファイルに対して以下を追加すればOKです。指定するIPアドレスはSimple ADのDNSアドレスとなります。
prepend domain-name-servers 172.31.46.186;
prepend domain-name-servers 172.31.6.6;
あとはネットワークの再起動。
$ sudo service networking restart
再度nslookupでの確認(DNS指定なし)を行なってみると、無事に名前解決が行えるようになりました。
$ nslookup <ホスト>
Server: 172.31.46.186
Address: 172.31.46.186#53
Non-authoritative answer:
Name: <ホスト>
Address: 172.16.15.146
/etc/resolv.conf
も見てみると、DNSサーバの追加が無事にされていることが確認できます。
$ cat /etc/resolv.conf
domain c.<プロジェクト名>.internal
search c.<プロジェクト名>.internal. google.internal.
nameserver 172.31.6.6
nameserver 172.31.46.186
nameserver 169.254.169.254
おまけ
GCEにはインスタンス起動時の独自のスクリプト実行として、起動スクリプトの仕組みがあります。
起動スクリプトして今回DNSの追加処理を行うと便利です。インスタンス作成時の「管理」->「自動化」->「起動スクリプト」の欄に、実行するスクリプトを記述することで、実行することができます。
今回は以下のスクリプトを記載することで、起動時のDNSサーバの設定を行うことができます。
echo 'prepend domain-name-servers 172.31.6.6;' >> /etc/dhcp/dhclient.conf
echo 'prepend domain-name-servers 172.31.46.186;' >> /etc/dhcp/dhclient.conf
sudo service networking restart
Google Cloud Storage上のファイルを起動スクリプトとして実行することもできるので、興味ある方はチャレンジしてみてください。
終わりに
今回はVPN接続されたAWSとGCPの環境に置いて、GCEからRoute53のPrivate DNSにおける名前解決方法について記載しました。
今後はGKEなどからも検証していけたらいいかな。