Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

ゼロから始めるdiagramsでシステム構成図

こんにちは。ひぐらし業を見て毎週心を痛めているふそやん@azihsoynです。

コロナ禍でIT業界ではリモートワークが増えてきて、オンボーディングもオンラインで行うことが多くなってきており、ドキュメントの重要性がさらに増している気がします。

恥ずかしながら弊チームはサーバーサイドのドキュメントが豊富にあるとは言えず、オンボーディングは手書きで構成図を書きながら口頭で説明していました。

そろそろちゃんとしないとと思い始めドキュメントを作り始めたのですが、一番重要なシステム構成図がなかなか描けずに苦労していました。

そもそもなぜシステム構成図が描けないのか? いくつか理由はあると思うのですが、自己分析した結果、

  • デザインセンスがない
    • 辛い
  • GUIのツールで書いても秘伝のタレ化してしまう
  • 継続的に更新されなさそう
    • → 一回だけの図を描くことになりコスパが悪い

などがありそうでした。

自分に向いてるやり方はないものかといろいろと調べた結果、

diagrams.mingrammer.com

というのがバチバチによかったので今回はその紹介をしたいと思います。

diagramsとは

Diagrams lets you draw the cloud system architecture in Python code. It was born for prototyping a new system architecture without any design tools. You can also describe or visualize the existing system architecture as well. Diagram as Code allows you to track the architecture diagram changes in any version control system.

aboutにあるとおり、pythonで構成図を描くツールです(go版もあります)。Diagram as Codeの通り、githubで差分を確認したり履歴を追うことが可能になります。

導入 はとても簡単で、graphvizとpythonがあれば動きます。

早速例を見てみましょう。

from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB

with Diagram("Grouped Workers", show=False, direction="TB") as diagram:
    ELB("lb") >> [EC2("worker1"),
                  EC2("worker2"),
                  EC2("worker3"),
                  EC2("worker4"),
                  EC2("worker5")] >> RDS("events")

if __name__ == '__main__':
    diagram

こんなコードを書くと

f:id:azihsoyn:20210301153641p:plain
grouped workers

こんな図が出力されます。

from diagrams import Cluster, Diagram
from diagrams.aws.compute import ECS, EKS, Lambda
from diagrams.aws.database import Redshift
from diagrams.aws.integration import SQS
from diagrams.aws.storage import S3

with Diagram("Event Processing", show=False):
    source = EKS("k8s source")

    with Cluster("Event Flows"):
        with Cluster("Event Workers"):
            workers = [ECS("worker1"),
                       ECS("worker2"),
                       ECS("worker3")]

        queue = SQS("event queue")

        with Cluster("Processing"):
            handlers = [Lambda("proc1"),
                        Lambda("proc2"),
                        Lambda("proc3")]

    store = S3("events store")
    dw = Redshift("analytics")

    source >> workers >> queue >> handlers
    handlers >> store
    handlers >> dw

こんなコードだと

f:id:azihsoyn:20210301153825p:plain
event processing

こんな図が作成されます。

これだけで大体のイメージは掴めたのではないでしょうか。

AWSのリソース以外にもGCPやFirebase、k8sなど豊富なリソースが標準で用意されているのですぐに構成図を描き始められます。

例は他にもここに載ってるのでまずは書いて動かしてみるのがいいと思います。

diagrams.mingrammer.com

よかったこと

GUIのツールでももちろん同様の図は書けるのですが、コードで書けると何が嬉しいかを使ってみた感想とともに書いてみます。

レイアウトをあまり考えなくてよい

デザインセンスがない人でも安心です。

リソースを定義して矢印でつなげば優先度に従って自動で配置してくれます。

再現性がある

1つめと重複しますが、自動でレイアウトを調整してくれるということは誰が書いても同じ図になるということです。

前任者から引き継いだコードを手元で動かしても同じ図になるので秘伝のタレ化することがなくなりそうです。

pythonの文法が使える

