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

インフラ高級言語としてのAWS CDK〜"設定"より1段階ハイレベルな抽象化〜

Yoda Keisuke
February 18, 2024
62

インフラ高級言語としてのAWS CDK〜"設定"より1段階ハイレベルな抽象化〜

Yoda Keisuke

February 18, 2024
Tweet

Transcript

  1. インフラ構築の領域は、 ノーコードから「コード」へと進化を遂げてきた IaC以前と以後の対⽐ ノーコード(GUI)管理 ⼿動操作、` 設計書` のメンテ ⾮⼀貫性の問題 スケーラビリティの制限 コード(Iac)管理

    ⾃動化、バージョン管理の利便性 ⼀貫性があり、再現可能なデプロイ 迅速かつ確実な変更 「コードレビュー」が可能 GenAI との対話性
  2. まずは実コードを概観 プロンプト : { 各 IaC} で、以下の要件を満たすインフラコードを書いて # 要件 ALB

    を通じて、 Aurora をデータストアとした ECS/Fargate のアプリケーションを公 開する。
  3. Cloud formation ( 62 ⾏) Resources: MyVPC: Type: 'AWS::EC2::VPC' Properties:

    CidrBlock: '10.0.0.0/16' ECSCluster: Type: 'AWS::ECS::Cluster' TaskDefinition: Type: 'AWS::ECS::TaskDefinition' Properties: Cpu: '256' Memory: '512' NetworkMode: 'awsvpc' RequiresCompatibilities: - FARGATE ContainerDefinitions: - Name: 'sample-app' Image: 'my-docker-image:latest' PortMappings: - ContainerPort: 80 ApplicationLoadBalancer: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' Properties: Subnets: - 'subnet-12345678' Type: 'application' ALBListener: Type: 'AWS::ElasticLoadBalancingV2::Listener' Properties: DefaultActions: - Type: 'forward' TargetGroupArn: Ref: 'TargetGroup' LoadBalancerArn: Ref: 'ApplicationLoadBalancer' Port: 80 Protocol: 'HTTP' TargetGroup: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: Port: 80 Protocol: 'HTTP' VpcId: Ref: 'MyVPC' AuroraDBCluster: Type: 'AWS::RDS::DBCluster' Properties: Engine: 'aurora' MasterUsername: 'username' MasterUserPassword: 'password' AuroraDBInstance: Type: 'AWS::RDS::DBInstance' Properties: DBInstanceClass: 'db.r4.large' Engine: 'aurora' DBClusterIdentifier: Ref: 'AuroraDBCluster' EcsToAuroraSGRule: Type: 'AWS::EC2::SecurityGroupIngress' Properties: GroupId: !Ref AuroraSecurityGroup SourceSecurityGroupId: !Ref ECSTasksSecurityGroup IpProtocol: tcp FromPort: '3306' ToPort: '3306'
  4. Terraform(69⾏) resource "aws_vpc" "my_vpc" { cidr_block = "10.0.0.0/16" } resource

    "aws_ecs_cluster" "cluster" { name = "my-cluster" } resource "aws_ecs_task_definition" "task" { family = "my-family" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" container_definitions = jsonencode([{ name = "sample-app" image = "my-docker-image:latest" portMappings = [{ containerPort = 80 }] }]) } resource "aws_lb" "lb" { name = "my-lb" internal = false load_balancer_type = "application" security_groups = ["sg-12345678"] subnets = ["subnet-12345678"] } resource "aws_lb_listener" "listener" { load_balancer_arn = aws_lb.lb.arn port = "80" protocol = "HTTP" default_action { type = "forward" target_group_arn = aws_lb_target_group.target_group.arn } } resource "aws_lb_target_group" "target_group" { port = 80 protocol = "HTTP" vpc_id = aws_vpc.my_vpc.id } resource "aws_rds_cluster" "aurora" { engine = "aurora" master_username = "username" master_password = "password" skip_final_snapshot = true } resource "aws_rds_cluster_instance" "aurora_instance" { engine = "aurora" instance_class = "db.r4.large" cluster_identifier = aws_rds_cluster.aurora.id } resource "aws_security_group_rule" "ecs_to_aurora" { type = "ingress" from_port = 3306 to_port = 3306 protocol = "tcp" security_group_id = aws_security_group.aurora_sg.id source_security_group_id = aws_security_group.ecs_tasks_sg.id }
  5. CDK(22⾏) const vpc = new ec2.Vpc(this, 'MyVpc'); const auroraCluster =

    new rds.DatabaseCluster(this, 'Database', { engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_09_1 }), instanceProps: { vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE), }, defaultDatabaseName: 'MyDatabase', masterUser: { username: 'adminuser', password: cdk.SecretValue.plainText('password1234'), }, }); const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, }); auroraCluster.connections.allowFrom(loadBalancedFargateService.service, ec2.Port.tcp(3306));
  6. 抽象化が更に進んだ CDK は、 その⽣産性から組織の競争⼒を加速する CDK のビジネスメリット ⼯数削減 コーディング量が少ない ヒューマンエラー削減 ⾞輪の再発明の防⽌

    競争⼒の増加 新サービスや機能の早期提供 デプロイまでの学習曲線が緩やか ë なぜそのようなメリットが⽣まれるのか?
  7. ⾼級⾔語であることのメリットを IaC に持ち込める ⾼⽔準でプログラマブルであることのメリット 1 モデリング可能 プロジェクトのインフラコードを構造化 コンポーネント同⼠の依存関係を記述可能 taskDef.json や`buildspec.yaml`

    のようなファイルをCDK コードに統合できる 2 低⽔準 / 冗⻑な作業の排除 「賢明なデフォルト」という特性をもつ 例えば… VPC 作成時: ベストプラクティスに従う( サブネットの分割、NAT ゲートウェイの配置、セキュリティ設定) lamda とdynamoDB を作成し、関連づける: それぞれにそれ⽤のSG を作成、lambda からdynamoDB を使⽤する最⼩限の権限のIAM ロールを作成、アタッチ 差別化に繋がらない重労働の排除、とも⾔い換えられる。(かつカスタマイズ性は犠牲になら ない) 3 パッケージング可能 ⾼いコンポーザビリティ 決まったパターンをライブラリのように共有/ 再利⽤が可能 公式のL3 コンストラクト( 後述) を使⽤ 4 ⾔語の機能を継承 繰り返しや条件分岐が使⽤可能 型チェック 、IDE によるAPI 仕様のサジェスト、(Typescript) プログラマのインフラ⼊⾨として、ゆるやかな学習曲線 5 Cloud formation の機能を継承 AWS 管理のロールバック、削除保護が使える CFn で使える機能は使える
  8. プログラミングの関⼼事と、 それに対する CDK のソリューションを紹介する 1 モデリング / パッケージング é Construct

    L1~3 の粒度があるConstruct による階層化 デプロイの単位はStack Construct で管理 2 DI / Configuration é environment / context / secret manager 実⾏時変数やクレデンシャル の扱い⽅、DI のやり⽅ 3 CD / CI é CDK pipeline
  9. Construct はその名の通り CDK を構成す る種々のビルディングブロックである - 1. 「モデリング」について construct の分類

    App Construct Stack Construct Construct 標準のAWS construct library 。抽象度により3つの種類が存在 L1 コンストラクト: 最も低レベルで、CFn のリソースと同じプロパティ。これがあるた め、CFn で出来ることはCDK で出来る、と⾔える L2 コンストラクト: 最も基本となるCDK らしいコンストラクト。特定のリソースを表す クラスであり、便利メソッドがたくさん⽣えている。 L3 コンストラクト( 別名 パターン): ハイレベルなコンストラクトで、よくあるパターンが事前定義され たパッケージ。独特な要件がなく、これを使⽤するとコード⾏数が ⼤幅に減る。 カスタムコンストラクト 上記の標準コンストラクトを元に独⾃作成するコンストラクト サードパーティのコンストラクト 個⼈や団体が配布しているものもある。プロダクションで使⽤する 場合は要確認。 App とStack は「特 殊な役割のコンスト ラクト」 https://docs.aws. amazon.com/cdk/ api/v2/docs/aws- construct- library.html construc… Construct Hub Construct Hub helps develope…
  10. 環境毎の実⾏時変数や設定値の DI も容易に可能 - 2. 「 DI / Configuration 」について

    値の種類とそれを適⽤する⽅法⼀覧 パラメータ種別 CDK の設定⽅法 備考 アカウント情報 CLI のプロファイルから取 得する コードに直接記述する 複数同時に開発する場合、誤 デプロイを避けるため、コー ドに直接書くのが無難 ⼀般的なパラメータ ex) ⾮機密的な環境変数 環境毎に指定する既存リ ソースが異なるなど cdk.json に記述 → 使⽤するコンストラクト 内で取得 → 必要とするコンストラク トに渡す。 parameter.ts に記述 → 環境毎のパラメータが多 い場合、別の設定ファイル に切り出すと良い( 型が効 くことからTypescript での み実質可能) 既存のparameter store から取 得してくることも可能 クレデンシャル ex) DB のパスワードや各種ア クセスキーなど secret manager を作成 → 使⽤するコンストラクト 内で取得し、必要とするコ ンストラクトに渡す。 既存のsecret manager をARN を指定して取得することも可 能。(既存のものを使⽤でき るのは全リソースがそう)
  11. CD CI パイプライン⾃体をモデリング ( コ ード表現 ) する 「CD CI

    」について 1. `stage` により表現されたパイプラインの⼀例 1 Source Stage リポジトリからソースコードを取得 2 Install Stage 依存ライブラリの取得 ソースのコンパイル Unit テスト実⾏ 3 Synth Stage インフラの同期 4 Assets Stage S3 にアセット配置 ECR にコンテナ配置 5 Dev Deploy Stage dev 環境にデプロイ Integration テスト実⾏ Load テスト実⾏ 6 Approval Stage コンソールからの⼿動承認をフロー に⼊れる 7 Prod Deploy Stage 本番デプロイ
  12. 今後の動向について pulumi やInfrastructure from Code (IfC) などという発展的概念がどんどん出てきている https://tmokmss.hatenablog.com/entry/survey_on_infrastructure_from_code 定義が曖昧なマーケティング⽤語 ひとつは、「アプリケーションコードを書けば、決まったインフラコードは書かずに⾃動⽣成すれ

    ば良い」ということ? https://infrastructurefromcode.com/ あるいは、「インフラリソースは第⼀級市⺠である」と⾔うこと? https://www.winglang.io/ インフラコードとアプリコードが同⼀⾔語で、同⼀ファイルに混ざって書かれてきている。 bring cloud; let queue = new cloud.Queue(timeout: 2m); let bucket = new cloud.Bucket(); let counter = new cloud.Counter(initial: 100); queue.setConsumer(inflight (body: str): str => { let next = counter.inc(); let key = "myfile-${next}.txt"; bucket.put(key, body); }); (inflight 以降の) 関数をコンシューマに登録したSQS ですよ。関数とは、受け取った⽂字列を元にバケ ットにデータを書き込む。その際にアトミックなカウンターとしてDynamoDB を使いますよ。という サービスが作成される。 クラスメソッド株式会社 【アプリもインフラも1 つの⾔語で書ける】Wingのチュート… 最近Infrastructure from Code ( IfC) という概念を知りました。 とり あえず、触って雰囲気を掴みたいと思いWingのチュートリアルをや…
  13. 追加のリソース集 1. ⼊⾨ /API リファレンス CDK ワークショップ https://cdkworkshop.com/ja/20-typescript.html ⽇本語あり。紹介しなかったgetting start

    的な⽅法がわかる。 ⾔語はCDK やるなら基本typescript が 良い。 公式doc https://docs.aws.amazon.com/cdk/ ⾔わずもがな 2. コンセプトのさらなる理解 The CDK Book https://www.thecdkbook.com/ 書籍ならこれかな?と⾔う感じ。公式doc を読み込めばこちらは不要かも。 3. サンプルコード系 Baseline Environment on AWS (BLEA) https://github.com/aws-samples/baseline-environment-on-aws AWS Japan の⼈が公開している、ベースラインとしてのセキュアな構成が実現されているテンプレ ート。複数のワークロードが公開されている。 現状、ここからパクってカスタマイズしていくのが良いのではないか。 初学者向けにコメントが⼊っていることもあり、勉強にもなる。 Servreless land https://serverlessland.com/ イベント駆動やサーバレスアーキテクチャの学習/ パターン集サイト。CDK 関係なくおすすめ。 EDA を構築するサンプルにCDK コードも含まれる ECS blue print https://github.com/aws-ia/ecs-blueprints/tree/main/cdk ECS 使⽤パターンのテンプレとして参考に aws-samples https://github.com/aws-samples/aws-cdk-examples
  14. Infrastructure as Code é Infrastructure is Code 54:47 YouTube AWS

    re:Invent 2018: Infrastructure Is Code with the AW… The AWS Cloud Development Kit ( AWS CDK) is a new open- source framework from AWS that enables developers to harnes…