15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonベースでアーキテクチャ図を記述するツール「Diagrams」チュートリアル

Posted at

Diagramsとは

DiagramsはDiagram as Codeの思想に基づいて開発されたツールで、アーキテクチャ図をコードによって表現することを目指しています。
特長としては

  • コードベースなのでバージョン管理システムでの追跡が可能
  • 主要なプロバイダーに対応
    といった点があります。

準備

今回は以下の環境で実施しています

  • wsl2(Ubuntu 22.04.4 LTS)
  • python 3.12.11
  • uv 0.7.19

開発環境の管理にmiseを利用しているため、mise.tomlに以下のように記述します。

[tools]
python = "3.12.11"
uv = "0.7.19"

mise installコマンドで必要なツールをインストールし、uv initコマンドでpythonプロジェクトを初期化、uv add diagramsコマンドで今回用いるdiagramsのパッケージをインストールします。

システムにGraphvizパッケージを導入するため、以下のコマンドを実行します。
sudo apt update && sudo apt install -y graphviz

Diagramsの使い方

Diagrams

Diagramはアーキテクチャ図のダイアグラム全体を表すコンテキストです。
Diagramには引数に以下のような値を指定できます。

  • ダイアグラム名:第一引数にダイアグラム名を指定します。
  • show:実行時に作成された画像をシステムの画像ビューワーで自動的に開くかの設定。デフォルトではTrueです
  • filename:実行時に作成される画像のファイルの名前を指定します。拡張子は含みません
  • outformat:実行時に作成される画像のファイル形式を指定します。png、jpg、svg、pdf、dot形式に対応しています
  • graph_attr、node_attr、edge_attr:Graphvizの属性オプションをサポートしています
from diagrams import Diagram
from diagrams.gcp.compute import ComputeEngine

def main():
    with Diagram("Basic Diagram", show=False, filename="basic_diagram", outformat="jpg"):
        web_server = ComputeEngine("Web Server")
        
        web_server
    
    print("完了: 00_basic_diagram.jpg が生成されました")

if __name__ == "__main__":
    main()

00_basic_diagram.jpg

Nodes

Node

Node(ノード)とはシステムのコンポーネントを表す単位です。
1つのノードは1つのコンポーネントを抽象的に表します。例えば、Compute Engineはノードとして表現されます。
Diagramsは主要なクラウドプロバイダーのノードが用意されており、公式ページから参照することが可能です。主要な3サービスのリンクが以下です。リンク先の情報を参考にしてfrom diagrams.gcp.compute import ComputeEngineのように記述することで、この場合だと「ComputeEngine」をノードとして利用できます。

Data Flow

ノード間はデータフローによって接続を表現することができます。コードでusers >> web_server >> databaseとなっている部分がそれに相当し、次のような記号を用いることができます。

  • >>:左から右方向への接続。イメージは「→」
  • <<:右から左方向への接続。イメージは「←」
  • -:無方向の接続。イメージは「-」
"""
基本的なNodes(ノード)の使用
"""

from diagrams import Diagram
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.onprem.client import Users

def main():
    with Diagram("Basic Nodes", show=False, filename="01_basic_nodes"):
        users = Users("Users")
        web_server = ComputeEngine("Web Server")
        database = SQL("Database")
        
        users >> web_server >> database
    
    print("完了: 01_basic_nodes.png が生成されました")

if __name__ == "__main__":
    main()


01_basic_nodes.png

またDiagram()directionオプションを指定することで、アーキテクチャ図全体のデータフローの流れる向きを指定することができます。デフォルトではLRになっています。指定できるパラメータは次の通りです。

  • TB:上から下への向き
  • BT:下から上への向き
  • LR:左から右への向き
  • RL:右から左への向き

上記のコードのDiagram部分を一部修正し、TB向きのアーキテクチャ図を作成してみると以下のようになります。
with Diagram("Basic Nodes", show=False, filename="01_basic_nodes_TB", direction="TB"):

01_basic_nodes_TB.png

データフロー全体の流れる向きが変わっていることがわかります。

Data Flow(グループ)

データフローは、複数のノードを[]で囲むことによってグループ化することが可能です。サンプルのコードを少し修正してグループの例を示します。
この例では、ComputeEngineのWeb Serverが3台に増えてグループ化されています。

出力されたアーキテクチャ図を見てみると、Usersからグループ化された3つのWeb Serverに対してデータフローが繋がっており、それぞれのWeb Serverからデータベースにデータフローが繋がっていることがわかります。
このように複数のリソースをグループとして扱うことが可能です。

"""
基本的なNodes(ノード)の使用
"""

from diagrams import Diagram
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.onprem.client import Users

def main():
    
    with Diagram("Basic Nodes", show=False, filename="01_basic_nodes"):
        users = Users("Users")
        web_server1 = ComputeEngine("Web Server")
        web_server2 = ComputeEngine("Web Server 2")
        web_server3 = ComputeEngine("Web Server 3")
        database = SQL("Database")
        
        users >> [web_server1, web_server2, web_server3] >> database
    
    print("完了: 01_basic_nodes.png が生成されました")

if __name__ == "__main__":
    main()

01_basic_nodes_group.png

Clusters

Cluster(クラスター)はノードをまとめてクラスター化するための仕組みです。データフローのグループ化がデータの流れ(矢印・線)をまとめるものだったのに対し、クラスターはそこに含まれるノードを視覚的にグルーピングし、複数のノードが含まれたのような表現を提供します。

クラスターはwith Cluster("<ラベル名>"):のように記述します。
このクラスター以下に書かれたノードがそのクラスターに所属し、クラスターはネストすることもできます。

"""
クラスターを使ったグループ化
"""

