ちょっと話題の記事

CDKで構築したAWS環境の構成図を自動生成するツール「CDK-Dia」を検証してみた

2021.11.14

こんにちは。CX事業本部MAD事業部のきんじょー(@joe_king_sh)です。

AWSでインフラを構築する際に必ず書くもの、

AWS構成図

皆さんはどうやって描いていますか?  

初めからきっちり決めて作ることもあれば、試行錯誤した後、最後に残すドキュメントとして描くもあり、できることならなるべく楽して作成したいですよね。

そこで今回は、CDKで構築したAWS環境の構成図を自動生成するツール「CDK-Dia」が、実際どれくらい使えるのか検証してみました。

CDK-Diaの使い方

環境

macOS Big Sur 11.5.1
node v14.17.6
cdk 1.131.0
cdk-dia 0.3.0

インストール

CDK-Diaと構成図の描写に使用するGraphvizをインストールします。

$ npm install cdk-dia
$ brew install graphviz

使い方

CDKのプロジェクトがあるディレクトリで、以下のコマンドで実行し構成図を出力します。

$ cdk synth
$ npx cdk-dia

上記手順はCDKをTypeScriptで書いていることを前提としています。
その他の言語を使用している場合はGetting-started - any other CDK languageを参照してください。

3層ウェブアプリケーションで検証

cdk-dia/examples/decoration-exampleをもとに構築します。

bin/three-tier-example.ts

#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "@aws-cdk/core";
import { ThreeTierExample } from "../lib/three-tier-example";

const app = new cdk.App();

new ThreeTierExample(app, "Tier3-DB");

lib/web-tier.ts

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

export class WebTier extends cdk.Construct {
  readonly instances: ec2.Instance[] = [];

  constructor(scope: cdk.Construct, id: string, vpc: ec2.Vpc) {
    super(scope, id);

    this.instances.push(this.webInstance("Web1", vpc));
    this.instances.push(this.webInstance("Web2", vpc));
  }

  private webInstance(id: string, vpc: ec2.Vpc): ec2.Instance {
    return new ec2.Instance(this, id, {
      instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T3,
        ec2.InstanceSize.NANO
      ),
      machineImage: ec2.MachineImage.latestAmazonLinux(),
      vpc: vpc,
    });
  }
}

lib/db-tier.ts

import * as rds from "@aws-cdk/aws-rds"
import * as cdk from "@aws-cdk/core"
import * as ec2 from "@aws-cdk/aws-ec2"

export class Db extends rds.DatabaseCluster {
    constructor(scope: cdk.Construct, id: string, vpc: ec2.Vpc) {
        super(scope, id, dbProps(vpc));
    }
}

function dbProps(vpc: ec2.Vpc): rds.DatabaseClusterProps {
    return {
        engine: rds.DatabaseClusterEngine.auroraMysql({version: rds.AuroraMysqlEngineVersion.VER_2_08_1}),
        credentials: rds.Credentials.fromGeneratedSecret('clusteradmin'),
        instanceProps: {vpc: vpc}
    }
}

lib/three-tier-example.ts

import * as cdk from '@aws-cdk/core';
import * as ec2 from "@aws-cdk/aws-ec2";
import * as rds from "@aws-cdk/aws-rds";
import * as lb from "@aws-cdk/aws-elasticloadbalancingv2";
import * as lb_targets from "@aws-cdk/aws-elasticloadbalancingv2-targets";

import {WebTier} from "./web-tier"
import {Db} from "./db-tier"

export class ThreeTierExample extends cdk.Stack {

    constructor(scope: cdk.Construct, id: string) {
        super(scope, id);

        const vpc = new ec2.Vpc(this, "Vpc");
        const alb = new lb.ApplicationLoadBalancer(this, "Loadbalancer", {vpc: vpc})

        const webTier = new WebTier(this, 'WebTier', vpc)

        let cluster: rds.DatabaseCluster
        cluster = new Db(this, 'DbTier', vpc)

        webTier.instances.forEach(instance => {
            cluster.secret?.grantWrite(instance)
        })

        const applicationListener = alb.addListener("443", {port: 80})

        applicationListener.addTargets("lb-targets", {
            port: 80,
            targets: webTier.instances.map(instance => {
                return new lb_targets.InstanceTarget(instance, 80)
            })
        })
    }
}

Draw.ioで手書きした構成図

このCDKでできるAWSのリソースを、普通に書くと以下のような構成図になります。

これをCDK-Diaで出力すると、どんなのが出てくるんでしょうか・・?

デフォルトでCDK-Diaから出力した構成図

cdk dia default export

