LoginSignup
7
8

More than 5 years have passed since last update.

[小ネタ] Route53 + CloudWatch Events + Lambda + Tagsを使って簡易DDNSを作る

Last updated at Posted at 2016-05-31

自社でDIY的に作った仕組みが案外好評だったので記事にしてみました。

面倒くさいからとりあえずEIP使う を無くしたいだけだった

開発や検証用途でAWS上にInstanceを立ち上げた時、とりあえずブラウザにIP直打ちしたり、とりあえずSSHもconfig使わずにIP直打ちしてしまう経験ありませんか??
私は壮絶にございました。

  • Public IPはInstanceを起動する度に変わるから、とにかくやってられなくてEIP使っちゃう
  • EIPは別に1個ならInstance起動中は0円だけど、停止してベッドでぐっすり寝てる時はじわじわ料金キテる。チリツモ
  • Public IP変わってもDDNS的にドメインを自動的にアップデートしてくれるような仕組みがあればEIPなんぞ使わなくてもいいんだけど…

一般的な実現方法

前述したようなケースの場合、これまではEC2の「user-data」などを使ってcloud-initやシェルスクリプトでInstanceの作成/起動時にRoute53のレコードをUPSERTするような手法が一般的だったと勝手に解釈しています。

[参考:クラスメソッドさん]
cloud-initを使ってRoute53をPrivate Dynamic DNSにする
http://dev.classmethod.jp/cloud/aws/route53-private-dynamic-dns-use-cloudinit/

Jenkinsを導入したEC2インスタンスに常に同じ名前でアクセスする
http://dev.classmethod.jp/cloud/jenkins-ec2-name-upsert/

上記の例は多くの場合に役立ちますが、1つ問題があります。

リソースが削除された時に、ドメインが削除されないという点です。

スクリプトがInstance内部にある場合はTerminate時にレコードを消す事は容易ではありません。
そこで今回はこれを解決するために、今年の初めにアップデートされた「CloudWatch Events」とみんな大好きLambdaを使ってこの問題を解決したいと思います。

CloudWatch Events とは

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/DeveloperGuide/WhatIsCloudWatchEvents.html
http://aws.typepad.com/aws_japan/2016/01/new-cloudwatch-events-track-and-respond-to-changes-to-your-aws-resources.html

詳細は上記のドキュメントを見てみてください。
何が嬉しいかと言うと、これまでEC2 Instanceのリソース状態の変化をシンプルに検知するにはCloudTrailなどを使うしかなかったのですが、CloudTrailはログが書き出されるまでに結構な時差があり、リアルタイムに検知することはできませんでした。

例. あるEC2のステータスがPendingからrunningに変わったのをトリガーに、すぐに任意の処理を走らせたい

これを見事に解決してくれるのがCloudWatch Eventsです。
EC2 Instanceであれば、
Pending, Running, Stopping, Stopped, Terminated
などの各状態変化をリアルタイムに検知して、
Lambda, SNS, SQS, Kinesis, Built-in traget
などにイベントを流す事ができます。

スクリーンショット 2016-06-01 3.55.35.png

上記の画像は全てのInstanceを対象として状態が「Terminated」、「Running」になった際に、Lambdaファンクションを発火させる設定例です。設定は、CloudWatch -> Events -> Rules からルールを作成していきます。

Lambdaファンクションには、

{
  "id": "ee376907-2647-4179-9203-343cfb3017a4",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2015-11-11T13:30:34Z",
  "region": "us-east-1",
  "resources": [
    "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111"
  ],
  "detail": {
    "instance-id": "i-abcd1111",
    "state": "running"
  }
}

のようなイベントが渡されるため、あとはLambdaから焼くなり煮るなり好きにすることができます。
今回の主目的は脱EIPでしたが、Route53のプライベートホストゾーンにも簡単に応用することができます。

Labmda内での処理

さて、前述までの部分でLambdaにInstanceの状態変化をリアルタイムに伝える事ができるようになったので、後はLambdaで好きにコードを書いて処理するだけです。

観点としては、

  • Instanceの作成/起動時にはInstanceのTagsを見て、Nameをドメイン名のprefixとして任意のAレコードをUPSERTで登録する
  • Instanceの削除(停止を含めてもよい)時には、その逆にレコードを削除する処理を書く

ただ、注意点としては現状のCloudWatch Eventsのルールではあくまでもリージョン内全てのInstance or 特定のInstanceしか対象にできないので、
上記を参考に実装するとDDNSをする必要の無いInstanceまで不要なレコードが追加されてしまいます。

そこで、個人的にオススメしたいのは、ドメインのprefixとしてInstanceのNameを使うのではなく、
任意のTagを1つルール決めしておいて、Lambdaファンクション実行時に、そのInstanceにDDNS設定用のTagがある/ない を基準に処理を続ける/止める という風にするのが良いと思います。

具体的には、下記のようなイメージです。
スクリーンショット 2016-06-01 4.14.10.png
この場合、Lambdaからタグ名「Domain」の存在を確かめる事で、レコードの追加の必要有無を判断できます。

その他

いかがだったでしょうか。小ネタ中の小ネタですみません。
自社ではこれらの仕組みを使って、ドメインが必要な場合は構築時にTagを追加するという運用ルールを決めることで自動化を取り入れました。

プライベートホストゾーンにも簡単に応用できるので、
例えばTerraformでの構築時にTagを設定するだけで内部DNSの設定自動化までサクッと出来たりすると思います。

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8