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

アプリエンジニアを救え! AWS CDKで実現するインフラCI・CD

アプリエンジニアを救え! AWS CDKで実現するインフラCI・CD

cndjp #15で発表させていただいた内容です。AWS CDKのお話。

bbrfkr

July 27, 2020
Tweet

More Decks by bbrfkr

Other Decks in Technology

Transcript

  1. アプリエンジニアを救え!
    AWS CDKで実現するインフラCI・CD
    株式会社アイリッジ
    斎藤辰徳

    View full-size slide

  2. 斎藤辰徳 (HN: bbrfkr)
    Hello!
    2
    所属:株式会社アイリッジ
    ミッション
    ● OMOモバイルアプリ実行基盤開発
    ○ バックエンド
    ○ クラウドインフラ (主にAWS)

    View full-size slide

  3. 3
    クラウドもいいけど、オンプレもね。。。

    View full-size slide

  4. ?
    ◉ 事業
    ○ OMO(Online Merges with Offline)ソリューション開発
    ○ OMOアプリの企画・開発
    ◉ 技術
    ○ インフラ開発・運用 → AWS × コンテナ がメイン
    ○ Managed Serviceを積極活用したCloud Architecture
    ○ ECS CLI v1 の国内トップレベルでの利用
    AWS Fargate
    5
    Amazon ECS Amazon ECR Amazon Aurora
    Amazon Cognito
    AWS Lambda

    View full-size slide

  5. Agenda
    6
    ◉ アプリエンジニアのお悩み事情
    ◉ CDK & CloudFormation
    ◉ コードリポジトリ構成例
    ◉ インフラCI・CD実現事例
    ◉ まとめ

    View full-size slide

  6. アプリエンジニアのお悩み事情
    7

    View full-size slide

  7. 非機能要件への興味
    8
    ◉ コード中心の考え方
    ○ アプリの動作に直結する部分では、ある
    ■ コードの非機能要件
    ○ そうでない部分では、あまりない
    ■ インフラの非機能要件

    View full-size slide

  8. インフラへの想い
    9
    ◉ やりたいことの本筋ではない!
    ○ 難しく、面倒で、専任に任せたい。。。
    ○ でもインフラエンジニアがいない。。。
    ○ 大部分をクラウドにオフロードしたい!
    ○ Kubernetesはオーバーテクノロジー
    ■ 使う必要性がないなら使いたくない

    View full-size slide

  9. コンソールぽちぽち問題
    10
    ◉ クラウドコンソールをぽちぽちしたくない!
    ○ これも不本意かつ時間の無駄。。。
    ○ ナレッジ不足によるコード化タイムロス。。。
    ○ インフラコード化/CI・CDは後回し。。。
    CDKでここに寄与したお話

    View full-size slide

  10. CDK & CloudFormation
    11

    View full-size slide

  11. AWS CDKとは ?
    12
    ◉ 高級言語でCloudFormation(CFn)の内容を記述

    View full-size slide

  12. AWS CFnとは ?
    13
    ◉ YAMLやJSONで宣言的にリソース管理
    https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html

    View full-size slide

  13. CDKとCFnのイメージ
    14
    const mybucket = new s3.Bucket(this, 'MyBucket', {
    removalPolicy: cdk.RemovalPolicy.DESTROY,
    });
    new cloudFront.CloudFrontWebDistribution(this, 'MyDistribution', {
    originConfigs: [
    {
    s3OriginSource: {
    s3BucketSource: mybucket
    },
    behaviors: [{isDefaultBehavior: true}]
    }
    ]
    });
    S3の定義
    CloudFront
    の定義
    CDK

    View full-size slide

  14. CDKとCFnのイメージ
    15
    Resources:
    MyBucketF68F3FF0:
    Type: AWS::S3::Bucket
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
    MyDistributionCFDistributionDE147309:
    Type: AWS::CloudFront::Distribution
    Properties:
    DistributionConfig:
    DefaultCacheBehavior:
    AllowedMethods:
    - GET
    - HEAD
    CachedMethods:
    - GET
    - HEAD
    Compress: true
    ForwardedValues:
    Cookies:
    Forward: none
    QueryString: false
    TargetOriginId: origin1
    ViewerProtocolPolicy: redirect-to-https
    DefaultRootObject: index.html
    Enabled: true
    HttpVersion: http2
    IPV6Enabled: true
    Origins:
    - ConnectionAttempts: 3
    ConnectionTimeout: 10
    DomainName:
    Fn::GetAtt:
    - MyBucketF68F3FF0
    - RegionalDomainName
    Id: origin1
    S3OriginConfig: {}
    PriceClass: PriceClass_100
    ViewerCertificate:
    CloudFrontDefaultCertificate: true
    S3の定義
    CloudFront
    の定義
    CloudFront
    の定義
    CFn

    View full-size slide

  15. CDKの優位性
    16
    ◉ YAML/JSONでは難しい 開発ノウハウ適用
    ○ 制御構造:if文、forループ
    ○ 静的型付け
    ○ 静的解析ツール
    ○ Snapshotテスト・Fine-Grainedテスト

    View full-size slide

  16. 静的型付け
    17
    ◉ リソースに与える引数一式を予め決定
    ◉ 静的解析ツールでバグを拾いやすく!
    codeS3Bucket -> String
    codeS3Key -> String
    codeHandler -> String
    codeRuntime -> lambda.Runtime
    apiMethod -> String
    myApiStackVar
    "MyApiFnBucket"
    "codes/apiFn.zip"
    "my_api.handler"
    PYTHON_3_8
    "POST"
    MyApiStackProps
    MyApiStack

    View full-size slide

  17. ◉ yamllintよりもリッチな静的解析
    静的解析ツール
    18
    const mybucket = new s3.Bucket(this, 'MyBucket', {
    removalPolicy: cdk.RemovalPolicy.DESTROY,
    });
    new cloudFront.CloudFrontWebDistribution(this, 'MyDistribution', {
    originConfigs: [
    {
    s3OriginSource: {},
    behaviors: [{isDefaultBehavior: "true"}]
    }
    ]
    });
    2行目、インデント多すぎ!
    s3OriginSourceのパラメータが足りない!
    isDefaultBehaviorの値はboolでないと✗!

    View full-size slide

  18. Snapshotテスト
    19
    ◉ 生成されるCFnのGolden Imageによるテスト
    ◉ 現状、TypeScriptのみサポート
    Snapshot
    Template
    =?
    ≠??

    View full-size slide

  19. Fine-Grainedテスト
    20
    ◉ 生成テンプレートの設定値テスト
    ◉ 現状、TypeScriptのみサポート
    Runtime == PYTHON_3_8 ?
    S3Origin.domainName == myS3DomainName ?
    ApiGateway Resource does exist ?

    View full-size slide

  20. コードリポジトリ構成例
    21

    View full-size slide

  21. cdk init直後の状態
    22
    ◉ あくまでサンプル
    ○ 設定値YAML✗
    ○ 環境概念✗
    /
    ├── README.md
    ├── bin
    │ └── .ts
    ├── cdk.json
    ├── jest.config.js
    ├── lib
    │ └── .ts
    ├── package.json
    ├── test
    │ └── .test.ts
    └── tsconfig.json

    View full-size slide

  22. 実際の構成例
    23
    ├── Gemfile
    ├── Gemfile.lock
    ├── README.md
    ├── Rakefile
    ├── bin
    │ └── cdkTsTemplate.ts
    ├── cdk.context.json
    ├── cdk.json
    ├── jest.config.js
    ├── lib
    │ ├── core
    │ │ ├── abstractStack.ts
    │ │ └── stackCreator.ts
    │ └── util
    │ ├── error.ts
    │ └── util.ts
    ├── package.json
    ├── tsconfig.json
    └── types
    └── index.ts
    project/
    ├── config ← 環境設定ディレクトリ
    │ ├── dev
    │ │ └── <リソース名>.yaml
    │ ├── global.yaml
    │ ├── prod
    │ │ └── <リソース名>.yaml
    │ └── stg
    │ └── <リソース名>.yaml
    ├── src ← ソースコードディレクトリ
    │ ├── <リソース名>.ts
    │ ├── types
    │ │ └── index.ts
    │ └── util.ts
    ├── test ← テストコードディレクトリ
    │ └── <リソース名>
    │ ├── __snapshots__
    │ │ └── snapshot.test.ts.snap
    │ ├── awspec_spec.rb
    │ ├── fineGrained.test.ts
    │ └── snapshot.test.ts
    ユーザ
    コントロール部
    フレームワーク部

    View full-size slide

  23. インフラCI・CD実現事例
    24

    View full-size slide

  24. CI・CD 不安の種
    25
    ◉ 意図しないリソース変更・削除
    ○ 特にステートフルなもの

    View full-size slide

  25. Check! Check! Check!
    26
    ◉ Snapshot・Fine-Grainedテスト
    ○ PR時に修正でSnapshotがどう変化するかCheck!
    ○ Gitの歴史にSnapshotの変化履歴を残して
    ○ Fine-Grainedテストは肝要な所に絞って
    ○ もちろんCIにも組み込む

    View full-size slide

  26. Check! Check! Check!
    27
    ◉ cdk diff
    ○ 実際にデプロイ済みのテンプレートとの差分Check!
    ○ replace & destroyがないことを機械的に確認
    ■ もしくは許容する対象であることを確認

    View full-size slide

  27. Check! Check! Check!
    28
    ◉ awspec
    ○ デプロイ後の実リソースパラメータCheck!
    ○ 実パラメータテストの蓄積は品質向上を促進
    ■ k1LoWさん、いつもお世話になってます

    View full-size slide

  28. CI・CDプロセス
    29
    ◉ CI
    test stage
    静的解析
    Snapshotテスト
    Fine-Grainedテスト
    diff stage
    cdk diff
    PR時に
    影響確認可能

    View full-size slide

  29. CI・CDプロセス
    30
    ◉ CD
    diff stage
    cdk diff
    >> >>
    deploy stage
    cdk deploy
    awspec stage
    rake spec
    ここでデプロイ
    承認

    View full-size slide

  30. CI・CDプロセス
    31
    ◉ デイリーテスト
    ○ cdkはリリース頻度が高い
    ○ 毎日最新パッケージでテスト
    ■ コードの陳腐化検出
    daily_test
    stage
    静的解析
    Snapshotテスト
    Fine-Grainedテスト

    View full-size slide

  31. アプリエンジニアの声
    32
    ◉ インフラの状態確認が容易になった!
    ○ コンソールを見なくても現状確認できる
    ◉ インフラも過去の状態に遡れるようになった!
    ○ 変更履歴がソースとして残るため
    ◉ リソース間依存関係がわかりやすくなった!
    ○ 依存関係把握に各サービスを行ったり来たりせずに済む
    ◉ デフォルト値と指定値の違いが明確!
    ○ どのパラメータに興味がある・あったのかがわかる
    ◉ ソースコードの記述量が意外と少ない!
    ○ 記述の抽象度が高いため
    ◉ 新規環境作成時に過不足が軽減された!
    ○ 新規環境用の設定値さえ用意できれば、同じものを複製可能
    ◉ 違う観点での複数テストで安心感がある!
    ○ 安心ポイントが複数 (デプロイ前、直前、後
    )
    ◉ 既存環境の適用はやっぱり怖い …
    ◉ インフラのナレッジはやっぱり必要 …
    ◉ CFnのナレッジもあるに越したことなし …
    ◉ Versionが頻繁に上がるので少し不安 …

    View full-size slide

  32. まとめ
    34
    ◉ アプリエンジニアに対して何を提供できる?
    ○ クラウドインフラエンジニアの命題の一つ
    ■ 安心して、開発に専念できる環境の提供
    ○ k8s利用推進やクラスタ提供であってもOK
    ■ ただし、アプリエンジニアが望んでいれば
    ○ CDKによるIaC推進もその一つかなと

    View full-size slide

  33. ご質問はお気軽にどうぞ !
    ◉ twitter: bbrfkr
    ◉ mail: [email protected]
    Thanks!
    35

    View full-size slide