LoginSignup
16
19

More than 5 years have passed since last update.

AWS-cli + route53でElasticIPを節約したお話

Posted at

この記事はリクルートライフスタイル Advent Calendar 2015 の20日目です。
ホットペッパービューティーで開発陣の周りをお手伝いしている、岡田賢治です。

はじめに

RLSにお世話になりまして、約半年が過ぎました。元は、オンプレサーバのサバ管で、いろいろスクリプトを書いていました。
こちらの環境で、AWSで作業することが非常に多くなりました。AWSは全くの素人だったので、ググりながらの日々が続きました。

作業内容としては、主にサーバの構築。サービスを提供するものや、サービスの検証・サービスのミラー等、様々なサーバを用意します。
サーバのインスタンスが増えるに当たり、増えるものと減るものが出てきます。

増えるもの

 インスタンス数
 ディスクの使用量

減るもの

 ElasticIPの残り数

Elastic IP

AWSを利用するに当たり、最初に面食らったのがElasticIPでした。インスタンスの設定では、内部管理のプライベートIPの他、外部からアクセスできるグローバルIPを割り当てることが出来ます。
しかし、このグローバルIPはインスタンスの起動毎に変わるIP=Public IPになります。
「どうやれば固定できる・・・」で、発見したのがElasic IP(の使用方法)でした。

減ってゆくElastic IPの残り

Elastic IPは、有償でAWSから借り受けるものであり、どの利用者も無尽蔵に利用できるというわけではないと思います。もちろん正式サービスに利用するのであればいいのですが、当方のように「検証環境」とか「ミラー環境」を用意する身としては、常に在庫があるわけではありません。
すると何が始まるか・・・?検証環境のインスタンスを起動するたびに、Route53へAレコードを登録しなくてはいけなくなります。それを忘れて「繋がらない・・・」とハマったことも何度も・・・

要は何ができればいいの?

そもそもElastic IPを利用する理由は「インスタンス起動時に常に同じIPが割あたっている保証がほしい」からなわけです。
なぜ保証がほしいか?といえば「DNS(のAレコード)に、そう登録してあるから」なわけです。

ここでひらめいたのが、AWSのWebAPIを利用する方法です。
・そのインスタンスに割り振られたPublic IP(≠Elastic IP)は、取得ができる。
・DNS/Route53のAレコードは、WebAPIにより登録ができる。

となれば、「常に同じIPじゃなくても、起動時に割あたったPublic IPがそのままRoute53に登録してあるFQDNに割あたってくれればいいんじゃね?」となります。

スクリプトへの反映

そこで考えたスクリプトが以下の2つです。

r53.sh
#!/bin/bash

export PATH=/usr/local/sbin:/usr/local/bin:${PATH}

#変数設定
INSTANCEID=XXXXXXXXX
HOSTEDZONEID=XXXXXXXXX


# PublicIPが有効になるまで2分待つ
sleep 120 ;

cd /root

# AWS CLIを使って、PublicIPを取得
PUBLICIP=`aws ec2 describe-instances --instance-ids ${INSTANCEID} | jq ".Reservations[0].Instances[0].NetworkInterfaces[0].PrivateIpAddresses[0].Association.PublicIp"`

#PublicIPは、"XXX.XXX.XXX.XXX"の形式なので、XXX.XXX.XXX.XXXに変換する
PUBLICIP=`echo ${PUBLICIP} | sed -e 's/"//g'`

# 設定ファイルset.jsonを削除
if [ -f set.json ]; then
        rm set.json ;
fi

# テンプレートファイルを元にset.jsonを作成
sed -e "s/PUBLICIP/${PUBLICIP}/" set.json.tmpl > set.json

# Route 53情報を書き換える
aws route53 change-resource-record-sets --hosted-zone-id ${HOSTEDZONEID} --change-batch file://set.json

exit ;

ここでは、
- 16行目でaws ec2 describe-instancesコマンドを利用して、対象インスタンスの情報を取得しています。対象インスタンスは6行目で指定したINSTANCEIDに設定したインスタンスIDです。
- ただしそのコマンドでは、起動直後にはインスタンス情報を取得できません(正確には、PublicIPが割当たるまでの時間差の関係で、PublicIPが取得できません)。有効になるまで一定時間待つ必要があります。ここでは120秒=2分としました(11行目)
- JSON形式で値が返りますので、jqコマンドとsedを使ってCIDR形式のIPアドレスに変換します(19行目)。
- AWS Route53に送るJSONデータを作成します(26行目)。テンプレートファイルset.json.tmplを元にして、set.jsonファイルを作成しています。
- 出来上がったset.jsonファイルを使って、Route53の情報を書き換えます(29行目)。

次にテンプレートファイルset.json.tmplですが、

set.json.tmpl
{
  "Comment": "create A record",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "XXXX.YYYY.ZZZZ.",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "PUBLICIP"
          }
        ]
      }
    }
  ]
}
  • Route53に登録するFQDNは"XXXX.YYYY.ZZZZ"です。
  • PUBLICIPの文字列が、r53.shの中のsedコマンドでCIDR形式のIPアドレスに置き換わります(r53.sh:29行目)。

補足情報

上記スクリプトを動かすには、以下の条件が必要です。
- AWSのコマンド操作ツール群、aws-cliがインストールされていること。
- jqがインストールされていること。
- AWS/EC2に、インスタンスの情報取得が可能であるアクセス権(キー・シークレットキー等)を保持していること。
- AWS/Route53に、更新可能なアクセス権とそれに付随するHOSTZONEID情報を保持していること。

まとめ

プログラミングやら何やらいろいろやっていますが、自分のプログラミングの起源はUNIX/Linuxのサーバ管理で使った、スクリプト群が起源であることを最近痛感しています。
最近では、それがWebAPI/RestAPIになったりJSON形式が出てきたり、DevOpsという言葉が生まれたりと、昔を懐かしんでばかりもいられないな、というのが実情です。
仕事では、引き続き他のツール群との連携を取っていくつもりです。
プライベートでは・・・OpenStackをやっているので、AWSの比較をAPIを含めながら行っていきたいな、と考えています。

長い文章を読んでいただき、ありがとうございました。それでは。

16
19
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
16
19