LoginSignup
144

テキストから図が生成できるMermaidでAWS構成図をつくる

Last updated at Posted at 2022-07-06

はじめに

テキストからダイアグラムの図が生成できるMermaidでAWS構成図をつくる方法を紹介します。

また、MermaidはGithubやQiitaなどのWebサービスやVSCodeやIntelliJなどのツール、コマンドやWebシステムでも使用できますので、良ければ下記の記事もご確認ください。

Mermaidのことはなんとなくわかったけど、AWSの構成図や配置図が描けないか考えていた人にも参考になれば幸いです。

AWSの構成図をつくる

・どんな感じの図ができるのか

AWSの構成図を描くときにはAWS公式から提供されている[AWS Architecture Icons]というAWSのダイアグラムを書く際のアイコンセットを利用する機会が多いと思いますが、Mermaidでは残念ながらまだ使用できません。

そこで、アイコンの使用は諦めてAWSに関するグループやサービスについて、それっぽく見える方法を記載しました。

なお、Mermaidの書き方については[ザックリ解説 - どう書くのか][Mermaid公式ドキュメント]を参照してください。

PlantUMLではAWSのアイコンが標準ライブラリ1に組み込まれています。MermaidでもFont Awesomeのアイコンを使用する方法2 (Qiita未対応)はあるので、将来的に[Amazon Web Services - Labs]あたりで対応してくれるかもしれません。

・グループを描く

AWS Architecture Iconsでも様々なグループを示す枠がありますが、今回はよく使うグループをMermaid記法でどのように表現するかまとめてみました。

Groups Architecture Icons Mermaid Mermaid記法のスタイル
AWS Cloud fill:none,color:#345,stroke:#345
Region fill:none,color:#59d,stroke:#59d,stroke-dasharray:3
VPC fill:none,color:#0a0,stroke:#0a0
Availability Zone fill:none,color:#59d,stroke:#59d,stroke-width:1px,stroke-dasharray:8
Private subnet fill:#efe,color:#092,stroke:none
Public subnet fill:#def,color:#07b,stroke:none

・グループのサンプル

分かりやすいように上記で記載した各グループをMermaid記法でグループのみ記述し、Qiita上で表現したのが下記になります。

上記のMermaid記法の記述は下記になります。

Mermaid記法
flowchart

%%---グループの設定---

%%Public subnetのグループ
subgraph GS1[Public subnet]
end

%%Private subnetのグループ
subgraph GS2[Private subnet]
end

%%Availability Zoneのグループ
subgraph GA[Availability Zone]
end

%%VPCのグループ
subgraph GV[VPC]
end

%%Regionのグループ
subgraph GR[Region]
end

%%AWS Cloudのグループ
subgraph GC[AWS Cloud]
end

%%---スタイルの設定---

%%AWS Cloudのスタイル
classDef SGC fill:none,color:#345,stroke:#345
class GC SGC

%%Regionのスタイル
classDef SGR fill:none,color:#59d,stroke:#59d,stroke-dasharray:3
class GR SGR

%%VPCのスタイル
classDef SGV fill:none,color:#0a0,stroke:#0a0
class GV SGV

%%Availability Zoneのスタイル
classDef SGA fill:none,color:#59d,stroke:#59d,stroke-width:1px,stroke-dasharray:8
class GA SGA

%%Private subnetのスタイル
classDef SGPrS fill:#def,color:#07b,stroke:none
class GS2 SGPrS

%%Public subnetのスタイル
classDef SGPuS fill:#efe,color:#092,stroke:none
class GS1 SGPuS

・サービスを描く

サービスはAWS Architecture Iconsのアイコンが使用できないので、ノードの色と形で模倣します。こちらもよく使うサービスをMermaid記法でどのように表現するのかまとめてみました。

Service Architecture Icons Mermaid Mermaid記法のスタイル Mermaid記法のノード
外部要素 fill:#aaa,color:#fff,stroke:#fff [ ]
Network関連 fill:#84d,color:#fff,stroke:none {{ }}
Compute関連 fill:#e83,color:#fff,stroke:none ( )
DB関連 fill:#46d,color:#fff,stroke:#fff [( )]
Storage関連 fill:#493,color:#fff,stroke:#fff [( )]

