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

Deploy production with AWS CDK / 実践プロダクションサーバーレス

Deploy production with AWS CDK / 実践プロダクションサーバーレス

AWS CDK と TypeScript による Web アプリケーション開発パターン

プロダクションでのアプリケーション構築にサーバーレスを採用することも増えてきました。本セッションではサーバーレスアプリケーションのデプロイを考えます。昨今のクラウドアプリに共通して、デプロイのハードルがかなり上がっています。実際の環境、例えばAWSにあげてみないとわからないことが増えてきたためです。

プロダクションデプロイのハードルを下げるアプローチとして、「デプロイ可能な状態を維持する」方針を立ててみました。そして、そのために AWS CDK が寄与することを述べます。さらに、実際にいくつかの実例を交えて、AWS 構成、その際の AWS CDK コードを説明します。

Yusuke Wada

June 26, 2020
Tweet

More Decks by Yusuke Wada

Other Decks in Technology

Transcript

  1. ࣮ફϓϩμΫγϣϯαʔόʔϨε
    "84$%,ͱ5ZQF4DSJQUʹΑΔ
    8FCΞϓϦέʔγϣϯ։ൃύλʔϯ

    ࿨ా༞հ

    View Slide


  2. αʔόʔϨε Web ΞϓϦέʔγϣϯΛຊ൪؀ڥʹσϓϩΠ͢Δ
    ࠓ೔ͷ࿩

    View Slide


  3. View Slide


  4. ͜ͷܗΛߟ͑Δεςοϓ·ͰͲ͏ͨͲΓͭ͘ͷʁ
    ύλʔϯ͸Θ͔͚ͬͨͲͲ͏σϓϩΠ͢Δͷʁ

    View Slide

  5. ຊηογϣϯͷ໨త
    αʔόʔϨεΞϓϦέʔγϣϯΛϓϩμΫγϣϯσϓϩΠ
    ͢ΔϋʔυϧΛԼ͛Δ
    Ξϓϩʔνɿ
    ΞϓϦέʔγϣϯσϓϩΠ·ͰͷεςοϓΛ໌Β͔ʹ͢Δ
    σϓϩΠՄೳੑ͕༗༻Ͱ͋Δ͜ͱΛࣔ͢
    ۩ମతͳઃܭύλʔϯΛه࿥ʹ࢒͢

    View Slide

  6. ࿩͢͜ͱɾ࿩͞ͳ͍͜ͱ
    ࿩͢
    "84ʹΑΔαʔόʔϨεΞϓϦέʔγϣϯ
    ΞϓϦέʔγϣϯઃܭɺσϓϩΠઓུ
    ࿩͞ͳ͍
    (PPHMF$MPVE1MBUGPSNɼ.JDSPTPGU"[VSF
    ૊৫ɺίϥϘϨʔγϣϯɺ։ൃख๏

    View Slide

  7. $POUFOUT
    αʔόʔϨεͷಘҙͳ͜ͱɾۤखͳ͜ͱΛ࠶֬ೝ͢Δ
    σϓϩΠ·Ͱͷεςοϓͱ"84$%,
    "84ͰͷΞϓϦέʔγϣϯύλʔϯ
    ͦͯ͠ϞμϯΞϓϦέʔγϣϯ΁

    View Slide

  8. $POUFOUT
    αʔόʔϨεͷಘҙͳ͜ͱɾۤखͳ͜ͱΛ࠶֬ೝ͢Δ
    σϓϩΠ·Ͱͷεςοϓͱ"84$%,
    "84ͰͷΞϓϦέʔγϣϯύλʔϯ
    ͦͯ͠ϞμϯΞϓϦέʔγϣϯ΁

    View Slide

  9. લఏɿαʔόʔϨεͷఆٛ
    ΦϯϓϨϛε Ϋϥ΢υ FaaS
    Ϛωʔδυ
    αʔϏε
    ΞϓϦέʔγϣϯ
    ϥϯλΠϜ
    ϛυϧ΢ΣΞ
    OS
    Ծ૝Խج൫
    ϋʔυ΢ΣΞ
    Ϣʔβʔ
    Ϣʔβʔ
    Ϋϥ΢υϕϯμʔ
    Ϣʔβʔ
    Ϋϥ΢υϕϯμʔ
    Ϋϥ΢υϕϯμʔ
    αʔϏε੹೚Ϟσϧ

    View Slide

  10. લఏɿαʔόʔϨεͷఆٛ
    ΦϯϓϨϛε Ϋϥ΢υ FaaS
    Ϛωʔδυ
    αʔϏε
    ΞϓϦέʔγϣϯ
    ϥϯλΠϜ
    ϛυϧ΢ΣΞ
    OS
    Ծ૝Խج൫
    ϋʔυ΢ΣΞ
    Ϣʔβʔ
    Ϣʔβʔ
    Ϋϥ΢υϕϯμʔ
    Ϣʔβʔ
    Ϋϥ΢υϕϯμʔ
    Ϋϥ΢υϕϯμʔ
    αʔϏε੹೚Ϟσϧ
    ͜ΕΒΛ૊Έ߹ΘͤΔ͜ͱ

    View Slide

  11. 'BSHBUF͸ "VSPSB4FSWFSMFTT͸ʁ
    ࿩ΛΘ͔Γ΍͘͢͢ΔͨΊʹɺຊηογϣϯͰ͸αʔ
    όʔϨεͷର৅ʹؚΊ·ͤΜ
    71$͕ొ৔͢ΔͱɺαʔϏεؒ࿈ܞʹ͓͍ͯϓϥΠϕʔτ
    ωοτϫʔΫΛҙࣝ͢Δඞཁ͕ग़ͯ͘ΔͨΊͰ͢
    ͱͯ΋ศརͰɺڧྗͰɺΞϓϦέʔγϣϯߏஙͷબ୒ࢶͱͯ͠
    ັྗతͰ͢

    View Slide

  12. αʔόʔϨε͕ಘҙͳ͜ͱϏδωεޮՌͱ͸
    αʔϏεΠϯ·
    Ͱͷ࣌ؒΛ୹ॖ
    ୹ظ࣮૷࣮ݱ
    ػձଛࣦ๷ࢭ
    ӡ༻ɾอकͷ
    লྗԽ
    αʔϏε඼࣭҆ఆԽ
    ಺੡Խ֦େͷࢧԉ
    ΞδϦςΟ޲্
    ݱ৔ཁٻͷਝ଎࣮૷
    αʔόʔϨεͷޮՌͱ͸? https://aws.amazon.com/jp/serverless/patterns/serverless-benefit/

    View Slide

  13. αʔόʔϨε͕ಘҙͳ͜ͱ
    αʔϏεͱ'BB4Λ૊Έ߹ΘͤͯϢʔεέʔεͷҰ෦Λૣظࢢ৔౤ೖՄೳ
    wطଘγεςϜͷҰ෦Λஔ͖׵͑
    w৽͍͠Ϗδωεͷ1SPPGPG$PODFQU
    wϚΠΫϩαʔϏεͱͯ͠ఆٛͨ͠γεςϜͷߏங
    1BZBTZPVHPʢ࢖ͬͨ෼͚ͩ՝ۚʣʹΑΔίετ࠷దԽ
    wར༻࣌ؒଳ͕ܾ·͍ͬͯΔ؅ཧը໘ͳͲͷΞϓϦ
    wಛఆͷ࣌ظ͚ͩՔಇ͢ΔΩϟϯϖʔϯαΠτ
    wσόΠε͕ͲΜͲΜ૿͍͑ͯ͘*P5όοΫΤϯυ

    View Slide

  14. αʔόʔϨε͕ۤखͳ͜ͱ
    ϦϨʔγϣϯʹΑͬͯσʔλΛ࿈ܞ͢ΔλΠϓͷγεςϜ
    w4'"ɺ$3.
    τϥϯβΫγϣϯ͕සൟ͔ͭେྔʹൃੜ͢ΔγεςϜ
    wۜߦ
    ௿ϨΠςϯγ͕ٻΊΒΕΔγεςϜ
    wΦϯϥΠϯ'14ήʔϜͷαʔόʔ

    View Slide


  15. ͜͜·Ͱͷ·ͱΊ
    αʔόʔϨεΞϓϦέʔγϣϯ͸ಛఆͷϢʔεέʔεɺҰ෦ͷ
    αʔϏεΛ࣮૷ͯ͠ૉૣ͘ࢢ৔ʹ౤ೖ͢Δ͜ͱ͕ಘҙ
    τϥϯβΫγϣϯ΍௿ϨΠςϯγ͕ٻΊΒΕΔγεςϜ͸ۤख

    View Slide

  16. $POUFOUT
    αʔόʔϨεͷಘҙͳ͜ͱɾۤखͳ͜ͱΛ࠶֬ೝ͢Δ
    σϓϩΠ·Ͱͷεςοϓͱ"84$%,
    "84ͰͷΞϓϦέʔγϣϯύλʔϯ
    ͦͯ͠ϞμϯΞϓϦέʔγϣϯ΁

    View Slide

  17. ຊηογϣϯͷ໨త
    αʔόʔϨεΞϓϦέʔγϣϯΛϓϩμΫγϣϯσϓϩΠ
    ͢ΔϋʔυϧΛԼ͛Δ
    Ξϓϩʔνɿ
    ΞϓϦέʔγϣϯσϓϩΠ·ͰͷεςοϓΛ໌Β͔ʹ͢Δ
    σϓϩΠՄೳੑ͕༗༻Ͱ͋Δ͜ͱΛࣔ͢
    ۩ମతͳઃܭύλʔϯΛه࿥ʹ࢒͢

    View Slide

  18. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    ։ൃલ
    ཁ͕݅αʔόʔϨεʹ߹க͍ͯ͠Δ͜ͱΛ֬ೝ͢Δ
    AWS ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    ֎෦ΠϯλʔϑΣʔεΛઃܭ͢Δ

    View Slide

  19. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    αʔόʔϨε։ൃܾఆޙ
    AWS CDK ͷ࠾༻Λݕ౼͢Δ
    ιʔεϦϙδτϦΛ࡞ͬͯσϓϩΠ͢Δ
    DEV, STG, PRD ؀ڥ΁σϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    σϓϩΠՄೳͳ CI /CD ύΠϓϥΠϯΛ૊Ή

    View Slide

  20. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    σϓϩΠͰ͖ͨΒ
    AWSߏ੒Λઃܭ͢Δ
    ΞϓϦέʔγϣϯΛ࣮૷͍ͯ͘͠
    PRD΁σϓϩΠ
    ຊ൪Քಇ

    View Slide


  21. ઌʹσϓϩΠՄೳͳঢ়ଶΛ֫ಘ͠ɺҡ࣋͢Δ
    Ұ؏ͨ͠ํ਑

    View Slide

  22. ͳͥʁ
    Ϋϥ΢υΞϓϦͷҰ൪ͷน͸ɺσϓϩΠͱ݁߹
    *".ϙϦγʔɺϦιʔε੍ݶɺΠϕϯτۦಈαʔϏεͷൃՐͳ
    Ͳɺ࣮؀ڥͰ͔͠Θ͔Βͳ͍͜ͱ͕ͨ͘͞Μ͋Δ
    ͜Ε͕ϓϩμΫγϣϯσϓϩΠʹ͋ͨͬͯͷҰ൪ͷ৺ཧతɺ࣌
    ؒత՝୊ͩͱߟ͑Δ
    ͳΒ͹ɺૣ͍ஈ֊Ͱ͜ͷ՝୊ΛͭͿͯ͠͠·͓͏ͱ͍͏ൃ૝

    View Slide

  23. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    ։ൃલ
    ཁ͕݅αʔόʔϨεʹ߹க͍ͯ͠Δ͜ͱΛ֬ೝ͢Δ
    AWS ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    ֎෦ΠϯλʔϑΣʔεΛઃܭ͢Δ

    View Slide

  24. ཁ͕݅αʔόʔϨεʹ߹க͍ͯ͠Δ͜ͱΛ֬ೝ͢Δ
    ௿ϨΠςϯγ΍ಉ࣌ʹेݸҎ্ͷτϥϯβΫγϣϯ͕ٻ
    ΊΒΕ͍ͯͳ͍͔ͳͲɺۤख෼໺Λ͖͚ͭͭΕ͍ͯͳ͍
    ͔ΛνΣοΫ͢Δ

    View Slide

  25. ϏδωεαΠυͱͷڠྗ͕ඞਢ
    ͜͜ͰαʔόʔϨε͕߹Θͳ͍Ͱ͢Ͷɺͱ͍͏൑அ΋े
    ෼͋Γ͑Δ
    ͦͷܾஅ͸ɺεςʔΫϗϧμʔશһ͕ڵຯΛ࣋ͪɺશһ
    ͕ೲಘ͢Δ͜ͱ͕ඞਢ

    View Slide

  26. ࣄྫ঺հɿ4#(JGU༷

    View Slide

  27. ࣄྫ঺հɿ4#(JGU༷

    View Slide

  28. ࣄྫ঺հɿ4#(JGU༷
    ͢ͰʹαʔόʔϨεͷಘҙྖҬΛཧղ͓ͯ͠Γ
    ࠷ॳ͔Βద༻ൣғΛߜ͍͍ͬͯͨͩͨ͜ͱ͕੒ޭཁҼ

    View Slide

  29. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    ։ൃલ
    ཁ͕݅αʔόʔϨεʹ߹க͍ͯ͠Δ͜ͱΛ֬ೝ͢Δ
    AWS ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    ֎෦ΠϯλʔϑΣʔεΛઃܭ͢Δ

    View Slide

  30. "84ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    σϓϩΠ͢ΔͨΊʹඞཁͳࡐྉͷͻͱͭ
    AWSΞΧ΢ϯτ DEV؀ڥ
    %&7
    αʔϏε#
    AWSΞΧ΢ϯτ PRD؀ڥ
    AWSΞΧ΢ϯτ
    αʔϏεA
    αʔϏε$
    αʔϏε" αʔϏε# αʔϏε$
    13%
    αʔϏε"
    %&7
    AWSΞΧ΢ϯτ
    αʔϏεB
    13%
    %&7
    AWSΞΧ΢ϯτ
    αʔϏεC
    13%

    View Slide

  31. "84ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    AWSΞΧ΢ϯτ DEV؀ڥ
    %&7
    αʔϏε#
    AWSΞΧ΢ϯτ PRD؀ڥ
    AWSΞΧ΢ϯτ
    αʔϏεA
    αʔϏε$
    αʔϏε" αʔϏε# αʔϏε$
    13%
    αʔϏε"
    %&7
    AWSΞΧ΢ϯτ
    αʔϏεB
    13%
    %&7
    AWSΞΧ΢ϯτ
    αʔϏεC
    13%
    ͪ͜Β͕͓͢͢Ί

    View Slide

  32. "84ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    AWSΞΧ΢ϯτ DEV؀ڥ
    %&7
    αʔϏε#
    AWSΞΧ΢ϯτ PRD؀ڥ
    AWSΞΧ΢ϯτ
    αʔϏεA
    αʔϏε$
    αʔϏε" αʔϏε# αʔϏε$
    13%
    αʔϏε"
    %&7
    AWSΞΧ΢ϯτ
    αʔϏεB
    13%
    %&7
    AWSΞΧ΢ϯτ
    αʔϏεC
    13%
    ͪ͜Β͕͓͢͢Ί
    - ΞΧ΢ϯτ͝ͱͷϦιʔε্ݶʹͻ͔͔ͬΓʹ͘͘ͳΔ
    - ΞΧ΢ϯτͷϥϯχϯάίετ = αʔϏεͷϥϯχϯάίετ
    - ৽͍͠αʔϏεΛ౤ೖ͢Δͱ͖ɺطଘͷՔಇதαʔϏεΛؾʹʹ͠ͳ͘
    ͯΑ͍

    View Slide

  33. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    ։ൃલ
    ཁ͕݅αʔόʔϨεʹ߹க͍ͯ͠Δ͜ͱΛ֬ೝ͢Δ
    AWS ΞΧ΢ϯτ΁ͷαʔϏε഑ஔΛܾΊΔ
    ֎෦ΠϯλʔϑΣʔεΛઃܭ͢Δ

    View Slide

  34. ֎෦ΠϯλʔϑΣʔεΛઃܭ͢Δ
    ৄࡉ·Ͱ٧ΊΔඞཁ͸ͳ͘ɺཁ͢ΔʹʮͲ͏ݴ͏ܗͰ
    αʔϏεΛ࢖ͬͯ΋Β͏͔ʯΛܾΊΔ
    3&45"1*ɺ(SBQI2-"1*
    ΩϡʔΠϯά
    4JOHMF1BHF"QQMJDBUJPO
    ϑΝΠϧΞοϓϩʔυ

    View Slide


  35. ͊͞։ൃͩ

    View Slide

  36. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    αʔόʔϨε։ൃܾఆޙ
    AWS CDK ͷ࠾༻Λݕ౼͢Δ
    ιʔεϦϙδτϦΛ࡞ͬͯσϓϩΠ͢Δ
    DEV, STG, PRD ؀ڥ΁σϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    σϓϩΠՄೳͳ CI /CD ύΠϓϥΠϯΛ૊Ή

    View Slide

  37. "84$%,ͷ࠾༻Λݕ౼͢Δ

    View Slide

  38. αϯϓϧ$MPVE8BUDI&WFOUTͰىಈ͢Δ-BNCEB'VODUJPO
    import events = require('@aws-cdk/aws-events');
    import targets = require('@aws-cdk/aws-events-targets');
    import lambda = require('@aws-cdk/aws-lambda');
    import cdk = require('@aws-cdk/core');
    import fs = require('fs');
    export class LambdaCronStack extends cdk.Stack {
    constructor(app: cdk.App, id: string) {
    super(app, id);
    const lambdaFn = new lambda.Function(this, 'Singleton', {
    code: new lambda.InlineCode(fs.readFileSync('lambda-handler.py', { encoding: 'utf-8' })),
    handler: 'index.main',
    timeout: cdk.Duration.seconds(300),
    runtime: lambda.Runtime.PYTHON_3_6,
    });
    // Run every day at 6PM UTC
    // See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-
    expressions.html
    const rule = new events.Rule(this, 'Rule', {
    schedule: events.Schedule.expression('cron(0 18 ? * MON-FRI *)')
    });
    rule.addTarget(new targets.LambdaFunction(lambdaFn));
    }
    }
    const app = new cdk.App();
    new LambdaCronStack(app, 'LambdaCronExample');
    app.synth();
    aws-cdk-examples/index.ts at master · aws-samples/aws-cdk-examples https://github.com/aws-samples/aws-cdk-examples/blob/master/typescript/lambda-cron/index.ts

    View Slide

  39. αϯϓϧ$MPVE8BUDI&WFOUTͰىಈ͢Δ-BNCEB'VODUJPO
    import events = require('@aws-cdk/aws-events');
    import targets = require('@aws-cdk/aws-events-targets');
    import lambda = require('@aws-cdk/aws-lambda');
    import cdk = require('@aws-cdk/core');
    import fs = require('fs');
    export class LambdaCronStack extends cdk.Stack {
    constructor(app: cdk.App, id: string) {
    super(app, id);
    const lambdaFn = new lambda.Function(this, 'Singleton', {
    code: new lambda.InlineCode(fs.readFileSync('lambda-handler.py', { encoding: 'utf-8' })),
    handler: 'index.main',
    timeout: cdk.Duration.seconds(300),
    runtime: lambda.Runtime.PYTHON_3_6,
    });
    // Run every day at 6PM UTC
    // See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-
    expressions.html
    const rule = new events.Rule(this, 'Rule', {
    schedule: events.Schedule.expression('cron(0 18 ? * MON-FRI *)')
    });
    rule.addTarget(new targets.LambdaFunction(lambdaFn));
    }
    }
    const app = new cdk.App();
    new LambdaCronStack(app, 'LambdaCronExample');
    app.synth();
    aws-cdk-examples/index.ts at master · aws-samples/aws-cdk-examples https://github.com/aws-samples/aws-cdk-examples/blob/master/typescript/lambda-cron/index.ts

    View Slide

  40. αϯϓϧ$MPVE8BUDI&WFOUTͰىಈ͢Δ-BNCEB'VODUJPO
    import events = require('@aws-cdk/aws-events');
    import targets = require('@aws-cdk/aws-events-targets');
    import lambda = require('@aws-cdk/aws-lambda');
    import cdk = require('@aws-cdk/core');
    import fs = require('fs');
    export class LambdaCronStack extends cdk.Stack {
    constructor(app: cdk.App, id: string) {
    super(app, id);
    const lambdaFn = new lambda.Function(this, 'Singleton', {
    code: new lambda.InlineCode(fs.readFileSync('lambda-handler.py', { encoding: 'utf-8' })),
    handler: 'index.main',
    timeout: cdk.Duration.seconds(300),
    runtime: lambda.Runtime.PYTHON_3_6,
    });
    // Run every day at 6PM UTC
    // See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-
    expressions.html
    const rule = new events.Rule(this, 'Rule', {
    schedule: events.Schedule.expression('cron(0 18 ? * MON-FRI *)')
    });
    rule.addTarget(new targets.LambdaFunction(lambdaFn));
    }
    }
    const app = new cdk.App();
    new LambdaCronStack(app, 'LambdaCronExample');
    app.synth();
    aws-cdk-examples/index.ts at master · aws-samples/aws-cdk-examples https://github.com/aws-samples/aws-cdk-examples/blob/master/typescript/lambda-cron/index.ts

    View Slide

  41. αϯϓϧ$MPVE8BUDI&WFOUTͰىಈ͢Δ-BNCEB'VODUJPO
    import events = require('@aws-cdk/aws-events');
    import targets = require('@aws-cdk/aws-events-targets');
    import lambda = require('@aws-cdk/aws-lambda');
    import cdk = require('@aws-cdk/core');
    import fs = require('fs');
    export class LambdaCronStack extends cdk.Stack {
    constructor(app: cdk.App, id: string) {
    super(app, id);
    const lambdaFn = new lambda.Function(this, 'Singleton', {
    code: new lambda.InlineCode(fs.readFileSync('lambda-handler.py', { encoding: 'utf-8' })),
    handler: 'index.main',
    timeout: cdk.Duration.seconds(300),
    runtime: lambda.Runtime.PYTHON_3_6,
    });
    // Run every day at 6PM UTC
    // See https://docs.aws.amazon.com/lambda/latest/dg/tutorial-scheduled-events-schedule-
    expressions.html
    const rule = new events.Rule(this, 'Rule', {
    schedule: events.Schedule.expression('cron(0 18 ? * MON-FRI *)')
    });
    rule.addTarget(new targets.LambdaFunction(lambdaFn));
    }
    }
    const app = new cdk.App();
    new LambdaCronStack(app, 'LambdaCronExample');
    app.synth();
    aws-cdk-examples/index.ts at master · aws-samples/aws-cdk-examples https://github.com/aws-samples/aws-cdk-examples/blob/master/typescript/lambda-cron/index.ts
    - $ cdk deploy
    - TypeScriptίʔυ͔Β AWS ϦιʔεΛσϓϩΠՄೳ
    - ཪͰ AWS CloudFormation ςϯϓϨʔτΛੜ੒͍ͯ͠Δ

    View Slide

  42. ͜Ε͸"84͔ΒͷϝοηʔδΛײ͡Δ

    View Slide

  43. ͜Ε͸"84͔ΒͷϝοηʔδΛײ͡Δ
    Ϋϥ΢υϦιʔεͷσϓϩΠ·ͰؚΊͯ
    ΞϓϦέʔγϣϯ։ൃͩͧ
    ͓·͕͑΍Ε

    View Slide

  44. "84$%,ͷ࠾༻Λݕ౼͢Δ
    ͸͍ɺ΍Γ·͢
    ։ൃऀͷٕज़εΠονίετ͕ݮΓɺσϓϩΠ·Ͱͷো
    น͕গͳ͘ͳΔ
    ΞϓϦέʔγϣϯΤϯδχΞ͕ΠϯϑϥΛɺΠϯϑϥΤ
    ϯδχΞ͕ΞϓϦέʔγϣϯΛ։ൃ͢Δ͖͔͚ͬʹͳΔ

    View Slide

  45. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    αʔόʔϨε։ൃܾఆޙ
    AWS CDK ͷ࠾༻Λݕ౼͢Δ
    ιʔεϦϙδτϦΛ࡞ͬͯσϓϩΠ͢Δ
    DEV, STG, PRD ؀ڥ΁σϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    σϓϩΠՄೳͳ CI /CD ύΠϓϥΠϯΛ૊Ή

    View Slide

  46. ϞϊϨϙʹΑΔΞϓϦέʔγϣϯͷ؅ཧ
    ύοέʔδߏ੒Ͳ͏͠·͔͢
    ZBSOXPSLTQBDFʹΑΔϞϊϨϙ͕͓͢͢Ί
    yarn workspace | Yarn https://classic.yarnpkg.com/ja/docs/cli/workspace/

    View Slide

  47. ߏ੒ྫ
    QBDLBHFT
    NBOBHFNFOUSFBDU
    MBNCEBOPEF
    JOGSBBXTDEL
    QBDLBHFKTPO
    UTDPOpHCBTFKTPO
    ./

    View Slide

  48. ߏ੒ྫ
    QBDLBHFT
    NBOBHFNFOUSFBDU
    MBNCEBOPEF
    JOGSBBXTDEL
    QBDLBHFKTPO
    UTDPOpHCBTFKTPO
    ./
    - ֤ workspace Ͱಠཱͯ͠։ൃ͕Մೳ
    - ಉ࣌ʹɺϓϩδΣΫτϧʔτͷ package.json ͷεΫϦϓτ࣍ୈͰɺ·ͱ
    ΊͯϏϧυ͢Δ͜ͱ΋Մೳ

    View Slide

  49. -BNCEB'VODUJPOͱ"84$%,ͷ࿈ܞ
    "84$%,Ͱ-BNCEB'VODUJPOΛఆٛ͢Δͱ͖
    ʹɺϏϧυޙͷ-BNCEB'VODUJPOύεΛࢦఆ͢Ε͹
    0,

    new lambda.Function(stack, 'getGreetingReply', {
    functionName: 'getGreetingReply-function',
    code: lambda.Code.fromAsset(NODE_LAMBDA_SRC_DIR),
    handler:
    'lambda/handlers/api-gw/greeting/api-gw-get-greeting-reply-handler.handler',
    runtime: lambda.Runtime.NODEJS_12_X,
    layers: [nodeModulesLayer],
    environment: {
    REGION: cdk.Stack.of(stack).region,
    },
    });

    View Slide

  50. -BNCEB'VODUJPOͱ"84$%,ͷ࿈ܞ
    "84$%,Ͱ-BNCEB'VODUJPOΛఆٛ͢Δͱ͖
    ʹɺϏϧυޙͷ-BNCEB'VODUJPOύεΛࢦఆ͢Ε͹
    0,

    new lambda.Function(stack, 'getGreetingReply', {
    functionName: 'getGreetingReply-function',
    code: lambda.Code.fromAsset(NODE_LAMBDA_SRC_DIR),
    handler:
    'lambda/handlers/api-gw/greeting/api-gw-get-greeting-reply-handler.handler',
    runtime: lambda.Runtime.NODEJS_12_X,
    layers: [nodeModulesLayer],
    environment: {
    REGION: cdk.Stack.of(stack).region,
    },
    });

    View Slide

  51. -BNCEB'VODUJPOͱ"84$%,ͷ࿈ܞ
    "84$%,Ͱ-BNCEB'VODUJPOΛఆٛ͢Δͱ͖
    ʹɺϏϧυޙͷ-BNCEB'VODUJPOύεΛࢦఆ͢Ε͹
    0,

    new lambda.Function(stack, 'getGreetingReply', {
    functionName: 'getGreetingReply-function',
    code: lambda.Code.fromAsset(NODE_LAMBDA_SRC_DIR),
    handler:
    'lambda/handlers/api-gw/greeting/api-gw-get-greeting-reply-handler.handler',
    runtime: lambda.Runtime.NODEJS_12_X,
    layers: [nodeModulesLayer],
    environment: {
    REGION: cdk.Stack.of(stack).region,
    },
    });

    - $ yarn deploy

    View Slide

  52. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    αʔόʔϨε։ൃܾఆޙ
    AWS CDK ͷ࠾༻Λݕ౼͢Δ
    ιʔεϦϙδτϦΛ࡞ͬͯσϓϩΠ͢Δ
    DEV, STG, PRD ؀ڥ΁σϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    σϓϩΠՄೳͳ CI /CD ύΠϓϥΠϯΛ૊Ή

    View Slide

  53. ؀ڥ͝ͱʹσϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    ελοΫ໊Λ؀ڥ͝ͱʹม͑Δ͜ͱͰରԠՄೳ
    ؀ڥม਺ͳͲʹೖΕ͓ͯ͘ͱྑ͍
    export async function greetingApplicationStack(
    scope: cdk.Construct,
    id: string,
    global: GlobalProps,
    ): Promise {
    // dev | stg | prd
    const stage = process.env.STAGE_NAME!;
    const stack = new cdk.Stack(scope, id, {
    stackName: `${stage}-${id}-stack`,
    });
    const buckets = await s3Construct.reference(stack, bucketArns);
    const dynamoTables = await dynamoConstruct.reference(stack, dynamoArns);
    const nodeModulesLayer = cdkLambda.LayerVersion.fromLayerVersionArn(
    stack,
    'NodeModulesLayer',
    nodeModulesLayerArn,
    );
    // lambda
    const lambda = await greetingLambdaConstruct(stack, global, {
    buckets,dynamoTables,nodeModulesLayer,
    });
    // API Gateway
    await greetingApiConstruct(stack, global, {
    lambda, env: { apiStageName: 'v1'},
    });
    return stack;
    }

    View Slide

  54. ؀ڥ͝ͱʹσϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    ελοΫ໊Λ؀ڥ͝ͱʹม͑Δ͜ͱͰରԠՄೳ
    ؀ڥม਺ͳͲʹೖΕ͓ͯ͘ͱྑ͍
    export async function greetingApplicationStack(
    scope: cdk.Construct,
    id: string,
    global: GlobalProps,
    ): Promise {
    // dev | stg | prd
    const stage = process.env.STAGE_NAME!;
    const stack = new cdk.Stack(scope, id, {
    stackName: `${stage}-${id}-stack`,
    });
    const buckets = await s3Construct.reference(stack, bucketArns);
    const dynamoTables = await dynamoConstruct.reference(stack, dynamoArns);
    const nodeModulesLayer = cdkLambda.LayerVersion.fromLayerVersionArn(
    stack,
    'NodeModulesLayer',
    nodeModulesLayerArn,
    );
    // lambda
    const lambda = await greetingLambdaConstruct(stack, global, {
    buckets,dynamoTables,nodeModulesLayer,
    });
    // API Gateway
    await greetingApiConstruct(stack, global, {
    lambda, env: { apiStageName: 'v1'},
    });
    return stack;
    }

    View Slide

  55. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    αʔόʔϨε։ൃܾఆޙ
    AWS CDK ͷ࠾༻Λݕ౼͢Δ
    ιʔεϦϙδτϦΛ࡞ͬͯσϓϩΠ͢Δ
    DEV, STG, PRD ؀ڥ΁σϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    σϓϩΠՄೳͳ CI /CD ύΠϓϥΠϯΛ૊Ή

    View Slide

  56. "84$PEF1JQFMJOFͰ΋σϓϩΠͰ͖ΔΑ͏ʹ͓ͯ͘͠
    NBTUFSϒϥϯν͔Β
    EFW؀ڥ͸ࣗಈσϓϩΠ
    TUH QSE͸ঝೝϑϩʔΛڬ
    Ήɺ͕͓͢͢Ί
    ঝೝΛϦδΣΫτ͢Ε͹ɺϦ
    Ϧʔε͞Εͳ͍ʢӈਤʣ

    View Slide

  57. ΋ͪΖΜ"84$PEF1JQFMJOFͷߏங΋"84$%,Ͱ
    const applicationBuild = new codeBuild.PipelineProject(
    stack,
    'GreetingApplicationDeploy-project',
    {
    projectName: 'GreetinApplicationDeploy-project',
    buildSpec: codeBuild.BuildSpec.fromSourceFilename(
    './buildspec/buildspec-deploy.yml',
    ),
    role: deployRole,
    environment: {
    buildImage: LinuxBuildImage.STANDARD_3_0,
    environmentVariables: {
    AWS_DEFAULT_REGION: {
    type: codeBuild.BuildEnvironmentVariableType.PLAINTEXT,
    value: stack.region,
    },
    },
    },
    },
    );

    View Slide


  58. αʔόʔϨεͰઓ͏͜ͱʹશһೲಘ͢Δ
    AWS CDK ͰσϓϩΠՄೳঢ়ଶΛ࠷ॳʹͭ͘Δ
    ͜͜·Ͱͷ·ͱΊ

    View Slide

  59. ϓϩμΫγϣϯσϓϩΠͷεςοϓ֓؍
    σϓϩΠͰ͖ͨΒ
    AWSߏ੒Λઃܭ͢Δ
    ΞϓϦέʔγϣϯΛ࣮૷͍ͯ͘͠
    PRD΁σϓϩΠ
    ຊ൪Քಇ

    View Slide

  60. $POUFOUT
    αʔόʔϨεͷಘҙͳ͜ͱɾۤखͳ͜ͱΛ࠶֬ೝ͢Δ
    σϓϩΠ·Ͱͷεςοϓͱ"84$%,
    "84ͰͷΞϓϦέʔγϣϯύλʔϯ
    ͦͯ͠ϞμϯΞϓϦέʔγϣϯ΁

    View Slide

  61. ͋ͱ͸ΞϓϦέʔγϣϯͷத਎Λॆ࣮͍ͤͯ͘͞
    "84ߏ੒Λઃܭ͢Δ
    ඞཁʹԠͯ͡-BNCEB'VODUJPOͷίʔυΛॻ͘
    "84$%,ʹ͓ͯ͜͠σϓϩΠ͢Δ
    σϓϩΠ͢Δ

    View Slide

  62. ͋ͱ͸ΞϓϦέʔγϣϯͷத਎Λॆ࣮͍ͤͯ͘͞
    "84ߏ੒Λઃܭ͢Δ
    ඞཁʹԠͯ͡-BNCEB'VODUJPOͷίʔυΛॻ͘
    "84$%,ʹ͓ͯ͜͠σϓϩΠ͢Δ
    σϓϩΠ͢Δ
    ✖ N

    View Slide

  63. ࣮੷ͷ͋Δύλʔϯ͔Βͷྲྀ༻ɾԠ༻͕Φεεϝ
    ઃܭϦϑΝϨϯε"84ެࣜ
    αʔόʔϨεύλʔϯ https://aws.amazon.com/jp/serverless/patterns/serverless-pattern/

    View Slide

  64. ࣮੷ͷ͋Δύλʔϯ͔Βͷྲྀ༻ɾԠ༻͕Φεεϝ
    ઃܭϦϑΝϨϯεॻ੶

    View Slide

  65. ࣮੷ͷ͋Δύλʔϯ͔Βͷྲྀ༻ɾԠ༻͕Φεεϝ
    ઃܭϦϑΝϨϯεαʔόʔϨείϛϡχςΟ

    View Slide

  66. ࣮੷ͷ͋Δύλʔϯ͔Βͷྲྀ༻ɾԠ༻͕Φεεϝ
    ࣮૷ϦϑΝϨϯε"84$%,&YBNQMFT

    View Slide

  67. ࣮੷ͷ͋Δύλʔϯ͔Βͷྲྀ༻ɾԠ༻͕Φεεϝ
    ࣮૷ϦϑΝϨϯε%FWFMPQFST*0

    View Slide

  68. ࠓ೔͸·ͩαϯϓϧ͕গͳͦ͏ͳύλʔϯΛ঺հ
    "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    71$-JOLΛར༻ͨ͠71$಺"1*ͱͷ࿈ܞ
    Ͳ͏ͯ͠΋+BWBϥΠϒϥϦΛ࢖Θͳͯ͘͸ͳΒͳ͍
    4UFQ'VODUJPOTΛར༻ͨ͠αʔόʔϨεδϣϒ

    View Slide

  69. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    ओʹΫϥΠΞϯτΞϓϦέʔγϣϯʹ(SBQI2-"1*
    Λఏڙ͢Δ
    'BDFCPPL΍(JU)VCͳͲɺϢʔβʔ޲͚"1*Λ(SBQI2-Ͱఏ
    ڙ͢Δύλʔϯ΋૿͖͑ͯͨ
    ·ͣ͸؅ཧը໘ͷόοΫΤϯυͱͯ͠ར༻͢Δͷ͕ศར

    View Slide

  70. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE

    View Slide

  71. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    const graphApi = new appsync.GraphQLApi(stack, 'AdminBff', {
    name: global.getGraphApiName('AdminBff'),
    authorizationConfig: {
    defaultAuthorization: {
    authorizationType: AuthorizationType.API_KEY,
    apiKeyConfig: {
    description: 'test api key config',
    expires: luxon.DateTime.local().plus({ days: 7 }).toISO(),
    name: 'default test api key',
    },
    },
    additionalAuthorizationModes: [],
    },
    logConfig: {
    fieldLogLevel: FieldLogLevel.ALL,
    excludeVerboseContent: true,
    },
    schemaDefinitionFile: path.join(__dirname, 'schema.graphql'),
    });

    View Slide

  72. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    const graphApi = new appsync.GraphQLApi(stack, 'AdminBff', {
    name: global.getGraphApiName('AdminBff'),
    authorizationConfig: {
    defaultAuthorization: {
    authorizationType: AuthorizationType.API_KEY,
    apiKeyConfig: {
    description: 'test api key config',
    expires: luxon.DateTime.local().plus({ days: 7 }).toISO(),
    name: 'default test api key',
    },
    },
    additionalAuthorizationModes: [],
    },
    logConfig: {
    fieldLogLevel: FieldLogLevel.ALL,
    excludeVerboseContent: true,
    },
    schemaDefinitionFile: path.join(__dirname, 'schema.graphql'),
    });

    View Slide

  73. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    const greetingTableDataSource = graphApi.addDynamoDbDataSource(
    'GreetingTableDataSource',
    'greeting table',
    dynamoTables.greetingTable,
    );
    greetingTableDataSource.createResolver({
    typeName: 'Mutation',
    fieldName: 'createHello',
    requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
    PrimaryKey.partition('id').auto(),
    Values.projecting('input'),
    ),
    responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
    });

    View Slide

  74. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    const greetingTableDataSource = graphApi.addDynamoDbDataSource(
    'GreetingTableDataSource',
    'greeting table',
    dynamoTables.greetingTable,
    );
    greetingTableDataSource.createResolver({
    typeName: 'Mutation',
    fieldName: 'createHello',
    requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
    PrimaryKey.partition('id').auto(),
    Values.projecting('input'),
    ),
    responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
    });
    (SBQI"QJʹ
    %BUB4PVSDFΛ௥Ճ

    View Slide

  75. "84"QQ4ZODʹΑΔ#BDLFOEGPS'SPOUFOE
    const greetingTableDataSource = graphApi.addDynamoDbDataSource(
    'GreetingTableDataSource',
    'greeting table',
    dynamoTables.greetingTable,
    );
    greetingTableDataSource.createResolver({
    typeName: 'Mutation',
    fieldName: 'createHello',
    requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
    PrimaryKey.partition('id').auto(),
    Values.projecting('input'),
    ),
    responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
    });
    %BUB4PVSDFʹ
    3FTPMWFSΛ௥Ճ

    View Slide

  76. 71$-JOLΛར༻ͨ͠71$಺"1*ͱͷ࿈ܞ
    طଘγεςϜͷҰ෦ΛαʔόʔϨεͰஔ͖׵͑Δ৔߹ʹ
    ૺ۰͢Δέʔε
    ߏஙࡁΈͷ&$αʔόʔ܊ʹ/FUXPSL-PBE#BMBODFSܦ༝
    Ͱ"1*(BUFXBZ͔ΒΞΫηεͰ͖Δ
    Πϯλʔωοτʢͨͱ͑͹41"ͳͲͷ؅ཧը໘ʣ͔ΒͷΞΫ
    ηεΛ"1*(BUFXBZʹू໿Ͱ͖ΔɻಛʹೝূํࣜΛ"VUI
    ϩάΠϯͳͲͰ౷Ұ͍ͨ͠ύλʔϯ

    View Slide

  77. 71$-JOLΛར༻ͨ͠71$಺"1*ͱͷ࿈ܞ

    View Slide

  78. 71$-JOLΛར༻ͨ͠71$಺"1*ͱͷ࿈ܞ
    71$ /-#·Ͱ
    ߏஙࡁΈͱ͠·͢

    View Slide

  79. "84$%,"1*(BUFXBZߏங෦෼
    const api = new apig.RestApi(scope, 'GreetingApi', {
    restApiName: global.getApiName('Greeting'),
    endpointTypes: [apig.EndpointType.REGIONAL],
    deployOptions: {
    stageName:’v1’,
    },
    });
    const helloLink = new VpcLink(scope, 'VpcLink', {
    targets: [
    NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(
    scope, ‘GreetingNlb', {
    loadBalancerArn:
    ‘arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxx:loadbalancer/net/Bonjo-Ec2Se-xfsda/12234567890',
    },
    ),
    ],
    });
    const helloResource = api.root.addResource('helo');
    helloResource.addMethod(
    'GET',
    new apig.Integration({
    type: IntegrationType.HTTP_PROXY,
    integrationHttpMethod: ‘GET',
    url: ‘http://abxyfskeladk.elb.ap-northeast-1.amazonaws.com’,
    options: {
    connectionType: ConnectionType.VPC_LINK,
    vpcLink: helloLink,
    },
    }),
    { methodResponses: [{statusCode: ‘200'}] },

    View Slide

  80. "84$%,"1*(BUFXBZߏங෦෼
    const api = new apig.RestApi(scope, 'GreetingApi', {
    restApiName: global.getApiName('Greeting'),
    endpointTypes: [apig.EndpointType.REGIONAL],
    deployOptions: {
    stageName:’v1’,
    },
    });
    const helloLink = new VpcLink(scope, 'VpcLink', {
    targets: [
    NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(
    scope, ‘GreetingNlb', {
    loadBalancerArn:
    ‘arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxx:loadbalancer/net/Bonjo-Ec2Se-xfsda/12234567890',
    },
    ),
    ],
    });
    const helloResource = api.root.addResource('helo');
    helloResource.addMethod(
    'GET',
    new apig.Integration({
    type: IntegrationType.HTTP_PROXY,
    integrationHttpMethod: ‘GET',
    url: ‘http://abxyfskeladk.elb.ap-northeast-1.amazonaws.com’,
    options: {
    connectionType: ConnectionType.VPC_LINK,
    vpcLink: helloLink,
    },
    }),
    { methodResponses: [{statusCode: ‘200'}] },
    طଘ/-#ΑΓ
    71$-JOL࡞੒

    View Slide

  81. "84$%,"1*(BUFXBZߏங෦෼
    const api = new apig.RestApi(scope, 'GreetingApi', {
    restApiName: global.getApiName('Greeting'),
    endpointTypes: [apig.EndpointType.REGIONAL],
    deployOptions: {
    stageName:’v1’,
    },
    });
    const helloLink = new VpcLink(scope, 'VpcLink', {
    targets: [
    NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(
    scope, ‘GreetingNlb', {
    loadBalancerArn:
    ‘arn:aws:elasticloadbalancing:ap-northeast-1:xxxxxx:loadbalancer/net/Bonjo-Ec2Se-xfsda/12234567890',
    },
    ),
    ],
    });
    const helloResource = api.root.addResource('helo');
    helloResource.addMethod(
    'GET',
    new apig.Integration({
    type: IntegrationType.HTTP_PROXY,
    integrationHttpMethod: ‘GET',
    url: ‘http://abxyfskeladk.elb.ap-northeast-1.amazonaws.com’,
    options: {
    connectionType: ConnectionType.VPC_LINK,
    vpcLink: helloLink,
    },
    }),
    { methodResponses: [{statusCode: ‘200'}] },
    "1*(BUFXBZͱ
    71$-JOLΛ઀ଓ

    View Slide

  82. Ͳ͏ͯ͠΋+BWBϥΠϒϥϦΛ࢖ΘͶ͹ͳΒͳ͍
    ଞϕϯμʔͷ֎෦"1*ͷར༻ํ๏Ͱɺ+"3Λ௨͔͢͠
    ͳ͍έʔεͳͲ
    -BNCEB'VODUJPOશମΛ+BWBݴޠͰ࣮૷͢Δ͔
    ϨΠςϯγ͕͞΄Ͳؔ৺ࣄͰͳ͍৔߹͸ɺ+"3ϥΠϒϥϦΛ࣮
    ߦ͢ΔͷΈͷ࠷খͷ-BNCEB'VODUJPOʢ+BWBʣΛ༻ҙ͢Δͷ
    ΋ख

    View Slide

  83. Ͳ͏ͯ͠΋+BWBϥΠϒϥϦΛ࢖ΘͶ͹ͳΒͳ͍
    ଞϕϯμʔͷ֎෦"1*ͷར༻ํ๏Ͱɺ+"3Λ௨͔͢͠
    ͳ͍έʔεͳͲ
    -BNCEB'VODUJPOશମΛ+BWBݴޠͰ࣮૷͢Δ͔
    ϨΠςϯγ͕͞΄Ͳؔ৺ࣄग़ͳ͍৔߹͸ɺ+"3ϥΠϒϥϦΛ࣮
    ߦ͢ΔͷΈͷ࠷খͷ-BNCEB'VODUJPOʢ+BWBʣΛ༻ҙ͢Δͷ
    ΋ख

    View Slide

  84. -BNCEB'VODUJPOͰϥοϓ͢Δ

    View Slide

  85. ߏ੒ྫ
    QBDLBHFT
    NBOBHFNFOUSFBDU
    MBNCEBOPEF
    JOGSBBXTDEL
    QBDLBHFKTPO
    UTDPOpHCBTFKTPO
    ./
    MBNCEBKBWB

    View Slide

  86. ߏ੒ྫ
    QBDLBHFT
    NBOBHFNFOUSFBDU
    MBNCEBOPEF
    JOGSBBXTDEL
    QBDLBHFKTPO
    UTDPOpHCBTFKTPO
    ./
    MBNCEBKBWB
    ௥Ճ
    (SBEMFͰϏϧυɺ-BNCEB
    'VODUJPOͷ+"3ੜ੒

    View Slide

  87. 4UFQ'VODUJPOTΛར༻ͨ͠αʔόʔϨεδϣϒ
    ͲΜͳͱ͖ʹ4UFQ'VODUJPOT͕ొ৔͢Δ͔
    -BNCEB'VODUJPO͕ෳ਺ͷ࢓ࣄΛ੥͚ෛ͓ͬͯΓɺ෼ղͯ͠
    δϣϒͱ͍ͨ͠
    ͳ͓͔ͭɺਐߦঢ়گ͕Θ͔Δͱخ͍͠έʔε
    ྫɿ؅ཧը໘͔Β࣮ߦ͢ΔσʔλҰׅొ࿥ॲཧ

    View Slide

  88. 4UFQ'VODUJPOTΛར༻ͨ͠αʔόʔϨεδϣϒ

    View Slide

  89. ҰׅॲཧͳͲͰΑ͘Έ͔͚ΔΞϨΛαʔόʔϨεͰ

    View Slide

  90. ҰׅॲཧͳͲͰΑ͘Έ͔͚ΔΞϨΛαʔόʔϨεͰ
    ΞϨ
    MPBEJOH

    View Slide

  91. "84$%,ͳΒ4UBUF.BDIJOFΛϝιουͰ਺चͭͳ͗ʹ
    const convertCsvTask = new sfnTasks.LambdaInvoke(
    stack,
    'CsvConvertTask',
    {
    lambdaFunction: lambda.convertCsvToJsonLinesFn,
    invocationType: LambdaInvocationType.REQUEST_RESPONSE,
    resultPath: '$.convert',
    },
    );
    const waitForConvert = new sfn.Wait(stack, 'WaitForConvert', {
    time: sfn.WaitTime.duration(Duration.seconds(5)),
    });
    const writeDynamodbTask = new sfnTasks.LambdaInvoke(
    stack,
    'WriteDynamodbTask',
    {
    lambdaFunction: lambda.writeDynamodbFn,
    invocationType: LambdaInvocationType.REQUEST_RESPONSE,
    resultPath: '$.writeData',
    inputPath: '$.convert.Payload',
    },
    );
    const batchWriteChain = sfn.Chain.start(convertCsvTask)
    .next(waitForConvert)
    .next(writeDynamodbTask)
    const batchWriteMachine = new sfn.StateMachine(stack, 'BatchWriteMachine', {
    stateMachineName: global.getStateMachineName('BatchWriteMachine'),
    definition: chain,
    timeout: cdk.Duration.minutes(20),
    });

    View Slide

  92. const convertCsvTask = new sfnTasks.LambdaInvoke(
    stack,
    'CsvConvertTask',
    {
    lambdaFunction: lambda.convertCsvToJsonLinesFn,
    invocationType: LambdaInvocationType.REQUEST_RESPONSE,
    resultPath: '$.convert',
    },
    );
    const waitForConvert = new sfn.Wait(stack, 'WaitForConvert', {
    time: sfn.WaitTime.duration(Duration.seconds(5)),
    });
    const writeDynamodbTask = new sfnTasks.LambdaInvoke(
    stack,
    'WriteDynamodbTask',
    {
    lambdaFunction: lambda.writeDynamodbFn,
    invocationType: LambdaInvocationType.REQUEST_RESPONSE,
    resultPath: '$.writeData',
    inputPath: '$.convert.Payload',
    },
    );
    const batchWriteChain = sfn.Chain.start(convertCsvTask)
    .next(waitForConvert)
    .next(writeDynamodbTask)
    const batchWriteMachine = new sfn.StateMachine(stack, 'BatchWriteMachine', {
    stateMachineName: global.getStateMachineName('BatchWriteMachine'),
    definition: chain,
    timeout: cdk.Duration.minutes(20),
    });
    "84$%,ͳΒ4UBUF.BDIJOFΛϝιουͰ਺चͭͳ͗ʹ

    View Slide


  93. ͜͜·Ͱͷ·ͱΊ
    "84$%,Λ࢖ͬͯઌʹσϓϩΠͯ͠͠·͏͜ͱΛ͓
    ͢͢Ί͠·ͨ͠
    த਎ͷ࡞ΓࠐΈύλʔϯΛ͍͕ͭࣔ͘͠·ͨ͠
    ͜ΕͰɺʮσϓϩΠ͚ͩͰ΋΍ͬͯΈΑ͏͔ͳʯͱͳΕ
    ͹໨తୡ੒Ͱ͢

    View Slide

  94. αϯϓϧ༻ҙ͋Γ·͢
    "84$%,-BNCEB'VODUJPOͷϞϊϨϙ
    https://github.com/cm-wada-yusuke/template-aws-cdk-typescript-serverless-app

    View Slide

  95. $POUFOUT
    αʔόʔϨεͷಘҙͳ͜ͱɾۤखͳ͜ͱΛ࠶֬ೝ͢Δ
    σϓϩΠ·Ͱͷεςοϓͱ"84$%,
    "84ͰͷΞϓϦέʔγϣϯύλʔϯ
    ͦͯ͠ϞμϯΞϓϦέʔγϣϯ΁

    View Slide

  96. Ϋϥεϝιου.PEFSO"QQMJDBUJPO%FWFMPQNFOU
    Ϋϥεϝιουɹ."%

    View Slide

  97. Ϋϥεϝιου.PEFSO"QQMJDBUJPO%FWFMPQNFOU
    ຊ൪؀ڥʹσϓϩΠͨ͠ΞϓϦέʔγϣϯ͸ɺ͓ۚΛՔ͙͜
    ͱ͕Ͱ͖·͢
    wมԽ΁ͷ௥ਵ͕ඞཁ
    wຊηογϣϯ͸αʔόʔϨεΞϓϦέʔγϣϯͷσϓϩΠՄೳੑʹ
    ΑΔΞδϦςΟ֬อʹϑΥʔΧε͕ͨ͠ɺՁ஋Λఏڙ͚ͭͮ͠Δͨ
    Ίͷཁૉ͸ͨ͘͞Μ͋Δ
    wมԽʹ௥ਵͰ͖ɺՁ஋Λఏڙ͚ͭͮ͠ΒΕΔΞϓϦΛϞμϯΞϓϦ
    έʔγϣϯͱఆٛ͠ɺ։ൃɾίϯαϧαʔϏεͱͯ͠ల։͍ͯ͠·
    ͢

    View Slide

  98. %FW*0$POOFDU݄೔͕."%ಛूͰ͢ʂ

    View Slide

  99. ࢀߟॻ੶ɾར༻ͨ͠πʔϧ
    w DODGXHTFSWFSMFTT$/$'4FSWFSMFTT8(IUUQTHJUIVCDPNDODG
    XHTFSWFSMFTT
    w "84$%,IUUQTHJUIVCDPNBXTBXTDEL
    w DNXBEBZVTVLFUTBTDELIUUQTHJUIVCDPNDNXBEBZVTVLF
    UTBTDEL

    View Slide

  100. ηογϣϯޙ͸Ξϯέʔτ΁ͷ͝ڠྗΛΑΖ͓͘͠ئ͍͠·͢ɻ
    ͝ճ౴͍͍ͨͩͨํʹ͸ޙ೔ɺࢿྉΛૹ෇͍ͨ͠·͢ɻ
    SNS౤ߘʹ͸ͪ͜ΒΛ͓࢖͍͍ͩ͘͞ɻ
    #devio2020
    ΠϕϯτͷϙʔλϧαΠτ͸ͪ͜Β
    https://classmethod.jp/m/devio_2020_connect/
    ϥΠϒηογϣϯ࿥ը΋ͪ͜Β͔Β
    ࢹௌͰ͖·͢ɻ
    https://forms.gle/ytMbgwo3ujUi2bsX9
    15:00ʙ15:45
    ʮ࣮ફϓϩμΫγϣϯαʔόʔϨε - AWS CDKͱTypeScript
    ʹΑΔWebΞϓϦέʔγϣϯ։ൃύλʔϯʯ

    ͷΞϯέʔτ͸ͪ͜ΒͰ͢ɻ
    Q&A Q&A

    View Slide