My Tracking

My Tracking

記憶力の低下が気になるアラフォー男の備忘録

「AWS-CLIで試すLambdaでのHelloWorld!」を試す

AWS Lambdaを試してみたいと思っていたところ、 AWS CLIを使ってAWS Lambdaを体験してみるのに、ちょうどいい記事があったため、

qiita.com

上記記事をもろパクリで、AWS Lambdaを試して際の備忘録。

目次

ユースケース

  • ユースケースは、上記記事にある通り、主に下記のとおり。
  • AWS CLIを使ってAWS Lambdaを設定する。
  • Lambdaで Hello World Lambda! という出力をCloudWatchLogsに出力

構成

(構成図)

S3バケットの作成

まずは、バケットを作成します。作成するS3バケットのリージョンは 上記記事のとおり、「us-east-1」 とする。 mylab-lambda-test となっている部分は適当に変更する。

[root@Linux ~]# aws s3 mb s3://mylab-lambda-test --region us-east-1
make_bucket: s3://mylab-lambda-test/
[root@Linux ~]#

作成されたことを確認

[root@Linux ~]# aws s3 ls --region us-east-1 |grep lambda
2016-10-30 01:42:29 mylab-lambda-test
[root@Linux ~]#

上記記事のとおり、コマンド実行。(nullの意味はよく分からない)

[root@Linux ~]# aws s3api get-bucket-location --bucket mylab-lambda-test
{
    "LocationConstraint": null
}
[root@Linux ~]#

Lambda Exec Roleの作成

Lambdaで処理を実行する際にCloudWatchLogsにログを出力するためのLambdaExecRoleする。

[root@Linux aws]# cat role-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
     {
       "Action": "sts:AssumeRole",
       "Principal": {
         "Service": "lambda.amazonaws.com"
        },
        "Effect": "Allow",
        "Sid": ""
     }
  ]
}
[root@Linux aws]#

作成後、以下のCLIでロールを作成する。

[root@Linux aws]# aws iam create-role --role-name hello_exec_role --assume-role-policy-document file://role-policy.json
{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Action": "sts:AssumeRole",
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    }
                }
            ]
        },
        "RoleId": "xxxxxxxxxxxxxxxxxx",
        "CreateDate": "2016-10-29T16:49:41.478Z",
        "RoleName": "hello_exec_role",
        "Path": "/",
        "Arn": "arn:aws:iam::999999999999:role/hello_exec_role"
    }
}
[root@Linux aws]#

作成されたロールを確認する。

[root@Linux aws]# aws iam get-role --role-name hello_exec_role

また、後の行程で利用するロールのARN「下記「999999999999」の個所」)を確認する。

[root@Linux aws]# aws iam get-role --role-name hello_exec_role |jq -r  .'Role.Arn'
arn:aws:iam::999999999999:role/hello_exec_role
[root@Linux aws]#

CloudWatchLogsへの書き込みを行う権限を付与する。(LambdaではCloudWatchLogsにログ情報を記載) 最初からAWS側で用意してあるポリシーがあるようなので、今回はそれを利用するため、下記コマンドで確認。

[root@Linux aws]# aws iam get-policy --policy-arn "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
{
    "Policy": {
        "PolicyName": "CloudWatchLogsFullAccess",
        "Description": "Provides full access to CloudWatch Logs",
        "CreateDate": "2015-02-06T18:40:02Z",
        "AttachmentCount": 0,
        "IsAttachable": true,
        "PolicyId": "xxxxxxxxxxxxxxxxxxx",
        "DefaultVersionId": "v1",
        "Path": "/",
        "Arn": "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",
        "UpdateDate": "2015-02-06T18:40:02Z"
    }
}
[root@Linux aws]#

先述のロールに上記ポリシーを付与する。

[root@Linux aws]# aws iam attach-role-policy --role-name hello_exec_role --policy-arn "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
[root@Linux aws]#

確認する。(先ほど付与したポリシーが表示されることを確認)

[root@Linux aws]# aws iam list-attached-role-policies --role-name hello_exec_role
{
    "AttachedPolicies": [
        {
            "PolicyName": "CloudWatchLogsFullAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
        }
    ]
}
[root@Linux aws]#

Lambdaの設定

続いて、Lambdaの設定する。 最初に Lambda に機能を追加する。先述の記事そのままのコードを追加する。

[root@Linux aws]# cat index.js
console.log('Loading function');

