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.2k
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
890
Cloudflare Workersのユースケースと開発方法
briete
0
3.8k
re:Invent 2019 サーバーレス関連アップデート
briete
0
1.1k
Other Decks in Programming
See All in Programming
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
200
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
4
1.4k
タクシーアプリ『GO』の バックエンド開発のおける AI利活用と若者のすべて
pyama86
3
2k
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
500
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
780
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
250
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
140
3Dシーンの圧縮
fadis
1
770
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.6k
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
400
OSもどきOS
arkw
0
570
Oxlintのカスタムルールの現況
syumai
6
1.1k
Featured
See All Featured
Amusing Abliteration
ianozsvald
1
200
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
840
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Chasing Engaging Ingredients in Design
codingconduct
0
220
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
270
The Spectacular Lies of Maps
axbom
PRO
1
810
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
230
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
How to build a perfect <img>
jonoalderson
1
5.7k
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