これは今のところメリットを感じているわけではないですが、普通にif文書いたりforでループを回したりということも出来ます。

例えば本番とステージングでリソースが異なる場合はif文で生成される図を変更することもできそうです。

一つ書くと使い回せる

これは実際に書き始めて感じたのですが、1つ構成図を描くと次の構成図を描くときに一部を持ってきたり参考にすることが出来ます。

要はコピペが捗ります。

コードとして持ってこれるので一括置換したりとIDEの恩恵を受けられるのも嬉しいです。

拡張性がすごい

diagramsは dot言語というgraphvizで図を描くための言語をラップしたものになっています。

つまりgraphvizでできることは理論上なんでもできます。

issueを見てみるとdotを使って複雑なdiagramを描いてるのがいくつか見つかるので探してみるのも面白そうです(レシピ集が欲しいです)。

https://github.com/mingrammer/diagrams/issues/452

こちらのissueでは標準だとできないclusterからclusterへのedgeを描く方法が説明されています。

from diagrams import Diagram, Cluster, Edge
from diagrams.oci.compute import VM

graph_attr = {
    "layout":"dot",
    "compound":"true",
    "splines":"spline",
    }

with Diagram("cluster to cluster edge", graph_attr=graph_attr, show=False) as diag:

    with Cluster("Cluster 1"):
        c1node1 = VM("c1node1")

    with Cluster("Cluster 2"):
        c2node1 = VM("c2node1")

    c1node1 - Edge(color="red", ltail="cluster_Cluster 1", lhead="cluster_Cluster 2") - c2node1

f:id:azihsoyn:20210301162554p:plain
cluster間edge

CI/CDとの相性

github等で管理することでCI/CDのフローに乗せることが出来ます。

今のところ必要性を感じていないですが、新しい構成図をpushしたらS3に自動でアップロードしてcloudfrontのinvalidationを実行するようにすれば更新漏れなどもなくせそうです。

その他

使ってる中で発見したTipsを紹介します。

配置を指定したい

自動で並べてくれるのがとても嬉しいのですが、graphvizの優先度順に並ぶので、例えば次の様な構成図は見栄えが悪くなってしまいます。

from diagrams import Cluster, Diagram
from diagrams import Edge
from diagrams.aws.compute import ECS, EKS

with Diagram("Event Processing", show=False) as diagram:
    source = EKS("k8s source")

    with Cluster("Event Flows"):
        a = ECS("A")
        b = ECS("B")
        c = ECS("C")
        d = ECS("D")

    source >> a
    source >> b
    source >> c
    source >> d

if __name__ == '__main__':
    diagram

f:id:azihsoyn:20210301161007p:plain
縦長

こういうときは見えないEdgeでつないで内部的に優先度を変えてあげると見た目を変えることができます。

from diagrams import Cluster, Diagram
from diagrams import Edge
from diagrams.aws.compute import ECS, EKS

with Diagram("Event Processing", show=False) as diagram:
    source = EKS("k8s source")

    with Cluster("Event Flows"):
        a = ECS("A")
        b = ECS("B")
        c = ECS("C")
        d = ECS("D")
        # 追加
        a >> Edge(style="invis") >> b  
        c >> Edge(style="invis") >> d

    source >> a
    source >> b
    source >> c
    source >> d

if __name__ == '__main__':
    diagram

f:id:azihsoyn:20210301161207p:plain
align

diagramsにない画像を出したい

できます。

CustomNodeを使えば簡単に画像を表示できます

from diagrams import Diagram
from diagrams.custom import Custom

with Diagram("test4", show=False) as diagram:
    Custom("Operator", "../custom_resources/operator.png") # 画像を配置

if __name__ == '__main__':
    diagram

f:id:azihsoyn:20210301161330p:plain

おわりに

いかがでしたでしょうか。diagramsの素晴らしさが少しでも伝われば幸いです。

同じような思想のツールは他にもあると思うので、こんなのがあるよなど紹介していただけるととても嬉しいです。