exports.handler = function(event, context) {
    console.log('value1 =', event.key1);
    console.log('value2 =', event.key2);
    console.log('value3 =', event.key3);
    console.log('hello world!');
    context.succeed(event.key1);  // Echo back the first key value
    // context.fail('Something went wrong');
};
[root@Linux aws]#

上記はzip圧縮する。

[root@Linux aws]# zip -r HelloWorld.zip index.js
  adding: index.js (deflated 47%)
[root@Linux aws]#
[root@Linux aws]# ls -l HelloWorld.zip
-rw-r--r-- 1 root root 351 1030 01:56 2016 HelloWorld.zip
[root@Linux aws]#

LamdaFunctionを作成する。 --role には先ほど作成したRoleのARN(「下記「999999999999」の個所」)を指定する。

[root@Linux aws]# aws lambda create-function \
> --function-name hello_function \
> --runtime nodejs \
> --role arn:aws:iam::999999999999:role/hello_exec_role \
> --handler index.handler \
> --zip-file fileb://HelloWorld.zip \
> --region us-east-1
{
    "CodeSha256": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Malc=",
    "FunctionName": "hello_function",
    "CodeSize": 351,
    "MemorySize": 128,
    "FunctionArn": "arn:aws:lambda:us-east-1:999999999999:function:hello_function",
    "Version": "$LATEST",
    "Role": "arn:aws:iam::999999999999:role/hello_exec_role",
    "Timeout": 3,
    "LastModified": "2016-10-29T16:57:33.995+0000",
    "Handler": "index.handler",
    "Runtime": "nodejs",
    "Description": ""
}
[root@Linux aws]#

確認する。

[root@Linux aws]# aws lambda get-function --function-name hello_function --region us-east-1
{
    "Code": {
        "RepositoryType": "S3",
        "Location": "https://prod-04-2014-tasks.s3.amazonaws.com/snapshots/812517560171/hello_function-4ae7c455-9bc4-4e96-8c0d-7463b41392b3?X-Amz-Security-Token=FQoDYXdzEDEaDIanV7oOQ5we%2BLkdvCK3A5h76yiKfc72ECqG6XhXe53l4RGqmX2bPtiXWsxuBfhH%2FK0cxoYi3KSB3YvpgJpc7bckdc1UwUm62x0uXqaS1GYxVYXpzQl1LPxneQiA3SF6cwfBneLj%2FLFqKPVVCLok%2BL0qt7xu9dS8ZHEFL42sk%2BcCsNIgnw5OzICsN%2BIcQ9XA%2BtmHEeOw%2Fw1LemS5P%2FBzw7vF4WOjy3JQl7Y2Es313STb0ILto5ZmuHuI1tRBCWNfPv3yuBrwj%2FEjIfSX0AEqMIMxwO%2FjlKMo7IVmMkD1QUPgu%2BENgt0lmfqZ0Zy9PXg74wOs9Jhprmws5tnUABspI9L%2B3NlcM1YSpOGo%2FMUUWwzyjXCC44Kl4Ir3ECb4NQpyvClzESGSoG1JL%2F1EsROd3Mi4fpuDBiTrREAEyBg08XuUEXfpVXjXz%2FpyAoZhVE4KiuZp7r8p4d%2BVfBCexIb4sQVWCvfoMjANENa9kQbbDi5S54hz7RPwT71Akk8s6%2FbLKMWmPdgKj8kZrW0r0xirD%2B%2Fi%2FmBiCDMd1SFtQ6TbGnkrkNK9yTBfb%2FJuRkHY2ST80jnU63dmkeN0CJEextWCpclBRUk0n10owovTwAU%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20161029T165800Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Credential=ASIAJJ2IKKNCV4NGIF3A%2F20161029%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=9ccdfd59ed3445203b7b320cec9d73d0d2ab18e5584f94aa29e79789a2546473"
    },
    "Configuration": {
        "Version": "$LATEST",
        "CodeSha256": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Malc=",
        "FunctionName": "hello_function",
        "MemorySize": 128,
        "CodeSize": 351,
        "FunctionArn": "arn:aws:lambda:us-east-1:999999999999:function:hello_function",
        "Handler": "index.handler",
        "Role": "arn:aws:iam::999999999999:role/hello_exec_role",
        "Timeout": 3,
        "LastModified": "2016-10-29T16:57:33.995+0000",
        "Runtime": "nodejs",
        "Description": ""
    }
}
[root@Linux aws]#

あとで、利用するARNを「下記「999999999999」の個所」)確認する。

