AWS Data Pipelineを利用したAWSジョブスケジューラ
こんばんは、城内です。 ついに先日AWS LambdaがTokyoリージョンに上陸しましたね。以下のまとめ記事、いいですね!
そんな中、今回はData Pipelineネタです。なぜいまLambdaのTokyoリージョン上陸を喜びつつもData Pipelineなのかは、この記事をご覧頂ければきっと分かってもらえるかと思います(笑)。
はじめに
今回何をやるのかというと、Data Pipelineをジョブスケジューラ代わりに使ってみたいと思います。 実行する処理は、定期的に不要なEC2インスタンスを停止するジョブです。開発用インスタンスの止め忘れなど、皆さんもよくあることかと思います。
事前準備
まず、Data Pipelineのロジック部分となるスクリプトとそれを格納するS3バケット、通知用のSNSトピックを作成します。
EC2インスタンス停止スクリプト
今回は以下のようなスクリプトを作成しました。 基本は、対象リージョンで起動しているすべてのEC2インスタンスを容赦なく停止していく仕様なのですが、除外の措置として、停止したくないEC2インスタンスに対し、「Production=True」タグを設定しておけば対象外となります。
#!/bin/bash targetRegion="ap-northeast-1" myTagName="Production" timeoutMins=5 topicArn="arn:aws:sns:ap-northeast-1:123456789012:dp-test" export AWS_DEFAULT_REGION=$targetRegion prodInstanceIds=$(echo $(aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(.Tags[] | select(.Key == "'$myTagName'") | .Value == "True").InstanceId')) myInstanceId=$(curl -s http://169.254.169.254/latest/meta-data/instance-id/) nonStopInstanceIds="$myInstanceId $prodInstanceIds" stopInstanceIds= for runInstanceId in $(aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(.State.Name == "running").InstanceId') do runInstanceId=$(echo $runInstanceId | sed 's/\"//g') if [ $(echo $nonStopInstanceIds | grep -c $runInstanceId) -eq 0 ]; then aws ec2 stop-instances --instance-ids $runInstanceId if [ "$stopInstanceIds" == "" ]; then stopInstanceIds="$runInstanceId" else stopInstanceIds="${stopInstanceIds} $runInstanceId" fi fi done if [ "$stopInstanceIds" == "" ]; then exit 0 fi notStopInstanceIds=$stopInstanceIds for ((i=0; i < $timeoutMins; i++)); do sleep 60 for checkInstanceId in $stopInstanceIds do result=$(aws ec2 describe-instance-status --instance-ids $checkInstanceId | jq '.InstanceStatuses[]') if [ "$result" == "" ]; then notStopInstanceIds=$(echo $notStopInstanceIds | sed "s/$checkInstanceId//") fi done if [ "$(echo $notStopInstanceIds | sed 's/ //g')" == "" ]; then break fi done stopInstanceIds=$(echo -e $(echo $stopInstanceIds | sed 's/ /\\n・/g')) notStopInstanceIds=$(echo $notStopInstanceIds | sed 's/ /、/g') message="以下のインスタンスを停止しました。 ・$stopInstanceIds" if [ "$notStopInstanceIds" != "" ]; then message="$message ※${notStopInstanceIds}のインスタンスは停止できませんでした。" fi aws sns publish --topic-arn $topicArn --message "$message" --subject "[Information] Job Scheduler has stopped EC2 instances." exit 0
S3バケットの作成
以下のようにS3バケットを作成し、配下に上記のスクリプト格納用フォルダ(script)と、ついでにログ格納用のフォルダ(log)も作成します。
そして、上記のスクリプトをscriptフォルダにアップロードしておきます。
SNSトピックの作成
上記のスクリプトの中で、結果通知用にSNSを送信しているので、そのためのSNSトピックを作成します。ちなみに、今回はData Pipelineでの通知設定は省略しています。
Data Pipelineセットアップ
では、さっそくData Pipelineの設定に入ります。
Create new pipeline
Data Pipelineのマネージメントコンソールを開き、[Create new pipeline]をクリックします。 以下の画面で、とりあえず赤枠の部分を設定しています。この後の画面で構成を設定するので、「Source」は「Build using Architect」を選択し、ログも事前に作成したS3バケットのフォルダに出力するようにします。
Edit in Architect
次に、構成を設定します。が、今回はShellCommandActivityを1つ作成するだけです。 以下のような感じで、とりあえず最低限の項目を設定します。
Schedulesは以下の通りです。
ResourcecsはEC2を使用します。
Preconditionsとして、jqのインストールを実行します。
Othersはデフォルトのままです。
ポリシーの変更
上記のData Pipelineをアクティブにする前に、スクリプトの実行でちゃんとEC2を停止できるよう、デフォルトのポリシー(DataPipelineDefaultResourceRole)を変更します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:*", "dynamodb:*", "ec2:*", "elasticmapreduce:Describe*", "elasticmapreduce:ListInstance*", "elasticmapreduce:AddJobFlowSteps", "rds:Describe*", "datapipeline:*", "cloudwatch:*", "redshift:DescribeClusters", "redshift:DescribeClusterSecurityGroups", "sdb:*", "sns:*", "sqs:*" ], "Resource": [ "*" ] } ] }
動作確認
最後に、動作確認をしてみます。動作確認のために、以下のようテストインスタンスを3つ立ち上げます。
- Test Server Stg ... Production=False
- Test Server Prod ... Production=True
- Test Server Dev ... Productionタグなし
作成したData Pipelineをアクティブにすると、まず実行環境となるEC2が立ち上がります。
そして、指定した時間になると、実行環境のEC2上でスクリプトが実行され、「Production=True」のタグがついていないEC2インスタンスが停止されます。
役目を終えた実行環境のEC2は、実行後に削除されます。
Data Pipelineの実行結果は以下の通りです。
ちゃんと結果通知メールも届いています。
さいごに
いかがでしょうか?Data Pipelineに少しでも興味を持って頂けたなら光栄です。
では、なぜLambdaフィーバー時にData Pipelineかと言えば、その理由は以下のスライドをご覧ください。 読み終えた時には、きっとData Pipelineを試してみたくなりますよ!
[slideshare id=42220749&doc=20141126aws-blackbelt-datapipeline-public-141201095140-conversion-gate01&w=640&h=320]