LambdaでRDSを定期的にスケールアップ・ダウンさせてみた
概要
普段はmicroインスタンスで十分だけど、重いSQLを実行するときだけsmallにしたいという要件を満たすために、 Lambdaを使ってサーバレスでRDSを定期的にスケールアップさせてみました。
ここではスケールアップする方法のみ記述してますが、業務時間終了後またmicroに戻す処理も実装してコストの上昇を最小限に止めてみました。
設定
Lambda
AWS-Services-Lambdaで「Create a Lambda Function」をクリック。
ひな形になる「hello-world-python」を選択。
「Name」をScaleUpReadDB
とし、「Runtime」にはpython 2.7
を選択。
肝心の「Lambda function code」はEdit code inlineで直接下記のコードを入力しました。
import boto3 def lambda_handler(event, context): client = boto3.client('rds') response = client.modify_db_instance( DBInstanceIdentifier='readonlyrds', DBInstanceClass='db.t2.small', ApplyImmediately=True ) print response
readonlyrds
は実際にスケールアップさせたいRDSの名前です。ちなみにApplyImmediately=True
を指定しないとコマンドは成功しても変更が即時反映されないため気を付けましょう。
「Role」では「Basic execution role」を新規で作ります。詳細については次のIAM roleで述べます。
また「Timeout」はデフォルトで3sとなってますが、時々3秒以内に処理が終わらずエラーとなるので10s
を設定しました。
IAM role
Lambda Function作成時にBasic execution roleを新規作成すると下記の画面に移りますので「Hide Policy Document」をeditして適切な権限を付与します。
今回は下記のような感じにしてみました。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "rds:*", "cloudwatch:DescribeAlarms", "cloudwatch:GetMetricStatistics", "ec2:DescribeAccountAttributes", "ec2:DescribeAvailabilityZones", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeVpcs", "sns:ListSubscriptions", "sns:ListTopics", "logs:DescribeLogStreams", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:GetLogEvents" ], "Resource": "arn:aws:rds:ap-northeast-1:xxxxxx123456789:db:readonlyrds" } ] }
IAM roleを作成するとLambda作成画面に戻るので、そのままnextをクリック、詳細確認して作成。
Lambdaのcron実行指定
Lambdaは作成しただけでは実行されないので、cronで実行時刻を指定します。 作成したLambdaの「Event Sources」で「Add event source」をクリック。 「Event source type」で「CloudWatch Events - Schedule」を選択すると下記のようなダイアログが出現するので設定して「Submit」して終了。
上の例では月曜日から金曜日の日本時間の朝9時1分(UTC 0:01)にLambda Functionが実行されます。
あとがき
やってみると意外と簡単だなというのが正直な感想です。普段コードを書かないインフラエンジニアでもワンパス通せば雰囲気も掴めて、いろんな事に応用できそうだと思ってもらえるはずです。
StatusCakeからslackにアラートを飛ばしてみる
概要
URL監視を手軽にする際にStatusCakeは便利です。設定は簡単だし、監視対象URL数もフリープランで20個以上軽く行けますし。 今回はStatusCakeからslackにアラートを飛ばしてみようとした際にしょうもないところでハマったのでソレについて述べます。
slack側設定
いつものように通知先のchannelのwebhookを用意します。(今回は割愛します)
StatusCake側設定
Contacts - Integrations
アラート送信先として外部サービス(slack)を登録します。 ContactsのIntegrationsで[ADD NEW 3RD PARTY SERVICE]でslackを選択して上の図のようにwebhookを設定。 この時[Alias]を設定しないと後でアラート送信先としてslackが選択できなくなるので注意です。
Contacts - Create Groups
アラート送信先を実際に設定します。
グループ名を適当に設定し、アラートの飛ばし先としてEmailとslackを設定しますが、slackの設定はwebhook、、、ではなく[Push Notifications]欄をクリックすると先ほどIntegrationsでaliasに設定した名前が選択できます。(自分はここでハマりました)。
Tests - New Test
最後に監視対象URLを設定します。
設定項目は一目瞭然なので割愛します。Contact Groupに上で作成したグループを選択して終了。
実際に障害を疑似的に起こしてテストしてみると
ちゃんとslackに通知されました。
Google Developers Launchpadで$100,000 GETした時の思い出
概要
Google Developers Launchpadに選出され$100,000 GETした時の流れを簡単にまとめました。
自分たちがGoogle Developers Launchpadに挑戦した時(2015/4)と状況が変わっているので、今はちょっと違うかもしれませんが誰かの参考になればイイなと。
流れ
2015/4
- Google Developers Launchpadの情報をキャッチ。
- androidアプリ開発のアドバイス、GCPの$100,000 credit、等々魅力的な特典満載なのでダメもとで応募することに。
- 会社情報やサービス内容など必要情報を整理してwebフォームから応募。
2015/5
We are happy to welcome <company_name> to Google Developers Launchpad program.
みたいなメールが来て、めでたく参加決定。やったー!- 再度、Google Cloud Credits($100,000)を貰うため会社規模や売上げ額などの情報を求められるので、フォームに入力。
2015/6
- 前のフォーム入力はなんか上手くいかなかったので、もう一度より詳しい情報(公開してるアプリ情報、開発言語、GCPで使いたい機能)を入力せよ!とメールが来る。
- フォームに入力すべきIDなど不明箇所があったのでメールで質問する。そのやりとりの中で
but please know that not every startup receives the credits
と言われ激しく意気消沈。 - とりあえず必要事項を全て入力して様子を見守る。
2015/7
You will have the opportunity to speak directly 1:1 with GCP for Startups program manager and Solution Architect
みたいなメールが来て最終面談へ。実際は米国の昼時間帯にビデオハングアウト。つまり日本時間深夜にビデオハングアウト。偉い外人さんと英語でビデオハングアウトォーーorz- アジェンダとか特に言われませんでしたが、間が持たないんじゃないかと不安だったのでプレゼン資料を事前に先方に共有しておきました。
- 実際のMTG時間は1時間ほど。
- 先方からGoogle Developers Launchpadの簡単な説明後、こちらから現在やってるサービスとそれを支える技術の説明。グローバル展開してるところをアピールしてみました。
- 質疑応答。
- ビデオハングアウトの最後で「OK, Google Cloud Creditsを受け取りたまえ」みたいな話になって無事終了。
2015/8
Accepted - Welcome to Google Cloud Platform for Startups
という題名のメールが到着。内容は下記の通りで、「Redeem now」をクリックすると自動的に$10,000づつ振り込まれていきます。
2015/9
- 実際に「Redeem now」をクリックしてcreditsをもらい始める。以後、google developer consoleのホーム画面の請求は
$0
のまま。
2015/10
- GCPにインフラの大半を引っ越して実運用開始。
その他
Shinjuku.rb #33 でspot instanceについてLTさせてもらった時の資料
概要
Shinjuku.rb #33 ではLTのお題目に縛りが無かったのでインフラっぽいことを喋らせてもらいました。
資料
ubuntuでセキュリティアップデートを自動で行う。
概要
unattended-upgradesを導入してdpkgで管理されてるアプリのセキュリティアップデートを自動で行います。
インストール
apt-get install unattended-upgrades
設定
/etc/apt/apt.conf.d/50unattended-upgradesの下記のコメントアウトを外す
Unattended-Upgrade::Automatic-Reboot "false";
sudo dpkg-reconfigure -plow unattended-upgrades
YESを選択
unable to resolve hostのエラーを抑制する。
概要
sudoコマンドを実行した際などホスト名が解決できないと
sudo: unable to resolve host
と出力されますが、ウザいので抑制したいです。
対処法
下記のスクリプトで起動時にhostnameを/etc/hostsに追記する。
-------------- #! /bin/sh ### BEGIN INIT INFO # Provides: rc.boot # Required-Start: $all # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: # Short-Description: Run /etc/rc.boot if it exist ### END INIT INFO do_start() { echo "127.0.0.1 `hostname`" >> /etc/hosts ##su - ubuntu -c 'cd /home/ubuntu/taptrip2;bundle exec cap ROLES=app local_staging deploy' return 0 } case "$1" in start) do_start ;; restart|reload|force-reload) echo "Error: argument '$1' not supported" >&2 exit 3 ;; stop) ;; *) echo "Usage: $0 start|stop" >&2 exit 3 ;; esac
/etc/rc2.dで下記のようにシムリンク作成。
lrwxrwxrwx 1 root root 17 Aug 26 09:45 S19boot -> ../init.d/rc.boot
起動時に自動的にhostsにホスト名が追記されます。
mysqldumpslowの結果をslackに投げてみた
概要
以前、mysqlのslow query数をslackに投稿させていましたが、数だけでなく質も見ないとダメだなということで、今回はmysqldumpslowによる統計結果を投稿させるようにしました。
mysqldumpslow
MySQLに付属しているツールで、スロークエリログを集計してくれます。
mysqldumpslow実行
例)
mysqldumpslow -s t mysql-slow.log
mysqldumpslow実行結果
回数、平均実行時間などを総消費時間数順に表示してくれます。
Reading mysql slow query log from mysql-slow.log Count: 1179 Time=1.88s (2222s) Lock=0.00s (0s) Rows=10.0 (11790), naked[naked]@33hosts SELECT `timeline_threads`.* FROM `timeline_threads` INNER JOIN `naked_friends` ON `naked_friends`.`naked_id` = N and `naked_friends`.`friend_naked_id` = `timeline_threads`.`naked_id` WHERE `timeline_threads`.`deleted_at` IS NULL ORDER BY `timeline_threads`.`created_at` DESC, `timeline_threads`.`id` DESC LIMIT N Count: 88 Time=17.08s (1502s) Lock=0.00s (0s) Rows=1.0 (88), naked[naked]@24hosts SELECT COUNT(DISTINCT `naked_items`.`id`) FROM `naked_items` INNER JOIN `naked_item_countries` ON `naked_item_countries`.`naked_item_id` = `naked_items`.`id` LEFT OUTER JOIN `nakeds` ON `nakeds`.`id` = `naked_items`.`naked_id` WHERE `naked_item_countries`.`country_id` = 'S' AND `nakeds`.`banned_at` IS NULL AND `nakeds`.`deleted_at` IS NULL AND `naked_items`.`target_type` != 'S' AND (`naked_items`.deleted_at IS NULL) Count: 76 Time=9.09s (690s) Lock=0.00s (0s) Rows=0.8 (59), naked[naked]@[10.10.0.4] SELECT `nakeds`.* FROM `nakeds` WHERE `nakeds`.`reset_password_token` = 'S' LIMIT N ・ ・ ・ ・ ・
slack.sh
mysqldumpslowの結果を全部送ると見切れないので上から3つまでの結果をmessageに入れて投稿するシェルスクリプトを作りました。
#!/bin/bash date=`date '+%Y-%m-%d'` server_name=`hostname` url="https://hooks.slack.com/services/zzzzzzz/xxxxxx/123456789aaa?parse=full" num=`mysqldumpslow -s t /var/log/mysql/mysql-slow.log | head -8` message="($date) $server_name のslow-query top3は\n \`\`\` $num \`\`\` です。" payload="payload={\"text\": \"${message}\", \"username\": \"naked\"}" curl --data "${payload}" ${url}
定期実行
cronで定期実行します。
# # m h dom mon dow command 30 6 * * * /root/work/slack.sh
あとがき
この仕組みで今度こそ他のメンバーの興味を引ければと考えています。。。