[root@Linux aws]# aws lambda get-function --function-name hello_function --region us-east-1 |jq -r .'Configuration.FunctionArn'
arn:aws:lambda:us-east-1:999999999999:function:hello_function
[root@Linux aws]#

イベントを明示的に発行させる。

上記記事のとおり、イベントを明示的に発行するため、以下のファイルを保存する。 なお、 mylab-lambda-test というバケット名の箇所は適宜自分の作成したバケット名に変更する。

[root@Linux aws]# cat input.txt
{
   "Records":[
      {
         "eventVersion":"2.0",
         "eventSource":"aws:s3",
         "awsRegion":"us-west-2",
         "eventTime":"1970-01-01T00:00:00.000Z",
         "eventName":"ObjectCreated:Put",
         "userIdentity":{
            "principalId":"xxxxxxxxxxxxxxx"
         },
         "requestParameters":{
            "sourceIPAddress":"127.0.0.1"
         },
         "responseElements":{
            "x-amz-request-id":"xxxxxxxxxxxxxxx",
            "x-amz-id-2":"xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx"
         },
         "s3":{
            "s3SchemaVersion":"1.0",
            "configurationId":"testConfigRule",
            "bucket":{
               "name":"mylab-lambda-test",
               "ownerIdentity":{
                  "principalId":"xxxxxxxxxxxxxxx"
               },
               "arn":"arn:aws:s3:::mylab-lambda-test"
            },
            "object":{
               "key":"HappyFace.jpg",
               "size":1024,
               "eTag":"xxxxxxxxxxxxxxx",
               "versionId":"xxxxxxxxxxxxxxx.xxxxxxxxxxxxxxx"
            }
         }
      }
   ]
}
[root@Linux aws]#

以下で実行する。

$aws lambda invoke --invocation-type Event --function-name hello_function --region us-east-1 --payload file://input.txt outputfile.txt
{
    "StatusCode": 202
}

ログ出力されていることを確認する。

[root@Linux aws]# aws logs describe-log-streams --log-group-name /aws/lambda/hello_function --region us-east-1
{
    "logStreams": [
        {
            "firstEventTimestamp": 1477760612319,
            "lastEventTimestamp": 1477760892171,
            "creationTime": 1477760612236,
            "uploadSequenceToken": "49558049102621580872441351977558681473346750801996953826",
            "logStreamName": "2016/10/29/[$LATEST]f11d2581b1174061a6bcec5415008bdf",
            "lastIngestionTime": 1477760907296,
            "arn": "arn:aws:logs:us-east-1:812517560171:log-group:/aws/lambda/hello_function:log-stream:2016/10/29/[$LATEST]f11d2581b1174061a6bcec5415008bdf",
            "storedBytes": 0
        }
    ]
}
[root@Linux aws]#

S3の設定をする

以下のコマンドを実行する。hello_functionのlambda:InvokeFunctionにS3の権限を付与する。 statement-id には任意の名称を指定し、ARNは arn:aws:s3:::{bucket_name} の形式で指定する。 ※ここら辺はよくわからないので、先述の記事をいままで通りパクる。

