30行くらいで作るはじめてのインフラ構築

AWS CDKでコードの記述30行ほどでVPC, ECS, Fargateなどを使ったインフラ環境を構築してみました。 HAPPY BIRTHDAY, クラスメソッド!
2020.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

弊社には 7月7日の会社のお誕生日にブログ書くという文化があります。 せっかくなので私も最近はまっている CDK ネタで一本書いてみようと思います。

ついこの間、はじめて CDK を使って VPC 環境を構築する機会があったのですが、思いのほかシンプルだったのでご紹介したいと思います。

作るもの

VPC、 ECS、 Fargateでインフラ環境を構築します。

使うもの

AWS CDK を Typescript で記述します。

cdk --version
1.32.2

tsc -v
Version 3.7.4

Typescript の watch モードをオンにする

私はよくビルドし忘れてデプロイの時にこけるので Watch モードをオンにして作業します。

tsc -w

これで記述したそばから Typescript コンパイラがプロジェクトをビルドしながらエラーを見つけてくれるので早い段階でエラーにも気づくことができます。

Step1: cdk init

空のディレクトリを作成し、cdk initします。

touch cdk
cd cdk
cdk init --language typescript

Step2: VPC を作る

lib/配下のcdk-stack.tsファイルを編集していきます。 まずは VPC を作成しましょう。

import * as cdk from "@aws-cdk/core";
import { Vpc } from "@aws-cdk/aws-ec2";

export class CdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new Vpc(this, "sample-vpc", {});
  }
}

上のコードをデプロイすると何ができるか見てみましょう。 たった 1 行しか書いてないのになんだかたくさんリソースができてますね。すごい!

マネジメントコンソールで CloudFormation を開いて CloudFormation Designer を開いてみましょう。

作成されたリソースはざっと以下でした。

  • VPC
  • Public Subnet x2
  • Private Subnet x2
  • NatGateway x2
  • Elastic IP x2
  • Internet Gateway
  • Route Table x4

細かい各デフォルトの値はこちらのドキュメントを参考にしてください。

何も指定しないと、上記の内容の VPC 環境が作成されます。ここに例えば、マルチ AZ 設定を 2 から 3 へ増やしたい、NatGateway の数を 1 つに減らしたい、Isolated Subnet も追加したい、などの細かい設定を追加してゆきます。

今回はこのままの設定で次に進みます。

Step2: ECS クラスタを追加

ECS を追加します。Propsには先ほど作成したVPCを渡します。

lib/cdk-stack.ts

    const cluster = new Cluster(this, "ecs-cluster", {
      vpc,
    });

Step3: ALB を追加する

最後に ALB を追加して、サンプルのamazon/amazon-ecs-sampleimage にアクセスできるようにしてみましょう。@aws-cdk/aws-ecs-patternsを使って ALB を追加します。

今回は Fargate を利用します。Version は指定がないとlatestになるためplatformVersionを指定します。

lib/cdk-stack.ts

const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(
      this,
      "fargate-alb-service",
      {
        cluster,
        taskImageOptions: {
          image: ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
        },
        platformVersion: FargatePlatformVersion.VERSION1_3,
      }
    );
  }

動作確認

最後に再度デプロイして、ALBのDNSnameから、デプロイしたコンテナへアクセスしてみましょう。

このようにサンプルのPHPAppが表示されれば成功です!

CDK全文

全文はこんな感じになりました。 記述した部分のコードだけを見れば20行程でしょうか。

import * as cdk from "@aws-cdk/core";
import { Vpc } from "@aws-cdk/aws-ec2";
import { ApplicationLoadBalancedFargateService } from "@aws-cdk/aws-ecs-patterns";
import {
  ContainerImage,
  Cluster,
  FargatePlatformVersion,
} from "@aws-cdk/aws-ecs";

export class CdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // Create VPC
    const vpc = new Vpc(this, "sample-vpc", {});
    // Create ECS Cluster
    const cluster = new Cluster(this, "ecs-cluster", {
      vpc,
    });
    // Create ALB
    const loadBalancedFargateService = new ApplicationLoadBalancedFargateService(
      this,
      "fargate-alb-service",
      {
        cluster,
        taskImageOptions: {
          image: ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
        },
        platformVersion: FargatePlatformVersion.VERSION1_3,
      }
    );
  }
}

因みに上記のコードで生成されたCloudFormation(json)は830行でした。

Step4: cdk destroy

不要な高額請求を避けるため、忘れずにcdk destroyを実行しましょう。

あとがき

少し前までは頑張って記述していた大量のCloudFormationがこれだけ少量のコードで再現できるのは本当に素晴らしいです。

細かく指定をしなくてもいい感じに必要なリソースを作成してくれるのはCDKの便利ポイントの一つです。しかし、少量のコードで済んでしまうぶん何のリソースを作成しているのかがコードから読み取りづらくなってしまうこともあります。

コードの変更を検知するためのテストを書いたり、構成図などをドキュメントに残したりする等、CDKの強みを生かして開発をスムーズに進められるようにするには少し工夫があるといいかもしれません。

この記事が誰かの参考になれば嬉しいです。

Reference List