AWS App Runnerでプライベートホストゾーンの名前解決ができるのか確認してみた

2024.06.15

しばたです。

先日同僚より「AWS App RunnerでVPC Connectorを使いユーザーVPCに接続した場合、そのVPCと紐づくプライベートホストゾーンの名前解決はできるのか?」という質問を受けました。

ドキュメントを一通り探しても明確な情報を見つけることができなかったので実際に試してみることにしました。

検証環境

前に入門記事で紹介したサンプルアプリケーションを改修し、コンテナからDNS設定の参照とクエリの実行ができる様にしました。

(追加したDNS関連機能)

DNSの操作にはdnspythonを使っています。
この機能を使いVPC Connectorの有無でどの様に挙動が変わるかを検証します。

検証環境は下図の様に東京リージョンにApp RunnerサービスとユーザーのVPC(191.168.12.0/24)を用意し、さらにプライベートホストゾーン(shibata.internal)をこのVPCと紐づけています。

プライベートホストゾーン(shibata.internal)にはテスト用のAレコードhost1.shibata.internalを設定済みです。

各リソースの構築手順は割愛します。

検証結果

ここからは実際の検証結果となります。

1. VPC Connectorを使わない場合

まずはVPC Connectorを使わない場合から試していきます。

App RunnerのサービスはAWSマネージドなVPC上で動作しており、ユーザーVPCとのつながりも一切ないためプライベートホストゾーンの名前解決は出来ないはずです。

アプリケーションをデプロイしDNS設定画面(/dns/)を開くとこんな感じの結果になりました。

コンテナ内部のresolv.conf

resolv.conf (VPC Connector未使用)

nameserver 10.0.0.2
search ap-northeast-1.compute.internal

となっており、デフォルトで使うDNSサーバーは10.0.0.2となっています。
このアドレス帯はAWSマネージドなVPCのものです。

コンテナ内部のECSタスクメタデータからもネットワーク情報を可能で、こちらでも全ての設定で"DomainNameServers"10.0.0.2になっていることが分かります。

タスクメタデータ (VPC Connector未使用)

{
  "DockerId": "580cf90045a74622b2c17931e02f3165-193386898",
  "Name": "instance",
  "DockerName": "instance",
  // ・・・中略・・・
  "Networks": [
    {
      "NetworkMode": "awsvpc",
      "IPv4Addresses": [
        "10.0.180.84"
      ],
      "AttachmentIndex": 0,
      "MACAddress": "0e:83:b3:5e:cb:25",
      "IPv4SubnetCIDRBlock": "10.0.160.0/19",
      "DomainNameServers": [
        "10.0.0.2"
      ],
      "DomainNameSearchList": [
        "ap-northeast-1.compute.internal"
      ],
      "PrivateDNSName": "ip-10-0-180-84.ap-northeast-1.compute.internal",
      "SubnetGatewayIpv4Address": "10.0.160.1/19"
    },
    {
      "NetworkMode": "awsvpc",
      "AttachmentIndex": 2,
      "DomainNameServers": [
        "10.0.0.2"
      ],
      "DomainNameSearchList": [
        "ap-northeast-1.compute.internal"
      ]
    }
  ],
  "LastRestartAt": "0001-01-01T00:00:00Z"
}

この状態でhost1.shibata.internalに対して名前解決をしても「結果なし」になります。

None of DNS query names exist: host1.shibata.internal., host1.shibata.internal.ap-northeast-1.compute.internal.

もちろんパブリックなゾーンに対しては普通に名前解決可能です。

(DevelopersIOに対する名前解決はふつうにできる)

2. VPC Connectorを使った場合

次にVPC Connectorを使った場合の動作を確認します。

ユーザーVPC(192.168.12.0/24)に接続するVPC Connectorを新規作成しApp Runnerサービスで使う様に設定変更します。

しばらく待つと設定変更が完了し、これでApp Runnerからのアウトバウンド通信はVPC Connectorを経由することになります。

