Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AWS でサーバーレスな LINE Bot/LIFF アプリ環境 をIaC な感じで構築するよ!

AWS でサーバーレスな LINE Bot/LIFF アプリ環境 をIaC な感じで構築するよ!

クラウドが得意なLINE API Expert集合!サーバレス×LINEでアプリ開発してみたLT 発表資料
https://linedevelopercommunity.connpass.com/event/175636/

sumihiro3

May 28, 2020
Tweet

More Decks by sumihiro3

Other Decks in Programming

Transcript

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

    4VNJIJSP ,BHBXB

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. "84Y*B$ ͱݴ͑͹
    n"84$MPVE'PSNBUJPO $'O

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

    View full-size slide

  16. $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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  19. 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

    View full-size slide

  20. ͦ͜Ͱ
    "84$%,

    View full-size slide

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

    View full-size slide

  22. "84$%,
    nରԠͨ͠ϓϩάϥϛϯάݴޠ
    l 1ZUIPO
    l 5ZQF4DSJQU
    l +BWB
    l /&5 $

    24
    https://aws.amazon.com/jp/cdk/features/
    ੩తܕ෇͖ݴޠʂ
    ͭ·Γɺ*%&ʹॿ͚ͯ΋Β͑Δʂ

    View full-size slide

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

    View full-size slide

  24. "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/

    View full-size slide

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

    View full-size slide

  26. -*/&#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

    View full-size slide

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

    View full-size slide

  28. %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 の指定も明確!

    View full-size slide

  29. -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'),
    })

    View full-size slide

  30. -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 の差し込みもこれだけ!
    環境変数も
    簡単に設定

    View full-size slide

  31. -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],
    }
    )

    View full-size slide

  32. -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 の
    作成も一行!

    View full-size slide

  33. "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')

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  40. 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',
    })

    View full-size slide

  41. $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

    View full-size slide

  42. $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,
    },
    )

    View full-size slide

  43. 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

    View full-size slide

  44. ઃఆ಺༰Λཧղ͠΍͍͢

    *%& ͷิ׬͕ར͍ͯخ͍͠ʂ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide