読者です 読者をやめる 読者になる 読者になる

set setting reset

インフラ関連の小ネタと備忘録

はじめての AWS Lambda python で boto3 から ec2 を起動する

はじめての AWS Lambda で boto3 から ec2 を起動する

いまさら感ありありですが表題のことを Management Console からやってみます。

初期画面

Screen Shot 2016-03-03 at 10.43.42.png

bluprint

Get Started で進むとたくさんのサンプルから選ぶことができますが、今回は Skip します

Screen Shot 2016-03-03 at 10.43.54.png

Configure function

設定画面が表示されますので、さっそく Lambda Function を定義していきます。

Screen Shot 2016-03-03 at 10.44.10.png

  • Name
    • Lambda Function の名前。
  • Description
    • 説明を記載します。必須ではありません。
  • Runtime
    • 執筆当時は以下のランタイムがありました。

今回は python2.7 にします。 (というか java も node.js もさっぱりです。。)

Lambda function code

デプロイ方法は 3 種類あります。

  • Edit Code inline
    • 画面のエディタに直接記述
  • Upload a .ZIP file
    • zip ファイルを upload
    • cli からやるときは zip でやるとよさそうです
  • Upload a .ZIP from Amazon S3
    • S3 にコードをアップロードしておき、その S3 URL を記載します

今回は Edit Code inline でやってみます。
test タグが Truestoppedインスタンスを起動するという単純なスクリプトを用意しました。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import boto3

ec2 = boto3.resource('ec2')


def get_specified_tagged_instance_ids(target_tag):
    """
    get target tagged instance-id
    """
    try:
        instances = ec2.instances.filter(
            Filters=[
                {'Name': 'tag:%s' % target_tag, 'Values': ['True']},
                {'Name': 'instance-state-name', 'Values': ['stopped']}])
    except Exception, e:
        print(e)
        sys.exit(2)

    if not instances is None:
        i = []
        for instance in instances:
            i.append(instance.instance_id)
    else:
        print("not found target tagged instances")
        sys.exit(0)

    return i


def start_instances(target_tag):
    """
    start instances
    """
    try:
        instances = get_specified_tagged_instance_ids(target_tag)
    except Exception, e:
        print(e)
        sys.exit(2)

    for instance in instances:
        res = ec2.instances.filter(InstanceIds=[instance]).start()
        status_code = res[0]["ResponseMetadata"]["HTTPStatusCode"]
        if status_code == 200:
            print("operation complete. target -> %s" % instance)
        else:
            print("operation failed. target -> %s" % instance)
            sys.exit(1)


def lambda_handler(event, context):
    target_tag = "test"
    start_instances(target_tag)
    sys.exit(0)

lambda_hanlder()__main__ 的に使うようにしてみました。 なお、lambda_hanlder() という名前は好きなものに変えることができます。

Lambda function handler and role

  • Handler
    • デフォルトは lambda_function.lambda_handler
    • 例えば test.py の hello_world() を実行したい場合は test.hello_world とすることができます
  • Role
    • 適切な IAM Role を付与します。

Role について、今回は basic vpc から作成してみます。 デフォルトの policy は以下のようなものでした。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateNetworkInterface",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DetachNetworkInterface",
        "ec2:DeleteNetworkInterface"
      ],
      "Resource": "*"
    }
  ]
}

ここに ec2:DescribeInstancesec2:StartInstances を追加して保存します。

Advanced settings

  • Memory
    • 128MB から 1536MB まで選択できます
  • Timeout
    • 5min まで設定できます
  • VPC
    • VPC を選択すると、lambda が起動する Subnet / Secrurity Groupを指定できます

確認画面

こんな感じになりました。 Create function に進みます。

Screen Shot 2016-03-03 at 11.31.42.png

Function の定義

Screen Shot 2016-03-03 at 11.33.43.png

今回は一日一回実行することにしますので Event Source のみ使います。

Screen Shot 2016-03-03 at 11.58.01.png

Add event source から CloudWatch Events Schedule を選択します。

Screen Shot 2016-03-03 at 11.59.30.png

  • Rule Name
    • 名前をつけます
  • Rule Description
    • 説明を記載します
  • Schedule Expression
    • rate (*) は繰り返し実行する時に使います
    • cron も書けますのでとても便利です
      • cron の時間は UTC のみです

指定したら submit します。Enable now の場合、少し待つと lambda が起動します。 Monitoring タブと CloudWatch Logs で稼働状況を確認できます。

CloudWatch Logs

Monitoring タブの View logs in CloudWatch からこの function の log stream に移動できます。
print 文の内容が表示されていますね。

Screen Shot 2016-03-03 at 12.22.02.png

awscli

一連の流れを awscli で行うとしたら以下の様な感じかと。

  • コードを zip にする
  • iam role を作成しておく(手抜き)
  • function を作成する
    • zip ファイルなので file:// ではなく、 fileb:// なことに注意
aws lambda create-function \
  --function-name auto_start_test \
  --runtime python2.7 \
  --role arn:aws:iam::**********:role/lambda_basic_vpc_execution \
  --handler auto_start.lambda_handler \
  --zip-file fileb://auto_start.zip \
  --timeout 30 \
  --memory-size 128 \
  --vpc-config SubnetIds=subnet-*******,SecurityGroupIds=sg-****** \
  --region ap-northeast-1
  • event を作成する
aws --profile lk-staging events put-rule \
  --name test \
  --schedule-expression "rate(5 minutes)" \
  --state ENABLED

{
    "RuleArn": "arn:aws:events:ap-northeast-1:**********:rule/test"
}

ただ、function と event の関連付ける方法がわかりませんでした。。。
ご存知の方、いらっしゃれば教えて下さい!