from diagrams import Diagram, Cluster
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.gcp.network import LoadBalancing
from diagrams.gcp.storage import Storage
from diagrams.onprem.client import Users

def main():
    with Diagram("Clusters with Grouping", show=False, filename="02_clusters"):
        users = Users("Users")
        
        # クラスターでグループ化
        with Cluster("Google Cloud"):
            load_balancer = LoadBalancing("Load Balancer")
            
            with Cluster("Web Tier"):
                web_servers = [
                    ComputeEngine("Web1"),
                    ComputeEngine("Web2")
                ]
            
            with Cluster("Data Tier"):
                database = SQL("Database")
                storage = Storage("Storage")
        
        # 接続の定義
        users >> load_balancer
        load_balancer >> web_servers
        web_servers >> database
        web_servers >> storage
    
    print("完了: 02_clusters.png が生成されました")

if __name__ == "__main__":
    main()

02_clusters.png

Edges

Edge(エッジ)はノード間の接続に関する表現を拡張する機能です。
ノード間の接続に対して次のような属性を拡張します

  • ラベル
  • スタイル

エッジは次のような書き方で表現します。>> Edge(label="HTTPS", color="blue", style="bold") >>
エッジの接続には>> Edge(~~) <<のように双方向の接続などを作成することも可能です。

"""
接続線の色、スタイル、ラベルを変更する例
"""

from diagrams import Diagram, Cluster, Edge
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.gcp.storage import Storage
from diagrams.onprem.client import Users

def main():
    
    with Diagram("Custom Edges", show=False, filename="03_custom_edges"):
        users = Users("Users")
        
        with Cluster("System"):
            web = ComputeEngine("Web Server")
            db = SQL("Database")
            cache = ComputeEngine("Cache")
            storage = Storage("Files")
        
        # 様々なエッジのスタイル
        users >> Edge(label="HTTPS", color="blue", style="bold") >> web
        web >> Edge(label="SQL", color="red") >> db
        web >> Edge(label="Cache", color="green", style="dashed") >> cache
        web >> Edge(label="Files", color="orange") >> storage
        
        # 双方向のエッジ
        cache << Edge(label="Sync", color="purple") >> db
    
    print("完了: 03_custom_edges.png が生成されました")

if __name__ == "__main__":
    main()

03_custom_edges.png

複合的なアーキテクチャ図

今までに説明したノード、クラスター、エッジを複合してアーキテクチャ図を作ってみます。
実際にクラウドアーキテクチャを設計する際にはこの例のように様々な要素を組み合わせることが想定されます。

"""
統合例: Nodes、Clusters、Edgesを全て活用
学習目的のためのシンプルなアーキテクチャ図
"""

from diagrams import Diagram, Cluster, Edge
from diagrams.gcp.compute import ComputeEngine
from diagrams.gcp.database import SQL
from diagrams.gcp.network import LoadBalancing
from diagrams.gcp.storage import Storage
from diagrams.onprem.client import Users

def main():
    with Diagram("Simple Architecture", show=False, filename="04_comprehensive"):
        # 外部ユーザー
        users = Users("Users")
        
        # Google Cloudプラットフォーム
        with Cluster("Google Cloud"):
            # ロードバランサー
            lb = LoadBalancing("Load Balancer")
            
            # アプリケーション層
            with Cluster("Web Layer"):
                web1 = ComputeEngine("Web-1")
                web2 = ComputeEngine("Web-2")
            
            # データ層
            with Cluster("Data Layer"):
                database = SQL("Database")
                storage = Storage("Storage")
        
        # 基本的な接続(Nodes学習)
        users >> lb
        lb >> [web1, web2]
        
        # カスタムエッジでの接続(Edges学習)
        web1 >> Edge(label="SQL", color="red") >> database
        web2 >> Edge(label="SQL", color="red") >> database
        web1 >> Edge(label="Files", color="blue", style="dashed") >> storage
        web2 >> Edge(label="Files", color="blue", style="dashed") >> storage
    
    print("完了: 04_comprehensive.png が生成されました")
    print("\nこの例では以下を学習できます:")
    print("- Nodes: Users, LoadBalancing, ComputeEngine, SQL, Storage")
    print("- Clusters: Google Cloud内のWeb LayerとData Layer")
    print("- Edges: SQLとFilesの接続を色とスタイルで区別")

if __name__ == "__main__":
    main()

この例では「users」と「Load Balancer」が単純なノードで接続されていることがわかります。
各種リソースはGoogle Cloudのプラットフォーム上に存在するため、「Google Cloud」クラスターを最上位レベルに記述しています。また、アーキテクチャで「Web Layer」レベルと「Data Layer」レベルのリソースをそれぞれクラスター化して記述しており、これらのクラスターは「Google Cloud」クラスター内にネストされた構造になっています。このようにクラスターはネストすることができ、これを活用することで見やすいアーキテクチャ設計の助けになります。

それぞれのサーバーがどのデータリソースに接続しているかを視覚的にわかりやすく表現するためにエッジ機能を活用しています。エッジのオプションを用いることで、接続の色や線の種類などがカスタムされ、より理解しやすいアーキテクチャ図になっています。

04_comprehensive.png

まとめ

今回はアーキテクチャ図を作成する手段として、Diagramsという例を紹介しました。
このツールの特長としては、主要なクラウドプロバイダーに対応していること、コードベースでアーキテクチャ図の記述ができることかと思います。
コードベースなのでGitHubなどのバージョン管理システムとの親和性が良く、変更差分も理解しやすいです。また、pythonベースですので多くのエンジニアにとって習得コストがそれほど大きくないかもしれないこともメリットになりそうです。
私も実務で活用していきたいと思います!最後までお読みいただきありがとうございました!

参考文献

15
6
0

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
15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?