年中アイス

いろいろつらつら

Roadworkerを使ってRoute53 Private DNSを管理する

Roadworkerとは

Route53の設定を、DSLで管理するruby製のツールです。ドメイン設定をコード化できるので、gitで管理することができます。

winebarrel/roadworker · GitHub

Route53 private DNSとは

2014年の11月ごろから使えるようになった機能です。

特定のVPC内からのみ応答するdomainを設定することができます。VPC内からは、任意の名前で対象を指定できます。 ec2で最初から割り当てられるprivate DNSは、ローカルIPアドレスが含まれているので、DBサーバといった役割の名前として使えませんでした。

ちなみに少しお金かかります。public/private変わらずな感じ。 ホストゾーンは、0.50USD/1ホストゾーン月と、標準リクエスト0.40USD/最初の10億リクエストまで月

料金 - Amazon Route 53(ドメインネームサーバー― DNS サービス) | アマゾン ウェブ サービス(AWS 日本語) 他、細かい説明がありますが、1USD/月ぐらいで試すのはできるようです。

Roadworkerのinstall

sudo gem install roadworker

入ったのは、0.5.4でした。 ここでは、AWSの接続用のトークン設定の説明は省きます。環境変数で指定するか、Credentialでも動きます。

試してみる

Private DNS用のHostedZoneの作成

AWSコンソールにログインして、Route53 > HostedZones > [Create Hosted Zone]

項目
Domain name 設定したいHostedZone名、ここでは、private.local
Comment 説明とか
Type [Private Hosted Zone for Amazon VPC]を選択
VPC ID 設定するDNSを使えるVPCのID(選択肢が出ます)

これでprivate.localというPrivate domainが作成されました。画面上末尾に.がついてprivate.local.となりますが大丈夫です。

gitで管理する準備

gitで管理するため、専用のディレクトリを作ります。

mkdir route53
cd route53
git init

現在の設定をexportする

exportは、-eまたは--exportを指定します。 HostedZoneごとにファイルが分かれる方が管理しやすいので、--splitを指定します。

roadwork -e --split

以下2種類のファイルが作成されます。

  • Routefile
  • private.local.route

Routefileは、HostedZoneごとのrouteファイルを読み込んでいるだけです。

# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'private.local.route'
# 複数あればここにrequireが増えます。

private.local.routeに、domainごとの設定が出力されています。

# -*- mode: ruby -*-
# vi: set ft=ruby :
hosted_zone "private.local." do
  vpc "ap-northeast-1", "vpc-XXXXXXXX"

end

gitで記録する

git commit -a -m 'stored route53 routings.'

編集する

一つドメインを追加してみます。vpcの行の後に以下のように追加します。シンプルなaliasレコードです。 10.0.0.10というPrivateIPにdb.private.localというdomainを割り当てます。

# -*- mode: ruby -*-
# vi: set ft=ruby :
hosted_zone "private.local." do
  vpc "ap-northeast-1", "vpc-XXXXXXXX"

# --ここから
  rrset "db.private.local.", "A" do
    ttl 300
    resource_records(
      "10.0.0.10"
    )
  end
# --ここまで

end

DSLわからないときは、AWSコンソールから作って、exportするのが早いです。domainの末尾にある.は省略しても勝手にあるものとして扱われます。exportした方は、末尾に.が付いているので、つけた方がexportと合わせられていいと思います。 gitで管理していれば、何かあっても戻せますし、差分も見やすいです。*1

適用する

-aまたは--applyを指定すると適用できます。まず必ず--dry-runをつけて、適用対象を確認しましょう。 *2

roadwork -a --target-zone private.local --dry-run

新規はCreate(青文字), Update(黄文字), Delete(赤文字)という接頭語で対象が羅列されます。以下簡単な例です。

# 追加
Create ResourceRecordSet: db.private.local A (dry-run)

# 変更
Update ResourceRecordSet: <変更するdomain> A (dry-run)
  set resource_records=[{:value=>"<新しいIPとか変更情報>"}] (dry-run)

# 削除
Delete ResourceRecordSet: <消すdomain> A (dry-run)

変更対象を確認したら、--dry-runを外して実行します

roadwork -a --target-zone private.local

確認

対象のVPCにあるインスタンス上で、dig db.private.localとすると、DNSの応答があります。

# 前後省略
;; ANSWER SECTION:
db.private.local.   300 IN  A   10.0.0.10

HostedZoneの削除

そんなにやる機会はないかもしれませんが、HostedZoneを削除するときは、Routefileから対象のHostedZone(require行)を消します。 ただし、applyしようとすると、そのままでは消せずに、警告がでます。

Undefined HostedZone (pass `--force` if you want to remove): private.local. (dry-run)

--forceをつけると、HostedZoneの削除も出来きます。--force --dry-runとすると、force状態でのdry-runが可能です。

Apply `Routefile` to Route53 (dry-run)
Delete HostedZone: private.local. (dry-run)

現状と比較する

-tまたは--testを使って、現在のDSLと、実際のDNS問い合わせ結果が同期した状態かを確認できます。 Aliasレコードでは完全ではないようで、おそらく

  • 同じドメイン複数のIPを割り当てる場合、実際にDNSから返ってくるのはランダムに1つ
  • そのため、一致しない別のIPが返ってくると失敗する。
  • またPrivate DNSは、そもそもVPC内からのみ有効なので、外からは応答なく失敗となる

なのでこの-tは、それを踏まえて使う必要があります。PrivateDNSは、もし確認するのであれば、VPC内のインスタンス上でRoadworkerを動かせば確認できると思いますが、前述の失敗条件もあるので、気をつける必要があります。

まとめ

Route53は、AWSコンソールのUIが少し微妙なので、謝って別の行を変更してしまうことが、ごく稀にあります(ありました)また、変更の履歴はないので、誰がいつやったかはわかりません。*3事前にコード化しておくと、どんな変更がいつあったか記録でき、適用前に確認もでるので、事故を防止したり、万が一何かで消えたときに復旧することもできます。

参考

*1:ローカルで編集して、git commitする前にexportすると消えるので、注意してください。

*2:個人的には、--target-zoneを使ってHostedZoneも指定して適用します。複数のHostedZoneがある場合に、万が一、他のZoneに不必要な影響があっては困るので、対象のzoneに絞ります。

*3:2015/3/8現在、CloudTrailの対象にまだない様子。AWS CloudTrail ( AWS API の呼び出し記録、ログファイル送信)| アマゾン ウェブ サービス(AWS 日本語)