ミニマリストの構成図が出力されました。

  • わかること
    • VPCの中にELB、RDS、EC2が入っている3層アプリケーション
  • わからないこと
    • DB層はAuroraMySQLのクラスターであること
    • DBインスタンスがリーダーとライターで2つあること
    • LoadBarancerがALBであること
    • VPC内のサブネットの個数
    • 各サブネットのリソースの配置場所
    • InternetGatewayやNatGatewayが存在すること

DBクラスターを展開して出力した構成図

デフォルトだとシンプルな構成図でしたが、これはCDK-DiaがLevel2のリソースを、自動的に折り畳んで出力するためです。 折りたたみのタイプをCdkDiaDecoratorを使用して設定でき、強制的に折り畳まないオプションFORCE_NON_COLLAPSEを指定してみます。

lib/db-tier.ts

import * as rds from "@aws-cdk/aws-rds"
import * as cdk from "@aws-cdk/core"
import * as ec2 from "@aws-cdk/aws-ec2"

import {CdkDia, CdkDiaDecorator} from "cdk-dia/src/cdk"
import {CollapseTypes} from "cdk-dia/src/diagram/component/customizable-attribute"

export class Db extends rds.DatabaseCluster implements cdk.IInspectable {

    constructor(scope: cdk.Construct, id: string, vpc: ec2.Vpc) {
        super(scope, id, dbProps(vpc));
    }

    inspect(inspector: cdk.TreeInspector): void {
        const decorator = new CdkDiaDecorator().collapse(CollapseTypes.FORCE_NON_COLLAPSE)
        CdkDia.decorate(inspector, decorator)
    }
}

function dbProps(vpc: ec2.Vpc): rds.DatabaseClusterProps {
    return {
        engine: rds.DatabaseClusterEngine.auroraMysql({version: rds.AuroraMysqlEngineVersion.VER_2_08_1}),
        credentials: rds.Credentials.fromGeneratedSecret('clusteradmin'),
        instanceProps: {vpc: vpc}
    }
}

上記ハイライト部分の変更を加え、再び出力した結果が以下です。

cdk-diagram-l2-non-collapse

先ほどより少し詳細になり、わからなかった以下が見えてきました。

  • DBインスタンスがリーダーとライターで2つあること
  • DBのマスターパスワードがSecretManagerによって管理されていること

CDKを使うなら、どんどんL2で記述をして楽をしたいですよね。
このようにL2で抽象化されたリソースも、collapseオプションを使うことで構成図に出力できます。

すべてのリソースを展開して出力

構成図出力時のオプションで、全体を通して折り畳みのオンオフを設定できます。

オプション: --collapse Collapse CDK Constructs [真偽] [デフォルト: true]

$ npx cdk-dia --collapse=false

cdk diagram-all-expand

CDKで作成されているリソースすべてが表示され、デフォルトではわからなかった以下が見えてきました。

  • VPC内のサブネットの個数
  • 各サブネットのリソースの配置場所
  • InternetGatewayやNatGatewayが存在すること

一方、普段EC2を立てるときに構成図上あまり書くことのないインスタンスプロファイルなども表示されており、見やすさを重視すると、必要なリソースのみ折り畳みを解除したほうが良さそうです。
折り畳みのオプションを個別でつけるには、CDKのソースに手を入れる必要があるため、既存のプロジェクトへの導入は少しハードルが上がります。
また、折り畳みを解除してもRDSのRDBMSや、ELBの種類といった情報は表示することができませんでした。

検証結果

というわけでまとめです。

CDKで作ったスタック内のリソースの概要把握には有効なツールですが、 ドキュメントとしてのAWS構成図は、情報を取捨選択しつつ人の手で書いた方が良いというのが結論です。

以下にユースケースをまとめてみました。

向いているケース

  • CDK L2レベルで全体の概要が掴みたい
  • CDKで抽象化されているリソースをすべて一覧化
    • すべて折り畳み/展開のどちらかであれば、簡単に構成図が出力可能
  • 小規模でシンプルな構成(VPCを必要としない)

向かないケース

  • 大規模なインフラストラクチャ(VPCを含む)
    • リソース間の依存関係が掴みづらくなる
  • 既存のCDKプロジェクトからいい感じに構成図をつくる
    • 各リソースの折り畳みのオプション設定で既存ソースに手を入れる必要あり
  • ドキュメントとしてのAWS構成図
    • リソースの細かい種別まで表示されないアイコンがある
    • 配置変更などは調整できない(Graphvizの.dotファイルをいじる事も可能だが、CDKから自動生成ができなくなってしまう)

余談

個人的にはDraw.ioをVS Codeで使う以下のExtensionsを使って、テキストファイルで構成図を書いて、CDKと同じリポジトリに突っ込んでおくのが好きです。

最後まで読んでいただきありがとうございました。
MAD事業部のきんじょー(@joe_king_sh)でした。