Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
DynamoDBの"Replacement"時にデータが消されないようにCustom Reso...
Search
morimorikochan
October 31, 2024
Technology
1.3k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
DynamoDBの"Replacement"時にデータが消されないようにCustom Resource Provider Frameworkでカスタムリソース作ってみた件
"クラスメソッドのCDK事情大公開スペシャル#1" の際に登壇した内容です
https://classmethod.connpass.com/event/332020/
morimorikochan
October 31, 2024
More Decks by morimorikochan
See All by morimorikochan
実装だけじゃない! CCA-F取得エンジニアが教えるClaude Code開発プロセス活用術
diggymo
2
900
Claude in Chromeで始める自律的フロントエンド開発
diggymo
1
1k
HonoとJSXを使って管理画面をサクッと型安全に作ろう
diggymo
0
500
バッチ処理で悩むバックエンドエンジニアに捧げるAWS Glue入門
diggymo
3
730
LIFF CLIとngrokを使ったLIFF/LINEミニアプリのお手軽実機確認
diggymo
0
1k
TypeScriptでモジュラーモノリスやってみた
diggymo
0
640
過去のインプットとアウトプットを振り返る
diggymo
0
420
Amazon BedrockとPR-Agentでコードレビュー自動化に挑戦・実際に運用してみた
diggymo
0
3k
個人開発でLIFFとMessagingAPIを使ってわかった5つのこと
diggymo
0
1.6k
Other Decks in Technology
See All in Technology
SREとQA 二人三脚で進めるSLO運用/sre-qa-slo
sugitak
0
1.2k
副作用のある Lambda でも Lambda Power Tuning は使えるのか / lambda-power-tuning-side-effects
koukihosaka
1
130
OpenTelemetryにおけるGoのゼロコード・コンパイル時計装について #fukuokago
quiver
0
190
Playwright × AI Agent でE2Eテストはどう変わるか AI駆動テストの可能性と実用検証の結果
taiga7543
2
760
AI時代におけるエンジニアの新たな役割──FDEとクオリアの探求/登壇資料(戸井田 裕貴)
hacobu
PRO
0
290
インフラと開発の垣根を超えていき!〜元AWSインフラエンジニアがAWS開発で奮闘している話〜
hatahata021
3
390
穢れた技術選定について
watany
19
6k
41歳でAWSが好きすぎてITエンジニアになったおっさんの話
yama3133
1
720
Making sense of Google’s agentic dev tools
glaforge
1
300
Kaggleで成長するために意識したこと
prgckwb
2
440
生成 AI 時代にいま一度「問い合わせ」について考えてみる
kazzpapa3
1
110
[Droidcon Orlando '26] The Android Lens: Applying Mobile Forensics to AI Performance
amanda_hinchman
1
100
Featured
See All Featured
Prompt Engineering for Job Search
mfonobong
0
380
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
610
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
390
What does AI have to do with Human Rights?
axbom
PRO
1
2.3k
Mobile First: as difficult as doing things right
swwweet
225
10k
Skip the Path - Find Your Career Trail
mkilby
1
170
The Spectacular Lies of Maps
axbom
PRO
1
870
Un-Boring Meetings
codingconduct
0
350
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1k
Rails Girls Zürich Keynote
gr2m
96
14k
Discover your Explorer Soul
emna__ayadi
2
1.2k
Transcript
DynamoDBの"Replacement"時にデータ が消されないように Custom Resource Provider Frameworkで カスタムリソース作ってみた件 クラスメソッド株式会社 リテールアプリ共創部 マッハチーム
morimorikochan
名前 morimorikochan 所属 クラスメソッド株式会社 リテールアプリ共創部 マッハチーム🚀 趣味 Switchのゲーム X @marooon88 ⼀⾔
中古7万の椅⼦でQoL爆上 ⾃⼰紹介
1. 結論 2. 問題提起 3. Custom Resources 4. Custom Resource
Provider Framework 5. 実装した 6. まとめ 内容
• CDKでDynamoDBのテーブル置換時、テーブルのデータが全件削除され て困っていた • CDKのcustomresources.Provider(通称Custom Resource Provider Framework)を使って新テーブルへのコピーを⾃動で⾏えるようにした • 処理時間も早く、CIへの影響も少ない
• 課題 ◦ Lambda関数のIAMロールがちょっとガバってしまう ◦ レースコンディション発⽣する 📚結論
DynamoDBのPrimaryKey/SortKeyこんな感じやろか とりあえず cdk deploy して開発開始や! ⸻⸻数⽇後⸻⸻ PrimaryKey/SortKey間違ってたわ、直して
cdk deploy っと... ほなさいなら...(データ全削除) うわあぁぁぁぁぁぁ動作確認⽤のデータが消えたあぁぁぁぁぁぁ 🤨こんなことないですか
🤨こんなことないですか
🤨こんなことないですか
📚こんなことないですか 🤔 CDKの⼒でなんとかならん?
📚こんなことないですか 💡 Custom Resource Provider Framework
カスタムリソースを使⽤すると、CloudFormation テンプレートにカスタムプロビジョニン グロジックを記述し、スタックを作成、更新 (カスタムリソースを変更した場合)、または削 除するたびに CloudFormation にそのロジックを実⾏させることができます。これは、プロ ビジョニング要件に、CloudFormation の組み込みリソースタイプでは表現できない複雑な ロジックやワークフローが含まれる場合に役⽴ちます。
カスタムリソースプロバイダーの定義⽅法 • SNS ◦ 1. メッセージが送られる ◦ 2. SNSのバックエンド側で受信し処理 ◦ 3. バックエンド側がS3にファイルをPUTし応答する • Lambda ◦ 1. Lambda関数が実⾏される ◦ 2. Lambda関数内で処理 ◦ 3. Lambda関数内でS3にファイルをPUTし応答する 🤔Custom Resourcesとは?
CDKでの定義⽅法は4種類 1. sns.Topic ◦ 前ページの処理を⾏うSNSを定義 2. lambda.Function ◦ 前ページの処理を⾏うLambdaを定義 3.
core.CustomResourceProvider ◦ 2を使いやすくした便利ラッパー(?) ◦ エラーハンドリングや応答をLambda関数の結果から⾃動で⾏ってくれる ◦ 15分のタイムアウト制限がある ◦ アプリケーション実装者には推奨されていない 4. customresources.Provider(Custom Resource Provider Framework) ◦ 3をさらに使いやすくした便利ラッパー(?) ◦ 別途“処理が終わったかどうかを判定する”ためのLambda関数 (isCompleteHandler)を定義可能なので、実質15分のタイムアウトがない >aws-cdk-lib module · AWS CDK 🤔CDKでどうやってCustom Resourcesを定義する?
🤔カスタムリソースプロバイダーにCRPFを使った場合 1. CloudFormation実⾏中にLambda関数が呼び出され、 同時にカスタムリソースが作成中/更新中/削除中になる 2. Lambda関数が応答する 3. カスタムリソースが完了状態になる ※isCompleteHandlerを利⽤しない場合
• DynamoDBがリソース置換されたことをカスタムリソースが検知し • Lambda関数を実⾏させる • Lambda関数内では以下の処理を⾏う ◦ 1. 旧テーブルからScanして全アイテムを取得 ◦
2. 新テーブルに全アイテムをBatchWriteItem この⽅法の他にも、AWSのAPI経由で旧テーブルからS3へコピーしそれを新 テーブルへコピーする⽅法もあったが⾒送り • 処理時間がかかる • DMSがややこしそう(DMSエアプ) 💡今回の課題へ適⽤すると...
const lambdaFunction = new nodejsLambda.NodejsFunction(/*略*/) lambdaFunction.addToRolePolicy( new iam.PolicyStatement({ effect: iam.Effect.ALLOW,
actions: ["dynamodb:Scan"], resources: ["*"], }) ); props.ddbTable.grantWriteData(lambdaFunction); const provider = new cr.Provider(this, "CustomResourceProvider", { onEventHandler: lambdaFunction, }); new cdk.CustomResource(this, "CustomResource", { serviceToken: provider.serviceToken, properties: { tableName: props.ddbTable.tableName, } as ResourceProperties, }); 利⽤イメージ(CDK側)
const lambdaFunction = new nodejsLambda.NodejsFunction(/*略*/) lambdaFunction.addToRolePolicy( new iam.PolicyStatement({ effect: iam.Effect.ALLOW,
actions: ["dynamodb:Scan"], resources: ["*"], }) ); props.ddbTable.grantWriteData(lambdaFunction); const provider = new cr.Provider(this, "CustomResourceProvider", { onEventHandler: lambdaFunction, }); new cdk.CustomResource(this, "CustomResource", { serviceToken: provider.serviceToken, properties: { tableName: props.ddbTable.tableName, } as ResourceProperties, }); 利⽤イメージ(CDK側) const originalTable = new dynamodb.Table(/* 略 */) new DynamoDbTableItemsRestorer(this,'OriginalTableItemsRestorer',{ ddbTable: originalTable }) 利⽤例
テーブルが置き換わる場合(=物理IDが変化した場合)のみ Lambdaを実⾏したい 🤔Lambda関数どう実装する? テーブルの変化 旧テーブルから新テーブルへ コピーさせるか テーブル作成時 ❌ テーブル更新時 (置換なし)
❌ テーブル更新時 (置換あり) テーブル削除時 ❌
/** Lambdaのエントリーポイント */ export const handler: CdkCustomResourceHandler<ResourceProperties> = async (event)
=> { logger.info("リソースが変化しました ", {event}); switch (event.RequestType) { case "Update": await copyAllItems({ fromTableName: event.OldResourceProperties.tableName, newTableName: event.ResourceProperties.tableName, }); return { PhysicalResourceId: event.ResourceProperties.tableName }; case "Create": case "Delete": return {}; } }; 利⽤イメージ(Lambda側)
/** Lambdaのエントリーポイント */ export const handler: CdkCustomResourceHandler<ResourceProperties> = async (event)
=> { logger.info("リソースが変化しました ", {event}); switch (event.RequestType) { case "Update": await copyAllItems({ fromTableName: event.OldResourceProperties.tableName, newTableName: event.ResourceProperties.tableName, }); return { PhysicalResourceId: event.ResourceProperties.tableName }; case "Create": case "Delete": return {}; } }; 利⽤イメージ(Lambda側) new cdk.CustomResource(this, "CustomResource", { serviceToken: provider.serviceToken, properties: { tableName: props.ddbTable.tableName, } as ResourceProperties, });
前回からPhysicalResourceId(物理ID)変化させた場合 • CloudFormationが”カスタムリソースが置換された”と認識する ◦ もしロールバックが発⽣した場合はCloudFormationがDeleteを実⾏する 前回から変化させなかった場合 • CloudFormationが”カスタムリソースが更新された”と認識する ◦ もしロールバックが発⽣した場合はCloudFormationが
パラメータを逆にしてUpdateを実⾏し、元の状態に戻そうとする 今回の要件では、ロールバック時に処理をさせる必要はないのでコードがシ ンプルになるよう”PhysicalResourceIdを変化させる” Update時に返却する物理IDについて
const copyAllItems = async (props: { fromTableName: string, newTableName: string,
} ) => { logger.info("データをコピーします ", {fromTableName: props.fromTableName, newTableName: props.newTableName}); const oldTableReadableStream = new DynamoDBReadableStream(ddbClient, props.fromTableName); const newTableWritableStream = new DynamoDBWritableStream(ddbClient, props.newTableName); await pipeline(oldTableReadableStream, newTableWritableStream) if (newTableWritableStream.errorChunks.length > 0) { logger.error("コピーに失敗したアイテムがあります ", {errorChunks: newTableWritableStream.errorChunks}) throw new Error(`${newTableWritableStream.errorChunks.length}件のデータをコピーでき ませんでした `) } } 利⽤イメージ(Lambda側)
💪実⾏してみた テーブルの置換
💪実⾏してみた カスタムリソース(Lambda) のポリシー変更
💪実⾏してみた カスタムリソースが実⾏されてる 物理IDが変化しているので、 カスタムリソースが置換されたと 認識されてる
💪実⾏してみた Lambda関数の処理時間 • Item数が少ない場合はだいたい10秒とか • これぐらいならCIへの影響が少ない Lambda関数のIAMロールがちょっとガバってしまう • CDK上で旧テーブル名を保持していないため •
SSM使えばできそうですけど 複雑にしたくない レースコンディション発⽣する(当然) • コピーの途中に旧テーブルにPutItemされると、そのデータは新テーブルにコピーされ ない可能性がある • 本番環境で利⽤する際は、メンテナンスモードなど検討必要 lambdaFunction.addToRolePolicy( new iam.PolicyStatement({ resources: ["*"], }) );
📚まとめ • CDKでDynamoDBのテーブル置換時、テーブルのデータが全件削除され て困っていた • CDKのcustomresources.Provider(通称Custom Resource Provider Framework)を使って新テーブルへのコピーを⾃動で⾏えるようにした •
処理時間も早く、CIへの影響も少ない • 課題 ◦ Lambda関数のIAMロールがちょっとガバってしまう ◦ レースコンディション発⽣する
📚資料 作成したコード • https://github.com/diggymo/ddb-table-item-restorer 参考資料 • aws-cdk-lib module · AWS
CDK ◦ https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.htm l#custom-resources • CDK で Custom resources を作成する|伊藤忠テクノソリューションズ ◦ https://www.ctc-g.co.jp/solutions/cloud/column/article/84.html
ありがとうございました 🫠おわり