Slide 1

Slide 1 text

"84 ͰαʔόʔϨεͳ -*/&#PU-*''ΞϓϦ؀ڥ Λ*B$ ͳײ͡Ͱߏங͢ΔΑʂ -*/&%FWFMPQFS$PNNVOJUZ αʔόϨεʷ-*/&ͰΞϓϦ։ൃͯ͠Έͨ-5 4VNJIJSP ,BHBXB

Slide 2

Slide 2 text

ࣗݾ঺հ

Slide 3

Slide 3 text

Ճ઒ ੅ኍʢ͔͕Θ ͢ΈͻΖʣ n 5XJUUFS l !TVNJIJSP n ډॅ஍ l ฌݿݝ n ৬ۀ l ίϯαϧˍΤϯδχΞ n ͦͷଞଐੑ l -*/&"1*&YQFSU l -*/& ք۾ͷΠϕϯτ΍ϋοΧιϯ౳ʹΑ͘ग़຅͠·͢ l "84 ΛΑ͘࢖͍·͢ Ø ͕ɺ࠷ۙ͸($1 ͕޷͖͔΋͆ 3

Slide 4

Slide 4 text

MJOFED MEHL MEHR n ։ൃऀίϛϡχςΟͰϋϯζΦϯߨࢣͳͲΛ͍ͯ͠·͢ 4 -*/&%FWFMPQFS $PNNVOJUZ ʢ౦ژʣ -*/&%FWFMPQFS (SPVQ,BOTBJ ʢؔ੢ʣ -*/&%FWFMPQFS (SPVQ,ZVTIV ʢ۝भʣ

Slide 5

Slide 5 text

࣍ճΠϕϯτొஃ͠·͢ʂ https://linedevelopercommunity.connpass.com/event/176924/

Slide 6

Slide 6 text

ެࣜ4%, ͕ແ͍ͷͰ࡞ͬͪΌ͍·ͨ͠ -*/&1BZ"1*4%,GPS1ZUIPO 6 https://pypi.org/project/line-pay/ $ pip install line-pay

Slide 7

Slide 7 text

Ϋϥ΢υ αʔόʔϨε -*/& ຊ೔ͷςʔϚ

Slide 8

Slide 8 text

ݸਓతʹ޷͖ͳαʔόʔϨε؀ڥ n(PPHMF$MPVE1MBUGPSN'JSFCBTF 8 Google App Engine

Slide 9

Slide 9 text

ݸਓతʹ޷͖ͳαʔόʔϨε؀ڥ n"NB[PO8FC4FSWJDFT 9 Amazon Simple Storage Service Amazon DynamoDB Amazon API Gateway Amazon Simple Queue Service AWS Lambda Amazon CloudFront

Slide 10

Slide 10 text

ݸਓతʹ޷͖ͳαʔόʔϨε؀ڥ nLJOUPOF 10

Slide 11

Slide 11 text

Ϋϥ΢υͷ؀ڥߏங Ͳ͏͍ͯ͠·͔͢ʁ

Slide 12

Slide 12 text

ख࡞ۀʁ n ドキュメントやQiita 記事を⾒ながら︖ ຖճɺؒҧΘͣʹ΍Δͷ͸େม 12

Slide 13

Slide 13 text

ຖճख࡞ۀ͸ແཧʂ ࢲɺࣦഊͪ͠Ό͏ͷͰ 13

Slide 14

Slide 14 text

΍ͬͺΓࣗಈԽʂ n サーバーレスだし⾃動化したい︕ Πϯϑϥ͸Ϛωʔδυͳͷʹߏங͸खಈͳΜͯΠϠͩʂ 14

Slide 15

Slide 15 text

ͦ͜Ͱ *B$

Slide 16

Slide 16 text

*OGSBTUSVDUVSFBT$PEF *B$ ͱ͸ n8JLJQFEJB l *OGSBTUSVDUVSFBT$PEFʢ*B$ʣ ͸ίϯϐϡʔςΟ ϯάɾΠϯϑϥʢϓϩηεɺϕΞϝλϧαʔόʔɺԾ ૝αʔόʔͳͲʣͷߏ੒؅ཧɾػցॲཧՄೳͳఆٛ ϑΝΠϧͷઃఆɾϓϩϏδϣχϯάΛࣗಈԽ͢Δϓϩ ηεͰ͋Δɻ 16 https://ja.wikipedia.org/wiki/Infrastructure_as_Code

Slide 17

Slide 17 text

"84Y*B$ ͱݴ͑͹ n"84$MPVE'PSNBUJPO $'O l ϓϩάϥϛϯάݴޠ·ͨ͸γϯϓϧͳςΩετϑΝΠ ϧΛ࢖༻ͯ͠ɺ͋ΒΏΔϦʔδϣϯͱΞΧ΢ϯτͰΞ ϓϦέʔγϣϯʹඞཁͱ͞ΕΔ͢΂ͯͷϦιʔεΛɺ ࣗಈԽ͞Εͨ҆શͳํ๏ͰϞσϧԽ͠ɺϓϩϏδϣχ ϯάͰ͖·͢ɻ͜Ε͸ɺ"84ͱαʔυύʔςΟ੡ͷ Ϧιʔεʹਅʹ୯ҰͷιʔεΛ༩͑·͢ɻ 17 https://aws.amazon.com/jp/cloudformation/

Slide 18

Slide 18 text

$MPVE'PSNBUJPOͱݴ͑͹ nઃఆϑΝΠϧʁ l :".- l +40/ 18 AWSTemplateFormatVersion: '2010-09-09' Description: Lambda function with cfn-response. Resources: primer: Type: AWS::Lambda::Function Properties: Runtime: nodejs12.x Role: arn:aws:iam::123456789012:role/lambda-role Handler: index.handler Code: ZipFile: | var aws = require('aws-sdk') var response = require('cfn-response') exports.handler = function(event, context) { console.log("REQUEST RECEIVED:¥n" + JSON.stringify(event)) // For Delete requests, immediately send a SUCCESS response. if (event.RequestType == "Delete") { response.send(event, context, "SUCCESS") return } var responseStatus = "FAILED" var responseData = {} var functionName = event.ResourceProperties.FunctionName var lambda = new aws.Lambda() lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) { if (err) { responseData = {Error: "Invoke call failed"} console.log(responseData.Error + ":¥n", err) } else responseStatus = "SUCCESS" response.send(event, context, responseStatus, responseData) }) } Description: Invoke a function during stack creation. TracingConfig: Mode: Active ͢Έ·ͤΜɻਖ਼௚ۤखͰ͢ʜ N @@ N

Slide 19

Slide 19 text

αʔόʔϨε ϑϨʔϜϫʔΫ ͷग़൪ͩʂ

Slide 20

Slide 20 text

4FSWFSMFTT'SBNFXPSL ͱ͸ n4FSWFSMFTT'SBNFXPSL l 5IF4FSWFSMFTT'SBNFXPSLHJWFTZPV FWFSZUIJOHZPVOFFEUPEFWFMPQ EFQMPZ NPOJUPSBOETFDVSFTFSWFSMFTTBQQMJDBUJPOT POBOZDMPVE 20 https://www.serverless.com/

Slide 21

Slide 21 text

4FSWFSMFTT'SBNFXPSL ͱ͸ l &BTZ:".- $-* EFWFMPQNFOU BOEEFQMPZNFOU UP"84 "[VSF (PPHMF$MPVE ,OBUJWF NPSF 21 service: myService provider: name: aws runtime: nodejs12.x memorySize: 512 timeout: 10 versionFunctions: false tracing: lambda: true functions: hello: handler: handler.hello name: ${self:provider.stage}-lambdaName description: Description of what the lambda function does runtime: python2.7 memorySize: 512 timeout: 10 provisionedConcurrency: 3 reservedConcurrency: 5 tracing: PassThrough ͢Έ·ͤΜɻਖ਼௚ۤखͰ͢ʜ N @@ N

Slide 22

Slide 22 text

ͦ͜Ͱ "84$%,

Slide 23

Slide 23 text

"84$%,ͱ͸ n"84$MPVE%FWFMPQNFOU,JU l "84Ϋϥ΢υ։ൃΩοτ "84$%, ͸ɺ࢖͍׳ ΕͨϓϩάϥϛϯάݴޠΛ࢖༻ͯ͠Ϋϥ΢υΞϓϦ έʔγϣϯϦιʔεΛϞσϧԽ͓ΑͼϓϩϏδϣχϯ ά͢ΔͨΊͷΦʔϓϯιʔεͷιϑτ΢ΣΞ։ൃϑ ϨʔϜϫʔΫͰ͢ɻ 23 https://aws.amazon.com/jp/cdk/

Slide 24

Slide 24 text

"84$%, nରԠͨ͠ϓϩάϥϛϯάݴޠ l 1ZUIPO l 5ZQF4DSJQU l +BWB l /&5 $ 24 https://aws.amazon.com/jp/cdk/features/ ੩తܕ෇͖ݴޠʂ ͭ·Γɺ*%&ʹॿ͚ͯ΋Β͑Δʂ

Slide 25

Slide 25 text

"84$%,ͱ͸ n"84$MPVE%FWFMPQNFOU,JU l ʹҰൠެ։ Ø ղઆهࣄ͸·ͩগͳ͍ʢ2JJUB Ͱ໿౤ߘʣ l ࠓ͸ͪΐͬͱᙱ͍ॴʹख͕ಧ͔ͳ͍͔΋ʁ Ø *%& ʹΑΔิ׬ͷԸܙ͕ಘΒΕқ͍zIJHIFSMFWFM DPOTUSVDUTz͕ॱ࣍ϦϦʔε͞Ε͍ͯΔ l "1* ϦϑΝϨϯε͋Γ·͢ʢӳޠͷΈʣ Ø ຊࢿྉͰ͸WΛϕʔεʹઆ໌ 25 https://docs.aws.amazon.com/cdk/api/latest/

Slide 26

Slide 26 text

"84$%, n΋ͪΖΜ$-* ΋͋Γ·͢ʂ l DEL JOJU Ø ৽͍͠ΞϓϦέʔγϣϯΛ೚ҙͷݴޠͰॳظԽ l DEL TZOUI Ø "84$MPVE'PSNBUJPOςϯϓϨʔτʹίϯύΠϧ l DEL EFQMPZ Ø ΞϓϦέʔγϣϯΛσϓϩΠ l DEL EFTUSPZ Ø ΞϓϦέʔγϣϯΛ࡟আ 26 https://aws.amazon.com/jp/cdk/features/

Slide 27

Slide 27 text

࣮ࡍʹ n -*/&#PU-*''ΞϓϦͷαʔόʔϨε؀ڥΛߏஙʂ 27 Amazon Simple Storage Service Amazon DynamoDB Amazon API Gateway Amazon Simple Queue Service AWS Lambda Amazon CloudFront

Slide 28

Slide 28 text

-*/&#PU؀ڥ n-BNCEB "1*(BUFXBZ %ZOBNP%# 424 28 AWS Cloud AWS Lambda DynamoDB Table Bot Users Webhook AWS Lambda Reply kintone SQS Queue API Gateway Endpoint REST API DB Streams

Slide 29

Slide 29 text

DEL JOJU n·ͣ͸ΞϓϦͷॳظԽ l ॳظԽ͸ద౰ͳσΟϨΫτϦʹͯίϚϯυͰ0, Ø ΞϓϦͷςϯϓϨʔτ͕ల։͞ΕΔ - ࠓճ͸ 5ZQF4DSJQUͰʂ 29 $ mkdir cdk_sample && cd cdk_sample $ cdk init app --language=typescript cdk_sample/lib/CdkSampleStack.ts にリソース定義のコードを記述していく 使いたい言語を指定

Slide 30

Slide 30 text

%ZOBNP%# nςʔϒϧͷ࡞੒ 30 // Create User table const userTableName = 'BotWithLambdaUserTable' const userTable = new Table(this, userTableName, { tableName: userTableName, partitionKey: { name: 'id', type: AttributeType.STRING, }, readCapacity: 1, writeCapacity: 1, stream: StreamViewType.NEW_IMAGE, }) DynamoDB Stream の設定もこれだけ! PK の指定も明確!

Slide 31

Slide 31 text

-BNCEB n-BNCEB-BZFSͷ࡞੒ 31 // Create Lambda Layer const layerFunctionName = 'BotWithLambdaLayer' const layer = new LayerVersion(this, layerFunctionName, { layerVersionName: layerFunctionName, compatibleRuntimes: [Runtime.NODEJS_12_X], code: Code.fromAsset('dist'), })

Slide 32

Slide 32 text

-BNCEB n-BNCEB'VODUJPO<"1*>ͷ࡞੒ 32 const functionName = 'BotWithLambda' const apiLambdaFunction = new LambdaFunction(this, functionName, { functionName: functionName, handler: 'index.handler', -- 中略 -- environment: { REGION: process.env.CDK_DEFAULT_REGION || 'ap-northeast-1', ACCESS_TOKEN: process.env.ACCESS_TOKEN || '', CHANNEL_SECRET: process.env.CHANNEL_SECRET || '', USER_TABLE_NAME: userTable.tableName, }, layers: [layer], }) Layer の差し込みもこれだけ! 環境変数も 簡単に設定

Slide 33

Slide 33 text

-BNCEB n-BNCEB'VODUJPO<4USFBNT>ͷ࡞੒ 33 const dbStreamFunctionName = 'BotWithLambdaDbStream' const dbStreamLambdaFunction = new LambdaFunction( { -- 中略 -- handler: 'db_stream.handler', -- 中略 –environment: { REGION: process.env.CDK_DEFAULT_REGION || 'ap-northeast-1', KINTONE_API_URL: process.env.KINTONE_API_URL || '', KINTONE_APP_ID: process.env.KINTONE_APP_ID || '', KINTONE_API_TOKEN: process.env.KINTONE_API_TOKEN || '', }, layers: [layer], } )

Slide 34

Slide 34 text

-BNCEB 424 n&WFOU4PVSDF2VFVFͷ࡞੒ 34 // Dead letter queue const deadLetterQueue = new Queue(this, dlqName, {queueName: dlqName,}) // add Event source dbStreamLambdaFunction.addEventSource( new DynamoEventSource(userTable, { startingPosition: StartingPosition.TRIM_HORIZON, batchSize: 5, bisectBatchOnError: true, onFailure: new SqsDlq(deadLetterQueue), retryAttempts: 10, }) ) Event source の… (ry Queue の 作成も一行!

Slide 35

Slide 35 text

"1*(BUFXBZ n"1*(BUFXBZ&OEQPJOUͷ࡞੒ 35 // API Gateway const apiGwName = 'BotWithLambdaApiGW' const api = new LambdaRestApi(this, apiGwName, { restApiName: apiGwName, handler: apiLambdaFunction, proxy: false, }) api.root.addMethod('POST')

Slide 36

Slide 36 text

DEL CVJMEDEL EFQMPZ nߏஙίʔυ͕ग़དྷͨΒϏϧυˍσϓϩΠ 36 $ yarn build $ cdk synth $ cdk deploy CloudFormation テンプレートを確認できる

Slide 37

Slide 37 text

CVJMEEFQMPZ nσϓϩΠͷ༷ࢠΛோΊͳ͕Β࢑͠଴ͭ 37 $ cdk deploy

Slide 38

Slide 38 text

%ZOBNP%# nςʔϒϧͰ͖ͯΔʂ 38

Slide 39

Slide 39 text

-BNCEB n-BNCEB'VODUJPO<"1*> 39

Slide 40

Slide 40 text

-BNCEB n-BNCEB'VODUJPO<%#4USFBN> 40

Slide 41

Slide 41 text

-*''ΞϓϦ؀ڥ n4 $MPVE'SPOU 41 AWS Cloud S3 Bucket LIFF Users HTTPS Access LINE Platform LIFF API Amazon CloudFront Deploy SPA app

Slide 42

Slide 42 text

4 nόέοτͷ࡞੒ 42 // Create Bucket const spaBucketName = `spa-bucket-liff-with-s3-cloudfront` const spaBucket = new s3.Bucket(this, spaBucketName, { bucketName: spaBucketName, websiteErrorDocument: 'index.html', websiteIndexDocument: 'index.html', })

Slide 43

Slide 43 text

$MPVE'SPOU *". nόέοτ΁ͷΞΫηεݖݶઃఆ 43 // Create OriginAccessIdentity const websiteOAI = new cloudfront.OriginAccessIdentity( this, `CFIdentity-${this.stackName}` ) // Add S3 Access Resource Policy to OAI const spaBucketPolicyStatement = new iam.PolicyStatement({ actions: ['s3:GetObject'], effect: iam.Effect.ALLOW, principals: [websiteOAI.grantPrincipal], resources: [`${spaBucket.bucketArn}/*`], }) spaBucket.addToResourcePolicy(spaBucketPolicyStatement) Resource Policy

Slide 44

Slide 44 text

$MPVE'SPOU nσΟετϦϏϡʔγϣϯͷ࡞੒ 44 // Create CloudFront Distribution const websiteDistribution = new cloudfront.CloudFrontWebDistribution( this, `CFDistribution-${this.stackName}`, { errorConfigurations: [ -- 中略 -- ], originConfigs: [ { s3OriginSource: { s3BucketSource: spaBucket, originAccessIdentity: websiteOAI,}, behaviors: [{isDefaultBehavior: true,},], }, ], priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL, }, )

Slide 45

Slide 45 text

4 ΁σϓϩΠ n41"Ϗϧυ݁ՌΛόέοτ΁σϓϩΠ 45 // Deploy to S3 bucket new s3Deploy.BucketDeployment(this, `DeploySpa-${this.stackName}`, { sources: [s3Deploy.Source.asset('./spa/dist')], destinationBucket: spaBucket, distribution: websiteDistribution, distributionPaths: ['/*'], }) // Show CloudFront distribution domain name new cdk.CfnOutput(this, 'CFTopURL', { value: `https://${websiteDistribution.domainName}/`, }) CloudFront のドメイン名を 出力しておくと何気に楽w

Slide 46

Slide 46 text

ઃఆ಺༰Λཧղ͠΍͍͢ *%& ͷิ׬͕ར͍ͯخ͍͠ʂ

Slide 47

Slide 47 text

ΞϓϦ؀ڥߏங͕ खܰʹࣗಈԽͰ͖Δʂ

Slide 48

Slide 48 text

͋ͱ͸-*/&ଆΛઃఆ͢Δ͚ͩ

Slide 49

Slide 49 text

Μʁ -*/&ଆͷ ઃఆ͸ը໘Ͱ ΍Δ͔͠ͳ͍ʁ

Slide 50

Slide 50 text

ΞΧ΢ϯτઃఆͷ$-*ɾ"1* ͷ͝ఏڙ͓ئ͍͠·͢ʂ ѪΏ͑ʹʂ

Slide 51

Slide 51 text

·ͱΊ nં֯ͷΫϥ΢υɾαʔόʔϨε؀ڥͳͷͰ ؀ڥߏங΋ੵۃతʹࣗಈԽ͍͖ͯ͠·͠ΐ͏ʂ l :".-౳Ͱͷઃఆ͕ۤखͳਓ͸"84$%,Λࢼͦ͏ Ø ޷ΈͷϓϩάϥϛϯάݴޠͰॻ͚Δ͸ͣ l (" ͞Εͨ͹͔ΓͰ"1* ͸සൟʹߋ৽͞Ε͍ͯΔ໛༷ l $*$% ςετ؀ڥߏஙͷࣗಈԽʹ΋ϐολϦʂ l -*/&1MBUGPSN΋πʔϧ͍ͩ͘͞ʂ 51

Slide 52

Slide 52 text

঺հͨ͠"84 $%, ͷ ιʔείʔυ͸ίνϥ https://github.com/sumihiro3/line-bot-and-liff-with-aws-cdk

Slide 53

Slide 53 text

͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ

Slide 54

Slide 54 text

&0$