・サービスのサンプル

分かりやすいように上記で紹介した各サービスをMermaid記法でサービスのみ記述し、Qiita上で表現したのが下記になります。

上記のMermaid記法の記述は下記になります。

Mermaid記法
flowchart

%%---グループの設定---

%%Storage関連のグループ
subgraph GST[Storage関連]
  ST1[(S3)]
  ST2[(EBS)]
  ST3[(EFS)]
end

%%Database関連のグループ
subgraph GDB[Database関連]
  DB1[(RDS)]
  DB2[(Redshift)]
  DB3[(ElastiCache)]
end

%%Compute関連のグループ
subgraph GCP[Compute関連]
  CP1(EC2)
  CP2(ECS)
  CP3(Lambda)
end

%%Network関連のグループ
subgraph GNW[Network関連]
  NW1{{ELB}}
  NW2{{API Gateway}}
  NW3{{Kinesis}}
end

%%外部要素のグループ
subgraph GOU[外部要素]
  OU1[Users]
  OU2[Server]
  OU3[Client]
end

%%---スタイルの設定---

%%外部要素のスタイル
classDef SOU fill:#aaa,color:#fff,stroke:#fff
class OU1,OU2,OU3 SOU

%%Network関連のスタイル
classDef SNW fill:#84d,color:#fff,stroke:none
class NW1,NW2,NW3 SNW

%%Compute関連のスタイル
classDef SCP fill:#e83,color:#fff,stroke:none
class CP1,CP2,CP3 SCP

%%DB関連のスタイル
classDef SDB fill:#46d,color:#fff,stroke:#fff
class DB1,DB2,DB3 SDB

%%Storage関連のスタイル
classDef SST fill:#493,color:#fff,stroke:#fff
class ST1,ST2,ST3 SST

%%グループのスタイル
classDef SG fill:none,color:#666,stroke:#aaa
class GST,GDB,GCP,GNW,GOU SG

・AWS構成図のサンプル

冒頭で紹介したAWSの構成図ですが、最初にどんな構成図が作れるのかイメージを持ってもらうために便宜上グループをくどいくらい記述しています。

通常はわざわざRegionやAZを記載しない上にEC2などのサービスも複数使用しているためタグ名などを表示しているかと思いますので、もう少し通常使う記載に寄せたAWSの構成図のサンプルを紹介します。

上記のMermaid記法の記述は下記になります。

Mermaid記法
flowchart LR

%%外部要素のUser
OU1[User]

%%グループとサービス
subgraph GC[AWS]
  subgraph GV[vpc-sc1]
    subgraph GS1[subnet-1]
      NW1{{"ELB<br>web1"}}
    end
    subgraph GS2[subnet-2]
      CP1("EC2<br>web1")
    end
    DB1[("RDS<br>db1")]
  end
  ST1[("S3<br>xx.com")]
end

%%サービス同士の関係
OU1 --> NW1
NW1 --> CP1
CP1 --> DB1
DB1 -.-> ST1

%%グループのスタイル
classDef SGC fill:none,color:#345,stroke:#345
class GC SGC

classDef SGV fill:none,color:#0a0,stroke:#0a0
class GV SGV

classDef SGPrS fill:#def,color:#07b,stroke:none
class GS2 SGPrS

classDef SGPuS fill:#efe,color:#092,stroke:none
class GS1 SGPuS

%%サービスのスタイル
classDef SOU fill:#aaa,color:#fff,stroke:#fff
class OU1 SOU

classDef SNW fill:#84d,color:#fff,stroke:none
class NW1 SNW

classDef SCP fill:#e83,color:#fff,stroke:none
class CP1 SCP

classDef SDB fill:#46d,color:#fff,stroke:#fff
class DB1 SDB

classDef SST fill:#493,color:#fff,stroke:#fff
class ST1 SST

・AWS-CLIを使ってEC2の配置図をつくる