[root@Linux aws]# aws lambda add-permission --function-name hello_function --region us-east-1 --statement-id s3_mylab-lambda-test --action "lambda:InvokeFunction" --principal s3.amazonaws.com --source-arn "arn:aws:s3:::mylab-lambda-test"
{
    "Statement": "{\"Sid\":\"s3_mylab-lambda-test\",\"Resource\":\"arn:aws:lambda:us-east-1:812517560171:function:hello_function\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":[\"lambda:InvokeFunction\"],\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::mylab-lambda-test\"}}}"
}
[root@Linux aws]#

確認する。

[root@Linux aws]# aws lambda get-policy --function-name hello_function --region us-east-1
{
    "Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"default\",\"Statement\":[{\"Sid\":\"s3_mylab-lambda-test\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:812517560171:function:hello_function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::mylab-lambda-test\"}}}]}"
}
[root@Linux aws]#

S3側にもイベントを追加するために、追加したいイベントJSONを作成する。

LambdaFunctionのARN(「下記「999999999999」の個所」)を指定し、 Id には任意の文字列を指定し、Events 内にイベントのタイミング ((下記例ではObjectが作成された時)を設定する。

[root@Linux aws]# cat event.json
{
    "LambdaFunctionConfigurations": [
        {
            "LambdaFunctionArn": "arn:aws:lambda:us-east-1:999999999999:function:hello_function",
            "Id": "lambda-hello",
            "Events": [
                "s3:ObjectCreated:*"
            ]
        }
    ]
}
[root@Linux aws]#

以下を実行してS3の対象バケットにイベントを設定。

[root@Linux aws]# aws s3api put-bucket-notification-configuration --bucket mylab-lambda-test --region us-east-1 --notification-configuration file://event.json
[root@Linux aws]#

設定を確認。

[root@Linux aws]# aws s3api get-bucket-notification --bucket mylab-lambda-test --region us-east-1
{
    "CloudFunctionConfiguration": {
        "CloudFunction": "arn:aws:lambda:us-east-1:8888888888888:function:hello_function",
        "Events": [
            "s3:ObjectCreated:*"
        ],
        "Id": "lambda-hello",
        "Event": "s3:ObjectCreated:*"
    }
}
[root@Linux aws]#

S3にファイルをアップロードし、イベントを発行する。

実際にS3にファイルをputする。

[root@Linux aws]# aws s3 cp event.json s3://mylab-lambda-test --region us-east-1
upload: ./event.json to s3://mylab-lambda-test/event.json
[root@Linux aws]#

lambdaが実行されたことをログで確認する。

最初に確認した際は、ResourceNotFoundExceptionエラーが発生したため、

[root@Linux aws]# aws logs get-log-events --log-group-name "/aws/lambda/demo_func" --log-stream-name "2016/10/29/[$LATEST]f11d2581b1174061a6bcec5415008bdf"

An error occurred (ResourceNotFoundException) when calling the GetLogEvents operation: The specified log group does not exist.
[root@Linux aws]# 

以下の記事を参考にして、--log-stream-name の引数を ' (シングルクォート) で囲んだうえで、 ログを確認し、ログが出力されていることを確認する。

dev.classmethod.jp

[root@Linux aws]# aws logs get-log-events --log-group-name "/aws/lambda/hello_function" --log-stream-name '2016/10/29/[$LATEST]9d7808a222dc4c48b2520e66dc2c0d90' --region us-east-1
{
    "nextForwardToken": "f/32955208848878810726028768378655453483555694011301167109",
    "events": [
        {
            "ingestionTime": 1477762546397,
            "timestamp": 1477762546380,
            "message": "2016-10-29T17:35:46.380Z\t1fab1ae4-9dfe-11e6-90e5-6d0b1489607e\tLoading function\n"
        },
        {
            "ingestionTime": 1477762561482,
            "timestamp": 1477762546381,
            "message": "START RequestId: 1fab1ae4-9dfe-11e6-90e5-6d0b1489607e Version: $LATEST\n"
        },
        {
            "ingestionTime": 1477762561482,
            "timestamp": 1477762546388,
            "message": "2016-10-29T17:35:46.388Z\t1fab1ae4-9dfe-11e6-90e5-6d0b1489607e\tvalue1 = undefined\n"
        },
        {
            "ingestionTime": 1477762561482,
            "timestamp": 1477762546388,
            "message": "2016-10-29T17:35:46.388Z\t1fab1ae4-9dfe-11e6-90e5-6d0b1489607e\tvalue2 = undefined\n"
        },
        {
            "ingestionTime": 1477762561482,
            "timestamp": 1477762546388,
            "message": "2016-10-29T17:35:46.388Z\t1fab1ae4-9dfe-11e6-90e5-6d0b1489607e\tvalue3 = undefined\n"
        },
        {
            "ingestionTime": 1477762561482,
            "timestamp": 1477762546388,
            "message": "REPORT RequestId: 1fab1ae4-9dfe-11e6-90e5-6d0b1489607e\tDuration: 7.49 ms\tBilled Duration: 100 ms \tMemory Size: 128 MB\tMax Memory Used: 27 MB\t\n"
        }
    ],
    "nextBackwardToken": "b/32955206010752172289830483475910265610675480239467724800"
}
[root@Linux aws]#

最後に作成した設定を削除する。

lambda関連

[root@Linux aws]# aws lambda delete-function --function-name hello_function --region us-east-1

iam関連

[root@Linux aws]# aws iam detach-role-policy --role-name hello_exec_role --policy-arn "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
[root@Linux aws]# aws iam delete-role --role-name hello_exec_role

s3関連

[root@Linux aws]# aws s3 rm s3://mylab-lambda-test --recursive --region us-east-1
delete: s3://mylab-lambda-test/event.json
delete: s3://mylab-lambda-test/input.txt
[root@Linux aws]# aws s3 rb s3://mylab-lambda-test --region us-east-1
remove_bucket: s3://mylab-lambda-test/
[root@Linux aws]#