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

AWS Solutions Constructs で楽してシステム作りたいよ〜!

watany
April 09, 2022

AWS Solutions Constructs で楽してシステム作りたいよ〜!

AWS CDK Conference Japan 2022での発表です。
https://jawsug.connpass.com/event/240422/

watany

April 09, 2022
Tweet

More Decks by watany

Other Decks in Technology

Transcript

  1. アジェンダ AWS Solutions Constructs って何? 調べてみました! Production での実践的な知見ではありません Solutions Constructs

    × CDK v2 で記述の抽象化・省力化をどこまで実現できるのか ”これならプロダクトへ組み込めそう”を目指したい 2
  2. 自己紹介 渡邉洋平 NTT テクノクロス デジタルツイン事業部 Twitter:@_watany, Qiita:@watany AWS: 2016~ 全社テックサポート、社内研修講師

    本業は AWS× システム開発・運用支援など CDK: 趣味で色々 上の活動での検証環境構築 自社アドベントカレンダー(2020,2021) グループ内勉強会(cdk8s) 3
  3. CDK を採用すると楽になる? デフォルト値を深く考えずに、いい感じのリソースが構築できる L2 Constructs は凄い! 数行でそれなり以上の VPC がスッと作れる素晴らしさ それでもしんどい点

    各リソースの連携は明示的に記述 非機能要件はユーザの責任で設計/実装が必要 そもそも”各リソース”の繋がりや付帯リソースも含めてデフォルト値 ならいいのに! 7
  4. AWS Solutions Constructs とは AWS Solutions Constructs は、2 つ以上の CDK

    のリソースを組み合わせ、ロギングや暗号化などの ベストプラクティスを実装する複数サービスのパターンを提供します。 参考:AWS Solutions Constructs – AWS CDK のアーキテクチャパターンのライブラリ ≒ 抽象度が高く、欲しい構成をスッと作れる L3 Constructs AWS CDK v2 でも使えます TypeScript/JavaScript, Python, Java で利用可 ”どこかで見た構成”をモジュール化 CloudFront × S3 ALB (with VPC) × Fargate and more... 9
  5. おさらい:Constructs とは 作成したい 1 つ以上のリソースを、CDK では Constructs という単 位で扱う L1

    Constructs CloudFormation の Parameter を逐次に定義する Low-Level な設定が必要ならば利用 L2 Constructs Better-Default, Boilerplate, Glue Logic 各リソースの効率的な実装。CDK 採用のモチベーションの 1 つ L3 Constructs 複数リソースの関係性を″記述しなくてもいい″選択肢 さながら L2 の"VPC"が各設定群(Subnet, Igw, NAT- GW...)を覆い隠すような抽象度 L3 Constructs ≠ AWS Solutions Constructs e.g. @aws_ecs_patterns 10
  6. まずは使ってみよう 発表時は 25 種類ほどであったが、現在は……? 参考:AWS Solutions Constructs – AWS CDK

    のアー キテクチャパターンのライブラリ アクティブな Constructs を確認すべく、Construct Hub を右 図のクエリで検索 2022.3 時点で 54 個 STABLE(安定版), EXPERIMENTAL(実験的)の 2 種類 傾向 "サーバレス"構成の頻出パターンは STABLE 多し ALB, WAF, VPC...的な構成はこれから 今回は”STABLE”のみでシステムを作ってみる 12
  7. 作りたい構成 API gateway + Kinesis Data Streams + Kinesis Firehose

    + S3 Bucket + CW logs, IAM Role, S3 Bucket(Accesslog) 参考 aws-apigateway-kinesisstreams module aws-kinesisstreams- kinesisfirehose-s3 module 13
  8. コーディング(1/3) Typescript で導入するための package.json 右図は 4/9 時点の Latest 依存関係は CDK

    v1 同様、必要なモ ジュールだけ導入する形式 CDK と Solution Constructs の Latest は異なる AWS CDK v2: 2.20.0 AWS Solution Constructs:2.5.0 14
  9. import import import import { Stack Stack Stack Stack Stack,

    StackProps StackProps StackProps StackProps StackProps } from from from from 'aws-cdk-lib' import import import import { Construct Construct Construct Construct Construct } from from from from 'constructs' import import import import { ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams } from from from from '@aws-solutions-constructs/aws-apigateway-kinesisstreams' import import import import { KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 } from from from from '@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3' export export export export class class class class Sample1Stack Sample1Stack Sample1Stack Sample1Stack Sample1Stack extends extends extends extends Stack { constructor constructor constructor constructor constructor(scope scope scope scope scope: Construct, id id id id id: string, props props props props props? ? ? ?: StackProps) { super super super super(scope scope scope scope, id id id id, props props props props) const const const const ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams = = = = new new new new ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams(this this this this, 'apigw-stream', {} ) new new new new KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3(this this this this, 'stream-firehose-s3', { existingStreamObj existingStreamObj existingStreamObj existingStreamObj existingStreamObj: ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams.kinesisStream kinesisStream kinesisStream kinesisStream kinesisStream, }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 コーディング(2/3) new ApiGatewayToKinesisStreams で API Gateway + Kinesis Streams を構 築 L3~, L13~ 今回はデフォルト設定 リソースを設定したい場合は xxxProps でチ ューニング apiGatewayProps, kinesisStreamProps, logGroupProps 15
  10. import import import import { Stack Stack Stack Stack Stack,

    StackProps StackProps StackProps StackProps StackProps } from from from from 'aws-cdk-lib' import import import import { Construct Construct Construct Construct Construct } from from from from 'constructs' import import import import { ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams } from from from from '@aws-solutions-constructs/aws-apigateway-kinesisstreams' import import import import { KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 } from from from from '@aws-solutions-constructs/aws-kinesisstreams-kinesisfirehose-s3' export export export export class class class class Sample1Stack Sample1Stack Sample1Stack Sample1Stack Sample1Stack extends extends extends extends Stack { constructor constructor constructor constructor constructor(scope scope scope scope scope: Construct, id id id id id: string, props props props props props? ? ? ?: StackProps) { super super super super(scope scope scope scope, id id id id, props props props props) const const const const ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams = = = = new new new new ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams ApiGatewayToKinesisStreams(this this this this, 'apigw-stream', {} ) new new new new KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3 KinesisStreamsToKinesisFirehoseToS3(this this this this, 'stream-firehose-s3', { existingStreamObj existingStreamObj existingStreamObj existingStreamObj existingStreamObj: ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams ApiGwToKinesisStreams.kinesisStream kinesisStream kinesisStream kinesisStream kinesisStream, }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 コーディング(3/3) KinesisStreamsToKinesisFirehoseToS 3 で Kinesis Firehose+S3 を構築 L6~, L16~ 作成済の .kinesisStream を指定す ると、簡単に繋がるぞ リソースを設定したい場合は xxxProps でチ ューニング kinesisStreamProps, kinesisFirehoseProps, bucketProps, logGroupProps, loggingBucketProps 16
  11. 完成! 簡単に書けて、しっかり動いた。 上:API Gateway に POST した文字列 下:Kinesis 経由で S3

    へ格納されたファイル 個人的な推しポイント Kinesis(DataStream/Firehose)では createCloudWatchAlarms=True(Default)で以 下のアラートが追加 ReadProvisionedThroughputExceeded:ス ロットリングされた GetRecords GetRecords.IteratorAgeMilliseconds:Get Records の処理遅延 17
  12. システムは無事に作れたか? API を叩くと S3 にファイルがある。=Production に採用可能か? 再掲:”ベストプラクティスを実装”と説明されているが...... AWS Solutions Constructs

    は、2 つ以上の CDK のリソースを組み合わせ、ロギングや暗号化な どのベストプラクティスを実装する複数サービスのパターンを提供します。 Solution Constructs で記載していない部分の設定レベル、ユーザ的には知りたいですよね? ビルド後の資材(CloudFormation Template)をテストしよう! 19
  13. テスト 目的 AWS Solution Constructs で作成したリソースが”いい感じ”になっているか? いい感じ=明らかにダメな設定がないか?を知りたい 方針 せっかく CDK

    v2 で @aws-cdk/assertions も出ましたが 生成した CFn テンプレートの設定値を既存のソリューションでチェック 20
  14. テスト用ツール 1. Security Hub Standards AWS が厳選した ConfigRule の詰め合わせ。良くない設定値を指摘 既存

    3 種類のうち、メンテナンスが活発で汎用的な"AWS Foundational Security Best Practices standard(FSBP)" を使用 今回関係ありそうなルール数: APIgw:5, IAM:9, S3:9 2. OSS(Linter): i. AWS CloudFormation Linter(aws-cloudformation/cfn-lint) aws cloudformation validate-template より強力なフォーマッタ CDK が自動生成する CFn テンプレートでは担保されそうだが一応 ii. cfn-nag(stelligent/cfn_nag) よく比較される AWS CloudFormation Guard 2.0 は標準ルールが非搭載のため、今回はこちら iii. Checkov(bridgecrewio/checkov) BridgeCrew 社製の静的解析ツール。CFn 以外にも Terraform、コンテナ系へも対応。充実の組み込 みルール(over 1000) 21
  15. テスト結果(Security Hub) 1. Security Hub(FSBP) -> 19/23 Passed! S3.9(アクセスログが Enable?)、S3.10(LifesyclePolicy

    が Enable?) NG なバケットは Accesslog 用のみ。設定意図は理解できるので、個人的には許容範囲 logS3AccessLogs=False で Logging しない or 作成済バケットを existingLoggingBucketObj で指 定するのも手。 APIGateway.2:API Gateway REST API ステージでバックエンド認証に SSL 証明書を使ってる? バックエンドのセキュリティ要件次第 APIGateway.4:API Gateway に AWS WAF が関連付けられている? WAF 作成はスコープ外なので納得 気になる場合は @aws-solutions-constructs/aws-wafwebacl-apigateway を追加 注:モジュールは EXPERIMENTAL 22
  16. テスト結果(Linter) 2. OSS(Linter) cfn-lint,cfn-nag 0 件 後者は次項で追記あり checkov -> 70/76

    Passed! Ensure that CloudWatch Log Group is encrypted by KMS (×2) Ensure that CloudWatch Log Group specifies retention days (×2) Ensure API Gateway caching is enabled Ensure the S3 bucket has access logging enabled 23
  17. テスト結果の振り返り Core なリソースの設定レベルは概ね良さそう。 そのまま採用できるかは要件次第。ベースラインとし ては良いレベル感 付帯リソース(CW Logs, S3)の厳密な設定が必要 なら L2

    で補う おまけ(右図) CFn テンプレートをふと覗くと、cfn_nag を抑制する 記載。 一読した感じ cfn_nag と checkov の差分にも見 える 24
  18. まとめ 結局、”Solutions Constructs で楽してシステムを作れる”ようになるのか 実装で楽できる リソース間の結びつきを数行で説明できる 要件に応じたテストは実施しよう! 非機能設計で楽できる 今回の例ではうまくいった。(n=1) 結局

    L2 で作り直すにしても、学ぶべき設定が多い 設計で楽できる コアロジック周りのアーキテクチャさえ検討できれば Solution Constructs の抽象化単位とシステム構成がマッチするとは限らない。設計意図を残すべき props で設定変更したり、L2Consurtucts を組み合わせたり、だんだんカオスになる IaC はコードがドキュメントだぜ!とサボると、比較的早くしっぺ返しが来そう 25