Diagram-as-code(awsdac)を使ってYAMLファイルからAWS構成図を出力してみた
Diagram as Code(DaC)の概要
Diagram as Code(DaC)とは図の構成要素をコードで定義するという概念です。
普通に図を作成する場合とDaCツールを使用して図を作成する場合の主な違いは以下の通りです。
観点 | 通常 | DaC |
---|---|---|
更新 | 面倒。図形を1つ追加するだけでもその分のスペースを確保するために様々な構成要素を微調整する必要がある。 | 手軽。テキストを追加・変更・削除するだけ。 |
差分管理 | 難しい。手動で更新履歴表などを作成する必要がある。 | 簡単。Gitで差分を管理できる。 |
一貫性 | 低い。作成者ごとにぶれやすい。 | 高い。コードが同一であれば図も同一になる。 |
学習コスト | 低い。直観的に描ける。 | 高い。コードの記法や図の出力方法を学ぶ必要がある。 |
表現力 | 高い。融通が利く。 | 低い。微調整が難しい。 |
DaCツールを使用すると、更新が比較的簡単で、いつ誰が何をどのように変更したのかGitで管理できるので、内部向けの構成図の作成に向いていそうです。
一方、細かい調整や豊かな表現は難しいので、プレゼンテーション用の構成図の作成には向いていないかもしれません。
Diagram-as-code(awsdac)の概要
Diagram-as-code[1](awsdac)とはAWSが公開しているOSSで、YAMLファイルからAWS構成図を出力するDaCツールです。
使用するにはGo 1.21以上が必要です。
今回は使用しませんが、ベータ版としてAWS CloudFormationテンプレートからAWS構成図を出力する機能も提供されています。
DACファイルの書式
awsdacの入力となるYAMLファイル(DACファイル)の書式の基本を説明します。
Diagram
セクション
Diagram
セクションはトップレベルセクションであり、その配下には
-
DefinitionFiles
セクション -
Resources
セクション -
Links
セクション
があります。
Diagram:
DefinitionFiles:
...
Resources:
...
Links:
...
DefinitionFiles
セクション
DefinitionFiles
セクションではAWS構成図に用いる構成要素のアイコンや色、ラベルなどをまとめた定義ファイルを指定します。
awsdacの既定の定義ファイルを使用する場合は以下のように指定します。
Diagram:
DefinitionFiles:
- Type: URL
Url: https://raw.githubusercontent.com/awslabs/diagram-as-code/main/definitions/definition-for-aws-icons-light.yaml
...
ローカルに配置した自前の定義ファイルを使用する場合は以下のように指定します。
Diagram:
DefinitionFiles:
- Type: LocalFile
LocalFile: <LOCAL_FILE_PATH>
...
Resources
セクション
Resources
セクションではAWS構成図に含めるリソースを定義します。
書式はAWS CloudFormationテンプレートに少し似ており、任意のリソース名の配下にリソースタイプやその他プロパティを記載します。
Diagram:
DefinitionFiles:
- Type: URL
Url: https://raw.githubusercontent.com/awslabs/diagram-as-code/main/definitions/definition-for-aws-icons-light.yaml
Resources:
Canvas:
Type: AWS::Diagram::Canvas
Children:
- AWSCloud
AWSCloud:
Type: AWS::Diagram::Cloud
Children:
- Lambda
Lambda:
Type: AWS::Lambda
特殊なリソースタイプについて説明します。
リソースタイプ | 説明 |
---|---|
AWS::Diagram::Canvas |
描画可能な範囲を表している。DACファイル内で必ず1つだけ定義する必要がある。 |
AWS::Diagram::Resource |
任意のリソースを表す。非AWSリソースを定義できる。 |
AWS::Diagram::VerticalStack |
リソースをグループ化して垂直方向に並べる。 |
AWS::Diagram::HorizontalStack |
リソースをグループ化して水平方向に並べる。 |
リソース名配下で指定できる主なプロパティ[2]は以下の通りです。
プロパティ | 説明 |
---|---|
Children |
入れ子として描画するリソース名のリスト。 |
BorderChildren |
境界線上に描画するリソース名と位置のリスト。 |
Title |
リソースのラベル。 |
Direction |
子のリソースを並べる方向。horizontal なら水平方向、vertical なら垂直方向。 |
Align |
子のリソースを寄せる方向。親のリソースが子のリソースを垂直方向に並べる場合、左寄せのleft 、中央揃えのcenter 、右寄せのright から選択。親のリソースが子のリソースを水平方向に並べる場合、上寄せのtop 、中央揃えのcenter 、下寄せのbottom から選択。 |
Preset |
定義済みのプロパティのセット。 |
Direction
とAlign
の説明はawsdacのGitHubに掲載されている図を見た方が分かりやすいです。
https://github.com/awslabs/diagram-as-code/blob/main/doc/resource-types.md#awsdiagramverticalstackより引用
https://github.com/awslabs/diagram-as-code/blob/main/doc/resource-types.md#awsdiagramhorizontalstackより引用
Preset
は定義ファイルに記載されているプロパティのセットを指定できます。
同じリソースタイプでもスタイルに違いがあるリソースで使用します。
Diagram:
DefinitionFiles:
- Type: URL
Url: https://raw.githubusercontent.com/awslabs/diagram-as-code/main/definitions/definition-for-aws-icons-light.yaml
Resources:
Canvas:
Type: AWS::Diagram::Canvas
Direction: vertical
Children:
- PublicSubnet
- PrivateSubnet
- User
PublicSubnet:
Type: AWS::EC2::Subnet
Preset: PublicSubnet
Children:
- EC2A
EC2A:
Type: AWS::EC2
PrivateSubnet:
Type: AWS::EC2::Subnet
Preset: PrivateSubnet
Children:
- EC2B
EC2B:
Type: AWS::EC2
User:
Type: AWS::Diagram::Resource
Preset: User
Links
セクション
Links
セクションではリソース間の線を定義します。
Diagram:
DefinitionFiles:
- Type: URL
Url: https://raw.githubusercontent.com/awslabs/diagram-as-code/main/definitions/definition-for-aws-icons-light.yaml
Resources:
Canvas:
Type: AWS::Diagram::Canvas
Children:
- User
- S3
User:
Type: AWS::Diagram::Resource
Preset: User
S3:
Type: AWS::S3
Links:
- Source: User
SourcePosition: E
Target: S3
TargetPosition: W
TargetArrowHead:
Type: Open
Links
セクションで指定可能な主なプロパティは以下の通りです。
プロパティ | 説明 |
---|---|
Source |
線の始点となるリソース名。 |
Target |
線の終点となるリソース名。 |
SourcePosition |
線の始点の位置。 |
TargetPosition |
線の終点の位置。 |
SourceArrowHead |
始点側を鏃(やじり)にする。配下のType フィールドでDefault かOpen を指定する必要がある。 |
TargetArrowHead |
終点側を鏃(やじり)にする。配下のType フィールドでDefault かOpen を指定する必要がある。 |
Type |
orthogonal を指定することでカギ線にする。 |
LineStyle |
normal なら実線、dashed なら破線。 |
Labels |
線のラベル。配下のSourceLeft フィールド、SourceRight フィールド、TargetLeft フィールド、TargetRight フィールドでラベルの位置を指定できる。これらのフィールドの配下のTitle フィールドにラベルの内容を記載する。 |
SourcePosition
とTargetPosition
で指定可能な値はawsdacのGitHubに掲載されている図を参考にしてください。
https://github.com/awslabs/diagram-as-code/blob/main/doc/links.md#link-positionより引用
SourceArrowHead
とTargetArrowHead
のプロパティについてもawsdacのGitHubに掲載されている図を参考にしてください。
https://github.com/awslabs/diagram-as-code/blob/main/doc/links.md#arrow-headより引用
awsdacでAWS構成図を作成してみた
DACファイルの書式を理解したところで、実際にawsdacを使ってみます。
今回はbuilders.flashに掲載されている以下のAWS構成図を出力できるか試してみます。
https://aws.amazon.com/jp/builders-flash/202204/way-to-draw-architecture/より引用
DACファイルは以下のように記載します。
Diagram:
DefinitionFiles:
- Type: URL
Url: https://raw.githubusercontent.com/awslabs/diagram-as-code/main/definitions/definition-for-aws-icons-light.yaml
Resources:
Canvas:
Type: AWS::Diagram::Canvas
Direction: vertical
Children:
- Users
- CloudAndDataCenter
Users:
Type: AWS::Diagram::Resource
Preset: Users
Title: Users
CloudAndDataCenter:
Type: AWS::Diagram::HorizontalStack
Children:
- AWSCloud
- DataCenter
AWSCloud:
Type: AWS::Diagram::Cloud
Direction: vertical
Children:
- GlobalServices
- Region
GlobalServices:
Type: AWS::Diagram::HorizontalStack
Children:
- Route53
- CloudFront
- GlobalEmptyResource
Route53:
Type: AWS::Route53
Title: Route 53
CloudFront:
Type: AWS::CloudFront
Title: CloudFront
GlobalEmptyResource:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
Region:
Type: AWS::Region
Title: Region (Tokyo)
Direction: vertical
Children:
- S3Group
- VPC
S3Group:
Type: AWS::Diagram::HorizontalStack
Children:
- S3EmptyResource1
- S3EmptyResource2
- S3
S3EmptyResource1:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
S3EmptyResource2:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
S3:
Type: AWS::S3
Title: Amazon S3
VPC:
Type: AWS::EC2::VPC
Title: VPC
Align: top
Children:
- AZa
- ELBGroup
- AZb
BorderChildren:
- Position: N
Resource: IGW
- Position: E
Resource: VPNGW
AZa:
Type: AWS::EC2::AvailabilityZone
Title: Availability Zone a
Direction: vertical
Children:
- PublicSubnetA
- PrivateSubnetA
ELBGroup:
Type: AWS::Diagram::VerticalStack
Children:
- ELBEmptyResource
- ELB
ELBEmptyResource:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
ELB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Title: |
Elastic Load
Balancing
AZb:
Type: AWS::EC2::AvailabilityZone
Title: Availability Zone b
Direction: vertical
Children:
- PublicSubnetB
- PrivateSubnetB
PublicSubnetA:
Type: AWS::EC2::Subnet
Preset: PublicSubnet
Title: Public subnet
Children:
- PublicSubnetAEmptyResource
PrivateSubnetA:
Type: AWS::EC2::Subnet
Preset: PrivateSubnet
Title: Private subnet
Direction: vertical
Children:
- EC2A
- RDSA
PublicSubnetB:
Type: AWS::EC2::Subnet
Preset: PublicSubnet
Title: Public subnet
Children:
- PublicSubnetBEmptyResource
PrivateSubnetB:
Type: AWS::EC2::Subnet
Preset: PrivateSubnet
Title: Private subnet
Direction: vertical
Children:
- EC2B
- RDSB
PublicSubnetAEmptyResource:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
EC2A:
Type: AWS::EC2
Title: Amazon EC2
RDSA:
Type: AWS::RDS
Title: |
Amazon RDS
(Primary)
PublicSubnetBEmptyResource:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
EC2B:
Type: AWS::EC2
Title: Amazon EC2
RDSB:
Type: AWS::RDS
Title: |
Amazon RDS
(Secondary)
IGW:
Type: AWS::EC2::InternetGateway
Title: Internet gateway
VPNGW:
Type: AWS::EC2::VPNGateway
Title: VPN gateway
DataCenter:
Type: AWS::Diagram::DataCenter
Children:
- Server1
- Server2
- Server3
Server1:
Type: AWS::Diagram::Resource
Preset: Server
Title: " "
Server2:
Type: AWS::Diagram::Resource
Preset: Server
Title: " "
Server3:
Type: AWS::Diagram::Resource
Preset: Server
Title: " "
Links:
- Source: Users
SourcePosition: W
Target: Route53
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: Users
SourcePosition: W
Target: CloudFront
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: CloudFront
SourcePosition: E
Target: S3
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: CloudFront
SourcePosition: S
Target: IGW
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: IGW
SourcePosition: S
Target: ELB
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: ELB
SourcePosition: W
Target: EC2A
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: ELB
SourcePosition: E
Target: EC2B
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: EC2A
SourcePosition: S
Target: RDSA
TargetPosition: N
TargetArrowHead:
Type: Default
- Source: EC2B
SourcePosition: S
Target: RDSA
TargetPosition: N
TargetArrowHead:
Type: Default
Type: orthogonal
- Source: RDSA
SourcePosition: E
Target: RDSB
TargetPosition: W
TargetArrowHead:
Type: Default
- Source: DataCenter
SourcePosition: W
Target: VPNGW
TargetPosition: E
TargetArrowHead:
Type: Default
Type: orthogonal
このDACファイルを基に出力したAWS構成図が以下です。
どうでしょうか?
基にした図と比較すると、ELBがサブネットを跨げていなかったり、Corporate data center内のサーバ間の余白が広すぎたり、多少不格好ではありますが、内部向けの構成図であれば十分な質ではないでしょうか?
しかし、DACファイルを作成する過程でいくつか躓いた点があるので共有します。
リソースがリソースを跨げない
基にした図ではVPCがAZ aとAZ bを跨いでいたり、ELBがパブリックサブネットを跨いでいたりしますが、awsdacでは表現することができません。
ただし、Issue#229として要望が上がっているので、いつか実装されるかもしれません。
リソースの位置の微調整ができない
DaCツールに微調整なんて求めてはいけないのかもしれませんが、何かしら工夫しないと矢印が他のリソースに重なって汚くなります。
ちなみに、微調整前の図はこんな感じです。
これを修正するために、AWSアイコンと同じ大きさの白い正方形の画像(EmptyResource.png
)を用意し、至る所に散りばめました。
DACファイルにいくつかある
XXXEmptyResource:
Type: AWS::Diagram::Resource
Icon: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\EmptyResource.png
という記述が微調整の努力の跡です。
ローカルの定義ファイル内の画像を読み込めない
白い正方形の画像を複数箇所で使うのなら、以下のようにローカルの定義ファイルにPresetとして記載しておけばよいのでは?と思っていました。
Definitions:
EmptyResource:
Type: Preset
Icon:
Path: C:\Users\example\go\pkg\mod\github.com\awslabs\diagram-as-code@v0.22.1\definitions\test.png
しかし、私の環境だとawsdacが画像パスを読み込んでくれません…。[3]
\
を\\
にしてみたり、\
を/
にしてみたり、相対パスにしてみたり、色々試したのですが上手くいきませんでした。
Windows環境で上手くできた方がいらっしゃれば是非とも教えてください。
まとめ
- Diagram as Code(DaC)とは図の構成要素をコードで定義するという概念です。
- Diagram-as-code(awsdac)とはYAMLファイルからAWS構成図を出力するDaCツールです。
- awsdacはいくつか制約があるものの、書式に慣れれば作図のストレスが低減され、更新・差分管理が楽になります。
-
概念としてのDiagram as Codeと混同するので、この命名はやめてほしかったです…。 ↩︎
-
resource-types.md内の表を見ながら記事を書いていたら、
Direction
とAlign
の説明が逆であることに気付き、人生初のプルリクエストなるものを提出しました。 ↩︎ -
ローカルの定義ファイル内のPresetにTitleを付けると、AWS構成図にTitleだけ出力されます…。 ↩︎
Discussion