AWS-CLIを使うとEC2やVPCやAZ、Subnetの情報が取得できるので、コンソール上でAWS-CLIと組み合わせたコマンドを使用して簡単な配置図のようなものを作ることができます。

下記はAWS-CLIのEC2情報(describe-instances)の情報を元に配置図を作るコマンドです。長いですがテキストをコピーしてAWS-CLIの使えるコンソールに貼り付けるとMermaid記法の記述が出力されます。

Mermaid記法を出力をするためのコマンド
aws ec2 describe-instances \
  --output text \
  --query \
  'Reservations[*].Instances[*].{N1:NetworkInterfaces[0].VpcId, N2:Placement.AvailabilityZone, N3:NetworkInterfaces[0].SubnetId, N4:Tags[?Key==`Name`]|[0].Value, N5:State.Name, N6:LaunchTime, N7:InstanceId, N8:PrivateIpAddress}' \
| sort -t$'\t' \
| perl -F'\t' -alne 'BEGIN{@s=("GV","GA","GS")};for($i=0;$i<3;$i++){ if($mv[$i] ne $F[$i]){$mc[$i]++;$c=0;for($m=1,$k=$mc[0];$m<=$i;$m++){$k.="_$mc[$m]"};for(;$m<3;$m++){($mv[$m],$mc[$m])=("",0)};if($mv[$i]){for($e=$l;$e>=$i;$e--){print " "x$e."end";}print "$s[$i]".($mc[$i]-1)."---$s[$i]$mc[$i]" if $i==0};print " "x$i."subgraph $s[$i]${k}[$F[$i]]";$l=$i }};$c++;print "   CP${k}_${c}(tag:$F[3]<br>id:$F[6]<br>ip:$F[7])";print "   CP${k}_".($c-1)."---CP${k}_${c}" if $c>1 && $mc[2]==1;@mv=splice(@F,0,3);END{print "  end\n end\nend";}' \
| cat <(cat <<EOF
%%{init:{'themeVariables':{'lineColor':'#000ff'}}}%%
flowchart TB
EOF
) - <(cat <<EOF
classDef SGV fill:none,color:#0a0,stroke:#0a0
classDef SGA fill:none,color:#59d,stroke:#59d,stroke-width:1px,stroke-dasharray:8
classDef SGS fill:#def,color:#07b,stroke:none
classDef SCP fill:#e83,color:#fff,stroke:none
EOF
) \
| perl -ple 'push @{$l{$2}},$1 if / (([A-Z]+)[\d_]+?)[\[\(]/;END{foreach (keys %l){print "class ".join(",",@{$l{$_}})." S$_"}}'

上記のコマンドを実行した結果を部分的にマスクしたサンプルが下記になります。

コマンド出力結果のサンプル
%%{init:{'themeVariables':{'lineColor':'#000ff'}}}%%
flowchart TB
subgraph GV1[vpc-xxx]
 subgraph GA1_1[ap-northeast-1a]
  subgraph GS1_1_1[subnet-xxx]
   CP1_1_1_1(tag:xxx<br>id:i-xxx<br>ip:xxx)
   CP1_1_1_2(tag:xxx<br>id:i-xxx<br>ip:xxx)
   CP1_1_1_1---CP1_1_1_2
  end
 end
end
GV1---GV2
subgraph GV2[vpc-xxx]
 subgraph GA2_1[ap-northeast-1a]
  subgraph GS2_1_1[subnet-xxx]
   CP2_1_1_1(tag:xxx<br>id:i-xxx<br>ip:xxx)
   CP2_1_1_2(tag:xxx<br>id:i-xxx<br>ip:xxx)
   CP2_1_1_1---CP2_1_1_2
  end
  subgraph GS2_1_2[subnet-xxx]
   CP2_1_2_1(tag:xxx<br>id:i-xxx<br>ip:xxx)
   CP2_1_2_2(tag:xxx<br>id:i-xxx<br>ip:xxx)
   CP2_1_2_3(tag:xxx<br>id:i-xxx<br>ip:xxx)
  end
 end
