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
【Developers.IO 2020 CONNECT】AWS CDK + Step Func...
Search
Sato Naoya
July 03, 2020
Programming
3.3k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
【Developers.IO 2020 CONNECT】AWS CDK + Step Functions 入門
Sato Naoya
July 03, 2020
More Decks by Sato Naoya
See All by Sato Naoya
Cloudflare AgentsとAI SDKでAIエージェントを作ってみた
briete
0
1.1k
Cloudflare Workersのユースケースと開発方法
briete
0
3.9k
re:Invent 2019 サーバーレス関連アップデート
briete
0
1.1k
Other Decks in Programming
See All in Programming
Laravelで学ぶ Webアプリケーションチューニング入門/web_application_tuning_101
hanhan1978
4
1.7k
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
670
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.4k
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.4k
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
220
Built Our Own Background Agent at LayerX
layerx
PRO
9
5k
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
180
【やさしく解説 設計編・中級 #6】良いアーキテクチャとは ~ 一本の登り道の、行き先 ~
panda728
PRO
0
210
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
240
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
330
プロポーザルを書いてもらう
pvcresin
0
280
Lean は証明の正しさを確認するためだけのツールって思ってませんか?
inoueasei
1
150
Featured
See All Featured
Design in an AI World
tapps
1
280
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
480
Navigating Team Friction
lara
192
16k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
730
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
460
First, design no harm
axbom
PRO
2
1.2k
AI: The stuff that nobody shows you
jnunemaker
PRO
9
890
A Modern Web Designer's Workflow
chriscoyier
698
190k
A better future with KSS
kneath
240
18k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
119
120k
Transcript
AWS CDK + Step Functions ⼊⾨ 2020/7/2 Developers.IO 2020 CONNECT
クラスメソッド株式会社 CX事業本部 佐藤直哉
2 このセッションについて • AWS Step Functionsの簡単な概要 • AWS CDKの簡単な概要 •
AWS CDK と Step Functionsを使ったステートマシンの 実装⽅法について • ⾔語はTypeScript、実⾏基盤は AWS Lambdaを前提とし ています。
3 ⾃⼰紹介 クラスメソッド株式会社 CX事業本部 MAD(Modern Application Development)チーム サーバーサイドエンジニア 佐藤直哉(Sato Naoya)
4 アジェンダ l AWS Step Functionsとは l AWS CDKの登場 l
ステートマシンにおけるAWS CDKの実装⽅法につ いて
5 AWS Step Functionsとは
6 AWS Step Functionsとは
7 AWS StepFunctionsとは l サーバーレスなワークフロー処理を作成することが できるサービス l ステートマシン l ワークフロー全体の処理のこと
l ステートマシン⼀つ⼀つの処理単位のことをStateと呼ぶ l ユースケース l 複数のLambda関数を順次的に処理したい l アプリケーションのジョブ機能として使う l Lambda単体では処理しきれない⼤容量ファイルを並列 に処理する
8 ステートマシンの構成要素について
9 Stateとは l ステートマシンにおける 処理の単位のこと l 全部で7つの種類があり ます l Task
l Wait l Parallel l Pass l Choice l Succeed l Fail
10 Task 単⼀の処理を⾏う基本的な State l タスクの実⾏基盤として、AWS Lambda、ECS等を選択するこ とができます l 基本的には、このTaskを組み合
わせてステートマシンを構成し ていくことになります start end 最初の処理 次の処理
11 Pass 前stateのoutputをそのままパ ススルーするstate l デバッグ⽤途で使うことが多い l 前stateのoutput JSONがその まま流れてくるので、その値を
確認したりするのに使う l とりあえず、全体のステートマ シンをPassで定義して、あとか らPassをTaskに置き換えていく という⽅法も取れる start end 処理 Pass
12 Wait 最初の処理 Start End 10秒待つ 最後の処理 指定された時間を待機する State l
StateとStateの間に⼊り、指定 された時間待機する
13 Parallel 並列に処理を実⾏するState l 複数のTask(Lambda)を並列 に処理させることができる l Parallel内の全てのStateが実⾏ されたら処理3に遷移する 並列処理1
並列処理2 start end 処理3
14 Choice 条件により分岐するState l IF⽂のように条件によって分岐 させるState l 処理1のoutputを受け取り、 ChoiceStateはその値により、 分岐させます
処理1 ChoiceState 処理2 処理3 処理4 start end
15 Succeed, Fail 成功か失敗かを定義するState l 前のChoiceと組み合わせて、 Choiceの結果に合わせて、ス テートマシンが成功したか失敗 したかをマークするなどで使う l
Succeed、Failに到達した段階 でステートマシンは終了する ChoiceState 処理 Succeed 処理 Fail start end
16 Map 動的並列処理を⾏うState l inputに配列を受け取り、配列 の数だけ処理を繰り返すState start 処理1 処理2
17 ASL(Amazon State Language) ASLと呼ばれるJSONベー スの⾔語を使ってステー トマシンを定義
18 ASLの⾟み l JSON形式の⾔語のため、あ る程度処理が複雑化してくる と、処理を追うのが⼤変にな る l プログラミング⾔語ではない ため、ある程度の複雑さがあ
ると可読性が悪くなってしま う
19 そこでAWS CDKが登場します
20 AWS CDKとは
21 AWS CDKとは l TypeScriptやPythonといったプログラミング⾔語を 使ってAWSリソースを定義する事ができるツール l Constructというライブラリを使うことで、 CloudFormationよりも少ない⾏数で記述が可能
22 Constructとは https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html
23 AWS CDKのメリット l 使い慣れたプログラミング⾔語でAWSリソースを定 義することができる l IDEの恩恵を受けることができる l CloudFormationや独⾃⾔語(今回の場合だとASL)
がConstructによって抽象化されているため、通常よ りも少ない記述量でリソースを定義することができ ます
24 AWS CDKにおけるステートマシンの実装⽅ 法について
25 AWS CDKプロジェクトの作成
26 AWS CDKのインストール npm install –g aws-cdk
27 CDKプロジェクトの作成 mkdir stepfunctions-sample cd stepfunction-sample cdk init app –language=typescript
28 ディレクトリ構成
29 AWS CDK Constructのインストール npm install –d @aws-cdk/aws-lambda npm install
–d @aws-cdk/aws-stepfunctions npm install –d @aws-cdk/aws-stepfunction-tasks
30 Lambda(タスク)のサンプルコード handlers/task.ts export async function handler(event: any): Promise<TaskResponse> {
console.log(JSON.stringify(event)); return { title: 'Hello’, message: 'World’, }; } type TaskResponse = { title: string; message: string; }
31 スタックのコード lib/stepfunction-sample-stack.ts import * as cdk from '@aws-cdk/core'; import
* as lambda from '@aws-cdk/aws-lambda'; import * as sfn from '@aws-cdk/aws-stepfunctions'; import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; export class StepfunctionsSampleStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // ここにAWSリソースを定義していく } }
32 スタックのコード lib/stepfunction-sample-stack.ts import * as cdk from '@aws-cdk/core'; import
* as lambda from '@aws-cdk/aws-lambda'; import * as sfn from '@aws-cdk/aws-stepfunctions'; import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; export class StepfunctionsSampleStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); } } 先程インストールした、Constructライブラ リをimportします。
33 ステートマシンの基本的な実装⽅法
34 Taskの順次処理(Next) l 基本的なNextでタスク同⼠を順 次処理させる⽅法です。 l AWS CDKでは .next() を使う
ことで簡単にタスクをつなげる ことができます。 start end 最初の処理 次の処理
35 Taskの順次処理(Next) lib/stepfunctions-sample-stack.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, });
36 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); タスクの処理を実⾏する Lambda関数を作成します
37 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); Taskを定義します。
38 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); Taskを定義します。 aws-stepfunctions-tasksライブラリのクラスを 使うことで、Lambdaを実⾏基盤としたタス クを定義することができます。
39 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); Taskを定義します。 lambdaFunctionsに上で定義したtaskFnインス タンスを渡します。
40 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); Taskを定義します。 outputPath には Taskの output を指定します。 $.Payload を指定することで, Lambdaの戻り 値を次のTaskに渡すことができます
41 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); Taskを定義します。 inputPath にはoutputPathから何を Taskの input とするかを指定します。 $とすることで、上のTaskのJSONがすべて Inputに渡ることになります。
42 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); Taskを .next() でつなげます。
43 Taskの順次処理(Next) lib/stepfunctions-sample.ts const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler’, }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload’, }); const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); ステートマシンを作成します。
44 デプロイ npm run build npm run cdk deploy
45 デプロイされたステートマシン図
46 他のStateについても実装してみます
47 Wait(再掲) 最初の処理 Start End 10秒待つ 最後の処理 指定された時間を待機する State この例だと、最初の処理が終わっ
てから、10秒後に最後の処理が実 ⾏されることになります。
48 Wait(AWS CDKで実装) const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload', }); const wait10 = new sfn.Wait(this, '10秒待つ', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)), }) const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(wait10).next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); lib/stepfunctions-sample-stack.ts Wait Stateを定義して、WatiTimeクラスの durationを使って秒数を指定します
49 Wait(AWS CDKで実装) const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const firstState = new tasks.LambdaInvoke(this, '最初の処理', { lambdaFunction: taskFn, outputPath: '$.Payload', }); const wait10 = new sfn.Wait(this, '10秒待つ', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)), }) const secondState = new tasks.LambdaInvoke(this, '次の処理', { inputPath: '$.message’, lambdaFunction: taskFn, }); const definition = firstState.next(wait10).next(secondState); new sfn.StateMachine(this, 'stateMachine', { definition: definition, }); lib/stepfunctions-sample-stack.ts 先程と同じく.nextでつなげます。
50 デプロイ
51 Parallel(再掲) 並列に処理を実⾏するState 並列処理1 並列処理2 start end 処理3
52 Parallel(AWS CDKで実装) const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const paralellState1 = new tasks.LambdaInvoke(this, '並列処理1', { lambdaFunction: taskFn, }); const paralellState2 = new tasks.LambdaInvoke(this, '並列処理2', { lambdaFunction: taskFn, }); const wait10 = new sfn.Wait(this, '10秒待つ', { time: sfn.WaitTime.duration(cdk.Duration.minutes(10)), }) const parallel = new sfn.Parallel(this, 'Parallel'); parallel.branch(paralellState1, paralellState2).next(wait10); new sfn.StateMachine(this, 'stateMachine', { definition: parallel, }); lib/stepfunctions-sample-stack.ts
53 Parallel(AWS CDKで実装) const taskFn = new lambda.Function(this, 'TaskFn', {
runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const paralellState1 = new tasks.LambdaInvoke(this, '並列処理1', { lambdaFunction: taskFn, }); const paralellState2 = new tasks.LambdaInvoke(this, '並列処理2', { lambdaFunction: taskFn, }); const wait10 = new sfn.Wait(this, '10秒待つ', { time: sfn.WaitTime.duration(cdk.Duration.minutes(10)), }) const parallel = new sfn.Parallel(this, 'Parallel'); parallel.branch(paralellState1, paralellState2).next(wait10); new sfn.StateMachine(this, 'stateMachine', { definition: parallel, }); lib/stepfunctions-sample-stack.ts branch()メソッドで、並列処理するstate を指定します。
54 デプロイ
55 Choice(再掲) 条件により分岐するState 処理1 ChoiceState 処理2 処理3 処理4 start end
56 Choice(AWS CDKで実装) lib/stepfunctions-sample-stack.ts const taskFn = new lambda.Function(this, 'TaskFn',
{ runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const task = new tasks.LambdaInvoke(this, '処理', { lambdaFunction: taskFn, outputPath: '$.Payload', }); const choice = new sfn.Choice(this, 'ChoiceState'); choice.when(sfn.Condition.stringEquals('$.message', 'Hello'), new sfn.Pass(this, '処理1')); choice.when(sfn.Condition.stringEquals('$.message', 'World'), new sfn.Pass(this, '処理2')); choice.otherwise(new sfn.Pass(this, '処理3')); const definition = task.next(choice); new sfn.StateMachine(this, 'stateMachine', { definition });
57 Choice(AWS CDKで実装) lib/stepfunctions-sample-stack.ts const taskFn = new lambda.Function(this, 'TaskFn',
{ runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const task = new tasks.LambdaInvoke(this, '処理', { lambdaFunction: taskFn, outputPath: '$.Payload', }); const choice = new sfn.Choice(this, 'ChoiceState'); choice.when(sfn.Condition.stringEquals('$.message', 'Hello'), new sfn.Pass(this, '処理1')); choice.when(sfn.Condition.stringEquals('$.message', 'World'), new sfn.Pass(this, '処理2')); choice.otherwise(new sfn.Pass(this, '処理3')); const definition = task.next(choice); new sfn.StateMachine(this, 'stateMachine', { definition }); when()メソッドで、分岐条件を定義します
58 Choice(AWS CDKで実装) lib/stepfunctions-sample-stack.ts const taskFn = new lambda.Function(this, 'TaskFn',
{ runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const task = new tasks.LambdaInvoke(this, '処理', { lambdaFunction: taskFn, outputPath: '$.Payload', }); const choice = new sfn.Choice(this, 'ChoiceState'); choice.when(sfn.Condition.stringEquals('$.message', 'Hello'), new sfn.Pass(this, '処理1')); choice.when(sfn.Condition.stringEquals('$.message', 'World'), new sfn.Pass(this, '処理2')); choice.otherwise(new sfn.Pass(this, '処理3')); const definition = task.next(choice); new sfn.StateMachine(this, 'stateMachine', { definition }); Conditionクラスを使って条件を記述します この場合は、前のタスクから渡されてきた $.PayloadのmessageがHelloという⽂字列なら 次の引数のStateに遷移するという意味にな ります。
59 Choice(AWS CDKで実装) lib/stepfunctions-sample-stack.ts const taskFn = new lambda.Function(this, 'TaskFn',
{ runtime: lambda.Runtime.NODEJS_12_X, code: lambda.Code.fromAsset('handlers’), handler: 'task.handler', }); const task = new tasks.LambdaInvoke(this, '処理', { lambdaFunction: taskFn, outputPath: '$.Payload', }); const choice = new sfn.Choice(this, 'ChoiceState'); choice.when(sfn.Condition.stringEquals('$.message', 'Hello'), new sfn.Pass(this, '処理1')); choice.when(sfn.Condition.stringEquals('$.message', 'World'), new sfn.Pass(this, '処理2')); choice.otherwise(new sfn.Pass(this, '処理3')); const definition = task.next(choice); new sfn.StateMachine(this, 'stateMachine', { definition }); otherwise()で条件にあてはまらなかった場合 のstateの遷移先を指定します。
60 デプロイ
61 まとめ l AWS CDKを使うことで、JSONベースなASLを書か なくとも、TypeScriptやPythonのようなプログラミ ング⾔語でStep Functionsのワークフローを書くこ とができる l
ASLで書くよりも直感的に実装できる
62 参考⽂献 l https://docs.aws.amazon.com/cdk/api/latest/ docs/aws-stepfunctions-readme.html l https://docs.aws.amazon.com/cdk/api/latest/ docs/aws-stepfunctions-tasks-readme.html
None