AWSのLambdaでEC2の起動・停止を制御したいと思い
pythonでコードをEC2の起動・停止のコードを書いたのですが、いざテスト実行したところ
「Task timed out after 60.00 seconds」
といったエラーになりました。
ロールも、pythonコードもあっている、Lambdaの処理時間(Timeout)も最大の60秒にしたはずなのに一体何故Lambdaがエラーになってしまうのか!?
レジュメ
結論、EC2に命令をするためにはLambdaがインターネットに抜ける必要がある
EC2の起動・停止をLambdaで実行させるには
- EC2を起動・停止するPythonプログラムコード
- Lambda必要なロールを割り当てる
- インターネットに抜けれるnatゲートウェイサブネット
が必要になります。
インターネットに抜けれる環境でないと「Task timed out after 60.00 seconds」というエラーが発生します。
EC2を起動・停止するPythonプログラムコード
pythonでEC2を起動させるためのプログラムサンプルコードは
import boto3
def lambda_handler(event, context):
client = boto3.client('ec2')
response = client.start_instances(
InstanceIds=['i-XXXXXXX']
)
print response
pythonでEC2を停止させるためのプログラムサンプルコードは
import boto3
def lambda_handler(event, context):
client = boto3.client('ec2')
response = client.stop_instances(
InstanceIds=['i-XXXXXXX']
)
print response
になります。
今回実行したRuntimeとしては「Python 2.7」で
Handlerは「index.lambda_handler」としました(Edit code inlineでプログラムコードを書いたのでindex。プログラムコードの関数名をlambda_handlerとしたため)
参考:Boto 3 Documentation — Boto 3 Docs 1.3.1 documentation
Lambda必要なロールを割り当てる
簡単には
- EC2をコントロールできる権限(「CloudWatchActionsEC2Access」相当)と
- Lambdaを実行出来る権限(「AWSLambdaVPCAccessExecutionRole」相当)を
Lambdaのロールに割り当てましょう
インターネットに抜けれるnatゲートウェイサブネット
最後に、Lambdaはawsコマンド同様、インターネット経由でAWSにEC2の起動・停止命令を出します。
そのため、Lambdaはインターネットに抜けれる、NatゲートウェイサブネットにLambdaのIPアドレスを持つように設定しましょう(サブネットの選択)。
もちろん、セキュリティグループも「outbound rules」をインターネットに抜けれるように設定します。
When you enable VPC, your Lambda function will lose default internet access. If you require external internet access for your function, ensure that your security group allows outbound connections and that your VPC has a NAT gateway.
これでLambdaが実行出来、EC2を起動・停止出来るようになると思います。
Lambdaをテスト実行してみましょう!