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

2b41772cec40855d563406ca89fdf926?s=47 bbrfkr
July 27, 2020

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

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

2b41772cec40855d563406ca89fdf926?s=128

bbrfkr

July 27, 2020
Tweet

Transcript

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

  2. 斎藤辰徳 (HN: bbrfkr) Hello! 2 所属:株式会社アイリッジ ミッション • OMOモバイルアプリ実行基盤開発 ◦

    バックエンド ◦ クラウドインフラ (主にAWS)
  3. 3 クラウドもいいけど、オンプレもね。。。

  4. 4

  5. ? ◉ 事業 ◦ 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
  6. Agenda 6 ◉ アプリエンジニアのお悩み事情 ◉ CDK & CloudFormation ◉ コードリポジトリ構成例

    ◉ インフラCI・CD実現事例 ◉ まとめ
  7. アプリエンジニアのお悩み事情 7

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

    ▪ インフラの非機能要件
  9. インフラへの想い 9 ◉ やりたいことの本筋ではない! ◦ 難しく、面倒で、専任に任せたい。。。 ◦ でもインフラエンジニアがいない。。。 ◦ 大部分をクラウドにオフロードしたい!

    ◦ Kubernetesはオーバーテクノロジー ▪ 使う必要性がないなら使いたくない
  10. コンソールぽちぽち問題 10 ◉ クラウドコンソールをぽちぽちしたくない! ◦ これも不本意かつ時間の無駄。。。 ◦ ナレッジ不足によるコード化タイムロス。。。 ◦ インフラコード化/CI・CDは後回し。。。

    CDKでここに寄与したお話
  11. CDK & CloudFormation 11

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

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

  14. 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
  15. 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
  16. CDKの優位性 16 ◉ YAML/JSONでは難しい 開発ノウハウ適用 ◦ 制御構造:if文、forループ ◦ 静的型付け ◦

    静的解析ツール ◦ Snapshotテスト・Fine-Grainedテスト
  17. 静的型付け 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
  18. ◉ 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でないと✗!
  19. Snapshotテスト 19 ◉ 生成されるCFnのGolden Imageによるテスト ◉ 現状、TypeScriptのみサポート Snapshot Template =?

    ≠??
  20. Fine-Grainedテスト 20 ◉ 生成テンプレートの設定値テスト ◉ 現状、TypeScriptのみサポート Runtime == PYTHON_3_8 ?

    S3Origin.domainName == myS3DomainName ? ApiGateway Resource does exist ?
  21. コードリポジトリ構成例 21

  22. cdk init直後の状態 22 ◉ あくまでサンプル ◦ 設定値YAML✗ ◦ 環境概念✗ <project名>/

    ├── README.md ├── bin │ └── <project名>.ts ├── cdk.json ├── jest.config.js ├── lib │ └── <project名>.ts ├── package.json ├── test │ └── <project名>.test.ts └── tsconfig.json
  23. 実際の構成例 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 ユーザ コントロール部 フレームワーク部
  24. インフラCI・CD実現事例 24

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

  26. Check! Check! Check! 26 ◉ Snapshot・Fine-Grainedテスト ◦ PR時に修正でSnapshotがどう変化するかCheck! ◦ Gitの歴史にSnapshotの変化履歴を残して

    ◦ Fine-Grainedテストは肝要な所に絞って ◦ もちろんCIにも組み込む
  27. Check! Check! Check! 27 ◉ cdk diff ◦ 実際にデプロイ済みのテンプレートとの差分Check! ◦

    replace & destroyがないことを機械的に確認 ▪ もしくは許容する対象であることを確認
  28. Check! Check! Check! 28 ◉ awspec ◦ デプロイ後の実リソースパラメータCheck! ◦ 実パラメータテストの蓄積は品質向上を促進

    ▪ k1LoWさん、いつもお世話になってます
  29. CI・CDプロセス 29 ◉ CI test stage 静的解析 Snapshotテスト Fine-Grainedテスト diff

    stage cdk diff PR時に 影響確認可能
  30. CI・CDプロセス 30 ◉ CD diff stage cdk diff >> >>

    deploy stage cdk deploy awspec stage rake spec ここでデプロイ 承認
  31. CI・CDプロセス 31 ◉ デイリーテスト ◦ cdkはリリース頻度が高い ◦ 毎日最新パッケージでテスト ▪ コードの陳腐化検出

    daily_test stage 静的解析 Snapshotテスト Fine-Grainedテスト
  32. アプリエンジニアの声 32 ◉ インフラの状態確認が容易になった! ◦ コンソールを見なくても現状確認できる ◉ インフラも過去の状態に遡れるようになった! ◦ 変更履歴がソースとして残るため

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

  34. まとめ 34 ◉ アプリエンジニアに対して何を提供できる? ◦ クラウドインフラエンジニアの命題の一つ ▪ 安心して、開発に専念できる環境の提供 ◦ k8s利用推進やクラスタ提供であってもOK

    ▪ ただし、アプリエンジニアが望んでいれば ◦ CDKによるIaC推進もその一つかなと
  35. ご質問はお気軽にどうぞ ! ◉ twitter: bbrfkr ◉ mail: bbrfkr@gmail.com Thanks! 35