Lambda (Go) + EventBridge (Cron) + Systems Manager Parameter Store + CDK
Go で作った Lambda 関数(パラメータストアから値を読む)を EventBridge を使って Cron 実行する環境を CDK で書く。
環境
- aws-cdk: 2.54.0
- @aws-cdk/aws-lambda-go-alpha: 2.54.0-alpha.0
- aws-cdk-lib: 2.54.0
作るものの概要
毎月一日に MySQL の DB に接続してデータの生成・削除を行うバッチを作る。
MySQL への接続情報を AWS Systems Manager Parameter Store に保存し、コード実行時に取得して環境変数に動的に設定する。
ディレクトリ構成は以下の通りとする。
ルート
|
|-app
| |-go.mod
| |-go.sum
| |-main.go
|
|-cdk(cdk init --language typescript で作られるファイル群)
|-bin
|-lib
|-...
Lambda のソースコード
app/main.go
package main
import (
"database/sql"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
_ "github.com/go-sql-driver/mysql"
"os"
"strings"
"time"
"gitlab.com/k1350/sololog_gql/sololog_back/app/repository/jwk"
)
func rotateKey() error {
err := fetchParameterStore()
if err != nil {
return err
}
dsn := os.Getenv("DSN")
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
defer db.Close()
if err = db.Ping(); err != nil {
return err
}
jwkr := jwk.NewJWKRepository(db)
now := time.Now().UTC()
// 新規鍵作成
err = jwkr.Create(now)
if err != nil {
return err
}
// 古い鍵削除
return jwkr.DeleteOldKey(now)
}
func fetchParameterStore() error {
sess := session.Must(session.NewSession())
svc := ssm.New(
sess,
aws.NewConfig().WithRegion("ap-northeast-1"),
)
parameters, err := svc.GetParametersByPath(&ssm.GetParametersByPathInput{
Path: aws.String("/sololog"),
WithDecryption: aws.Bool(true),
})
if err != nil {
return err
}
for _, v := range parameters.Parameters {
names := strings.Split(*v.Name, "/")
name := names[len(names)-1]
err = os.Setenv(name, *v.Value)
if err != nil {
return err
}
}
return nil
}
func main() {
lambda.Start(rotateKey)
}
パラメータストアに予め “/sololog/DSN” という名前で MySQL への接続情報を保存していることを前提としている。
fetchParameterStore
内で、GetParametersByPath
を使って “/sololog” というパスの下のパラメータをすべて取得し、環境変数に投入している。
今回のケースでは取得したパラメータを環境変数に入れずにそのまま使っても良かったのだが、ローカル開発となるべく同じコードにしたかったのでこのような実装にした。
CDK
cdk/lib/cdk-stack.ts
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { GoFunction } from "@aws-cdk/aws-lambda-go-alpha";
import { Rule, Schedule } from "aws-cdk-lib/aws-events";
import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
import { Role, ServicePrincipal, ManagedPolicy } from "aws-cdk-lib/aws-iam";
export class CdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const executionLambdaRole = new Role(this, "SolologLambdaExecutionRole", {
roleName: "sololog-lambda-execution-role",
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
managedPolicies: [
ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AWSLambdaBasicExecutionRole"
),
ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMReadOnlyAccess"),
],
});
const lambda = new GoFunction(this, "handler", {
entry: "../app",
role: executionLambdaRole,
});
new Rule(this, "scheduleRule", {
schedule: Schedule.cron({ minute: "0", hour: "16", day: "1" }),
targets: [new LambdaFunction(lambda, { retryAttempts: 3 })],
});
}
}
Lambda からパラメータストアを読み取る必要があるので読み取り権限を付与したロールを作成する。
また EventBridge で毎月一日に Cron 実行するルールを作成し、Lambda にくっつける。
実行
cdk deploy
でデプロイ後、Lambda のテスト実行でコードの実行を確認できる。
またテスト用に EventBridge の設定を schedule: Schedule.cron({ minute: "0" })
などとしてデプロイしておくと cron 実行も確認できる。
参考文献
- AWS Lambda と Parameter Store の環境を CDK で構築する
- AWS CDK で EventBridge + Lambda で定期実行処理(バッチ処理)を実装してみた
- GolangでAWS Systems Managerパラメータストアを利用する
- https://docs.aws.amazon.com/cdk/api/v2/
以上