#はじめに
「EC2を起動し、特定の時間経過後、EC2を停止する」仕組みをAPIGatewayとStepFunctionを使い、実現します。
#完成図
https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/start-limit?instance_id=i-hogehoge&time=10
をリクエストすると、インスタンスIDがi-hogehoge
のEC2を起動し、10
秒後に停止する挙動になります。
挙動の詳細について説明しますと、
起動するインスタンスinstance_id
で指定し、と起動してから停止するまでの時間をtime
で指定しています。
APIGatewayからこれらの2つの値をStepFunctionに渡し、StepFunction内で、Lambdaにinstance_id
、とWaitにtime
を渡して実行する挙動になります。
#作業の流れ流れ
①Lambda用のIAMポリシーを作成
②Lambdaを2つ作成
③Stepfunction作成
④APIGateway用のIAMロール作成
⑤APIGateway作成
#Lambda用のIAMポリシーを作成
LambdaでEC2を起動・停止するためのぽりが必要です。
jsonで下記のコードをコピペして、ポリシーを作成しましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"ec2:DescribeInstances",
"ec2:StopInstances",
"ec2:StartInstances",
"logs:CreateLogGroup",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
#Lambdaを2つ作成
起動と停止するLambdaを作成します。
・関数を作成:一から作成
・関数名:適切に
・ランタイム:Python
・アクセス権限:基本的な Lambda アクセス権限で新しいロールを作成
import json
import boto3
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name='ap-northeast-1')
ec2.start_instances(InstanceIds=[event['instance_id']])
import json
import boto3
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name='ap-northeast-1')
ec2.stop_instances(InstanceIds=[event['instance_id']])
作成後、設定
→実行ロールの編集
から、先程作成したポリシーをIAMロールにアタッチしてください。
#Stepfunction作成
ステートマシンを作成します。
・ワークフローを視覚的に設計
・タイプ
:標準
次へ
ワークフローを設計
StartとEndの間に以下の通りにフローを設定します。
・アクション
:Lambda Invoke
・フロー
:Wait
・アクション
:Lambda Invoke
###第一工程(EC2の起動)
設定
・状態名
:startEC2
・Integration Type
:Optimized
・Function name
:先程作成したEC2の起動Lambda
・ペイロード
:Use state input as payload
・追加の状態
:Wait
入力
・InputPath で入力をフィルタリング
:$.InputParams
入力をInputParamsに絞ることで、Lambdaに渡す値がわかりやくすなります。
Lambdaは、InputParams.instance_id
を参照します。
"InputParams": {
"instance_id": "i-xxxxxxxxxxxx",
"time": 10
}
出力
・ResultPath を使用して元の入力を出力に追加
:Discard result and keep original input
元の入力からそのまま出力されます。
元の入力を変えると、Waitや次のLambdaが値を参照できなくなります。
###第二工程(待機時間)
設定
・状態名
:stopEC2
・オプション
:Wait for a fixed interval
・Get seconds from state input
:$.InputParams.time
InputParams
のtime
の値を参照して待機時間の値が決定されます。
入力
・チェックしません
出力
・チェックしません
###第三工程(EC2の停止)
設定
・状態名
:stopEC2
・Integration Type
:Optimized
・Function name
:作成したEC2の停止Lambda
・ペイロード
:Use state input as payload
入力
・InputPath で入力をフィルタリング
:$.InputParams
次へ
・名前
:EC2-Control
・実行ロール
:新しいロールを作成
ステートマシンが作成されました。
###StepFunctionの定義
stepfunctionの定義になります。LambdaのARN2つを貼り付けると、コピペで作成できます。
{
"Comment": "This is your state machine",
"StartAt": "startEC2",
"States": {
"startEC2": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxx:function:test-steppfunction:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException"
],
"IntervalSeconds": 2,
"MaxAttempts": 6,
"BackoffRate": 2
}
],
"Next": "Wait",
"ResultPath": null,
"InputPath": "$.InputParams"
},
"Wait": {
"Type": "Wait",
"Next": "stopEC2",
"SecondsPath": "$.InputParams.time"
},
"stopEC2": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"OutputPath": "$.Payload",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:ap-northeast-1:xxxxxxx:function:stop-stepfunction:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException"
],
"IntervalSeconds": 2,
"MaxAttempts": 6,
"BackoffRate": 2
}
],
"End": true,
"InputPath": "$.InputParams"
}
}
}
#APIGateway用のIAMロール作成
StepFunctionsの実行権限を持ったロールが必要なため、API Gateway用のIAMロールを作成します
ロールの作成
・AWSサービス
・APIGateway
次のステップ
ポリシーの選択
・AmazonAPIGatewayPushToCloudWatchLogs
が選択済み
追加せずそのまま、次のステップをクリック
作成したロールにAWSStepFunctionsFullAccess
をアタッチします。
ロールのARNをコピーしておきます。
#APIGateway作成
REST API
の構築
を選択します。
・プロトコル
:REST
・新しいAPI
・API名
:EC2-Start-StepFunction
リソースの作成
・リソース名
:start-limit
メソッドの作成
・メソッド
:GET
・結合タイプ
: AWS サービス
・AWS リージョン
:適切な値
・AWS サービス
:Step Functions
・HTTP メソッド
:POST
・アクションの種類
: アクション名の使用
・アクション
:StartExecution
(LambdaをキックするAPIにはStartExecution)
・実行ロール
:先程作成したAPIGateway用のロールのARN
統合リクエスト
をクリックします。
下側にあるマッピングテンプレート
をクリックし、application/json
名で、下記のコードを入力し、保存します。
先程コピーしたStepFunctionのARNが必要です。
#set( $body = $util.escapeJavaScript($input.json('$')) )
{
"input": "{\"input\":$body,\"InputParams\":{\"instance_id\":\"$input.params('instance_id')\",\"time\":$input.params('time')}}",
"stateMachineArn": "StepFunctionのARNを入力!"
}
起動するインスタンスinstance_id
と起動してから停止するまでの時間time
をAPIGatewayからStepFunctionに渡します。
StepFunction側は、以下のように受け取ります。
{
"input": {},
"InputParams": {
"instance_id": "i-xxxxxxx",
"time": 10
}
}
APIをデプロイすると、URLが発行されます。
デプロイのステージ名をprod
とすると、
URLはhttps://xxxxx.execute-api.ap-northeast-1.amazonaws.com/prod
になります。
https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/start-limit?instance_id=i-xxxxxxx&time=100
とすると、インスタンスが起動し、100秒後にインスタンスが停止します。
URLをコピペして、エンターキーをおしてみましょう。
#参考
Step Functionsを使い倒す
API Gateway を使用したStep Functions API の作成
ParametersやらResultPath
StepFunctionsの入力方法サンプルメモ集
API GatewayでStepFunctionsと統合する時のTips