subscriptionFilter
CloudWatch Logsに入ってきたデータをイベントドリブンに処理が可能なものです。
各ロググループに1つのみ適応可能という制限があります
subscriptionFilterを使ってLambdaを起動する方法を説明します。
なお、subscriptionFilterの設定はマネコンではできないはずです
設定
前提として、動かすLambdaはできているものとします。
設定はCFnを用いて行います
対象のLambda名: sample-lambda
対象のロググループ名: sample-log
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
SourceLogGroup:
Description: "CWL log group name"
Type: "String"
LambdaFunctionName:
Description: "Lambda function name"
Type: "String"
filterPattern:
Description: "CWL filter pattern"
Type: "String"
Resources:
subscriptionFilter:
Type: "AWS::Logs::SubscriptionFilter"
Properties:
LogGroupName: !Ref SourceLogGroup
FilterPattern: !Ref filterPattern
DestinationArn: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaFunctionName}"
設定を行うのは上記のテンプレートのとおりです。
AWSTemplateFormatVersion: "2010-09-09"
Description: "root stack for cloudwatch logs subscription filter template."
Mappings:
ResourceMapping:
LambdaFunction:
name: "sample-lambda"
clpudwatchLogsFilterPattern:
all: ""
error: "error"
Resources:
CWLSubscriptionFilterStack:
Type: "AWS::CloudFormation::Stack"
Properties:
TemplateURL: <nested-template.yaml への相対パス>
Parameters:
SourceLogGroup: "sample-log"
LambdaFunctionName: !FindInMap [ ResourceMapping, LambdaFunction, name ]
filterPattern: !FindInMap [ ResourceMapping, clpudwatchLogsFilterPattern, default ]
必要なロググループ分リソースを追加していけば大丈夫です。
デプロイ
aws cli を用いてデプロイします。設定は終わっているものとします。
ネストしたテンプレートはS3に上がっている必要があるので先にpackage化します。
aws cloudformation package \
--template-file ./ubscription-filter-root-stack.yaml \ # 2つ目に書いたテンプレートへのパス
--s3-bucket ${S3_BUCKET_NAME} \ # テンプレートを格納するS3(CWLと同一リージョンのS3を使うこと)
--s3-prefix ${REPOSITORY_NAME} \ # S3に格納する際のプレフィックスを指定
--output-template-file ./bscription-filter-root-stack-package.yaml # package化してデプロイに使用するテンプレートの出力先
デプロイ
aws cloudformation deploy \
--s3-bucket ${S3_BUCKET_NAME} \ # テンプレートを格納するS3
--template-file ./bscription-filter-root-stack-package.yaml \ # package化してデプロイに使用するテンプレート
--stack-name ${STACK_NAME} \ # デプロイするCFnスタックの名称
--capabilities CAPABILITY_NAMED_IAM \ # 固定値だと思っていいです
--role-arn ${ROLE_ARN} # CFnを動かす権限を持ったロールを指定
注意
CWLのsubscriptionFilterからLambdaを動かす際にはLambdaに特殊な権限が必要です。
権限が無い状態でこのCFnを動かすとエラーでロールバックします
権限の設定はCLIで行います
aws lambda add-permission \
--function-name "sample-lambda" \
--statement-id "sample-log-sample-lambda" \
--principal "logs.<region>.amazonaws.com" \
--action "lambda:InvokeFunction" \
--source-arn "arn:aws:logs:<region>:<account-id>:log-group:sample-log:*" \
--source-account "<account-id>"
<>で囲われてる部分は直してください。
なお、上記commandを打っていない状態であれば下記のCFnを適応することでデプロイが可能
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
SourceLogGroup:
Description: "CWL log group name"
Type: "String"
LambdaFunctionName:
Type: "String"
filterPattern:
Type: "String"
Resources:
subscriptionFilter:
DependsOn:
- LambdaInvokePermission
Type: "AWS::Logs::SubscriptionFilter"
Properties:
LogGroupName: !Ref SourceLogGroup
FilterPattern: !Ref filterPattern
DestinationArn: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaFunctionName}"
LambdaInvokePermission:
Type: 'AWS::Lambda::Permission'
Properties:
FunctionName: !Ref LambdaFunctionName
Action: "lambda:InvokeFunction"
Principal: !Sub "logs.amazonaws.com"
SourceAccount: !Ref AWS::AccountId
SourceArn: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${SourceLogGroup}:*"
上記テンプレートはCLIを使ってパーミッション入っていると逆に落ちます。