end
classDef SGV fill:none,color:#0a0,stroke:#0a0
classDef SGA fill:none,color:#59d,stroke:#59d,stroke-width:1px,stroke-dasharray:8
classDef SGS fill:#def,color:#07b,stroke:none
classDef SCP fill:#e83,color:#fff,stroke:none
class GV1,GV2 SGV
class GS1_1_1,GS2_1_1,GS2_1_2 SGS
class GA1_1,GA2_1 SGA
class CP1_1_1_1,CP1_1_1_2,CP2_1_1_1,CP2_1_1_2,CP2_1_2_1,CP2_1_2_2,CP2_1_2_3 SCP

上記のコマンドで出力されたMermaid記法の記述をQiitaで表現したのが下記になります。

上記は標準出力された内容をQiitaに貼り付けていますが、そのまま標準出力をリダイレクトでファイルに出力してMermaidコマンドで画像ファイルを出力することもできます。
Mermaidコマンドについては[ザックリ解説 - コマンドでmermaidが使える][公式ドキュメント]を参照してください。

Mermaid記法をファイルに出力してpngファイルを作成するコマンド
$ aws ec2 describe-instances \
  --output text \
  --query \
  'Reservations[*].Instances[*].{N1:NetworkInterfaces[0].VpcId, N2:Placement.AvailabilityZone, N3:NetworkInterfaces[0].SubnetId, N4:Tags[?Key==`Name`]|[0].Value, N5:State.Name, N6:LaunchTime, N7:InstanceId, N8:PrivateIpAddress}' \
| sort -t$'\t' \
| perl -F'\t' -alne 'BEGIN{@s=("GV","GA","GS")};for($i=0;$i<3;$i++){ if($mv[$i] ne $F[$i]){$mc[$i]++;$c=0;for($m=1,$k=$mc[0];$m<=$i;$m++){$k.="_$mc[$m]"};for(;$m<3;$m++){($mv[$m],$mc[$m])=("",0)};if($mv[$i]){for($e=$l;$e>=$i;$e--){print " "x$e."end";}print "$s[$i]".($mc[$i]-1)."---$s[$i]$mc[$i]" if $i==0};print " "x$i."subgraph $s[$i]${k}[$F[$i]]";$l=$i }};$c++;print "   CP${k}_${c}(tag:$F[3]<br>id:$F[6]<br>ip:$F[7])";print "   CP${k}_".($c-1)."---CP${k}_${c}" if $c>1 && $mc[2]==1;@mv=splice(@F,0,3);END{print "  end\n end\nend";}' \
| cat <(cat <<EOF
%%{init:{'themeVariables':{'lineColor':'#000ff'}}}%%
flowchart TB
EOF
) - <(cat <<EOF
classDef SGV fill:none,color:#0a0,stroke:#0a0
classDef SGA fill:none,color:#59d,stroke:#59d,stroke-width:1px,stroke-dasharray:8
classDef SGS fill:#def,color:#07b,stroke:none
classDef SCP fill:#e83,color:#fff,stroke:none
EOF
) \
| perl -ple 'push @{$l{$2}},$1 if / (([A-Z]+)[\d_]+?)[\[\(]/;END{foreach (keys %l){print "class ".join(",",@{$l{$_}})." S$_"}}' > input.mmd
$ 
$ mmdc -i input.mmd -o output.png
$ 

image.png
また、VPCやSubnetなどはIDしか表示されていないので、もしタグなどに変更したい場合はAWS-CLIのdescribe-vpcsdescribe-subnetsなどで取得できるIDとタグ情報を元に、追加で置換して見やすくすることもできます。

おわりに

先日投稿した[ザックリ解説]を見てMermaid面白そうと感じてもらえた方や、AWS構成図をコード管理したい、AWS構成図や配置図を自動生成したい方の参考になれば幸いです。

また、Mermaidは他のモノと組み合わせて使うことで活用範囲が広がっていくので、本稿を読んで興味を持って頂けたらAWS構成図に限らず色々な図の作成にトライしてみてください。
(Mermaid記法はQiitaやGithubでも手軽に確認できます)

  1. https://plantuml.com/ja/stdlib#a464d2f6236a5c23

  2. https://github.com/mermaid-js/mermaid/issues/1435

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
144