設定変更が完了した後でDNSの設定を確認すると下図の様にユーザーVPCのDNSサーバー(192.168.12.2)を使う様に変わっていました。

resolv.confの内容も変わっています。

resolv.conf (VPC Connector利用時)

nameserver 192.168.12.2
search ap-northeast-1.compute.internal

ECSタスクメタデータはこんな感じで、VPC Connector用と思しき新しい設定(AttachmentIndex = 1 のもの)が増え、これがDNSサーバー192.168.12.2を使う設定となっていました。

タスクメタデータ (VPC Connector利用時)

{
  "DockerId": "e8f47b1a76344f1eb63e0b6b86ed475f-193386898",
  "Name": "instance",
  "DockerName": "instance",
  // ・・・中略・・・
  "Networks": [
    {
      "NetworkMode": "awsvpc",
      "IPv4Addresses": [
        "10.0.112.51"
      ],
      "AttachmentIndex": 0,
      "MACAddress": "0a:78:2d:fe:09:27",
      "IPv4SubnetCIDRBlock": "10.0.96.0/19",
      "DomainNameServers": [
        "10.0.0.2"
      ],
      "DomainNameSearchList": [
        "ap-northeast-1.compute.internal"
      ],
      "PrivateDNSName": "ip-10-0-112-51.ap-northeast-1.compute.internal",
      "SubnetGatewayIpv4Address": "10.0.96.1/19"
    },
    {
      "NetworkMode": "awsvpc",
      "IPv4Addresses": [
        "169.254.175.252"
      ],
      "AttachmentIndex": 1,
      "MACAddress": "8e:42:07:f3:e7:87",
      "IPv4SubnetCIDRBlock": "169.254.175.252/31",
      "DomainNameServers": [
        "192.168.12.2"
      ],
      "DomainNameSearchList": [
        "ap-northeast-1.compute.internal"
      ],
      "SubnetGatewayIpv4Address": "169.254.175.253/31"
    },
    {
      "NetworkMode": "awsvpc",
      "AttachmentIndex": 2,
      "DomainNameServers": [
        "10.0.0.2"
      ],
      "DomainNameSearchList": [
        "ap-northeast-1.compute.internal"
      ]
    }
  ],
  "LastRestartAt": "0001-01-01T00:00:00Z"
}

コンテナがVPCのDNSサーバーを使う設定になっているので、プライベートホストゾーンに対する名前解決も問題なく可能でした。

いい感じですね。

追記 : DHCPオプションセットの影響は受けない

記事を公開した後に「VPC Connector接続先VPCのDHCPオプションを変えたらどうなるのだろうか?」と気になり試してみましたが、App Runnerサービスが参照するDNSサーバーの設定は変わりませんでした。(resolv.confも変化せず)

App RunnerでVPC Connectorを使う場合はDHCPオプションセットの影響は受けず、VPCデフォルトのRoute 53 Resolver(旧AmazonProvidedDNS)を使います。
このためApp Runnerを使いつつ任意のネームサーバーを設定することはできない感じです。

ただ、実際に試してはいませんが、今回使用したdnspython等のプログラムで直接ネームサーバーを指定する形であれば代替できると思います。

# 実際に試してはいないが、こういうコードなら任意のネームサーバーを使えるはず
import dns.resolver

# プログラムコード内でネームサーバーを指定して代替
resolver = dns.resolver.Resolver()
resolver.nameservers = ['xx.xx.xx.xx', 'yy.yy.yy.yy']
answers = dns.resolver.resolve('hostname.yourdomain.internal', 'A')

最後に

以上となります。

調べ始めた当初は「VPCも分かれるし名前解決は難しいんじゃないか?」と予想していたのですがいい意味で裏切られました。
VPC Connectorを使った場合はApp RunnerのサービスがあたかもユーザーVPCにあるかの様に考えて大丈夫だと思います。