ちょっと話題の記事

Diagramsを使ってPythonでシステム構成図を描く

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Pythonでシステム構成図を書ける、DiagramsというOSSが便利そうだったので試してみました。

対応プロバイダ

現在、Diagramsは以下の7種類のプロバイダに対応しています。各プロバイダが提供している各種サービスがノードとして対応されています。以下は対応プロバイダとそのノード一覧へのリンクです。

オンプレミスプロバイダには、GitHubやCircleCIといったサービス、汎用的なクライアント、各種DBなど幅広い種類のノードが含まれています。このアイコンないかなと思った場合は、オンプレミスプロバイダを調べてみるともしかしたらあるかもしれません。

試してみる

AWS上のシステム構成図を書いてみて各機能を試していきます。

まずはDiagramsをインストールします。

pip install diagrams

Diagramsを使うためにはGraphvizが必要となります。インストールされていない環境の場合は、ドキュメントに従い、インストールしてください。macOSの場合はbrew install graphvizでインストールできます。

基本

diagrams.Diagramを使ってコンテキストを作成することで、図を表示できます。 図を構成する要素であるノードはdiagrams.{プロバイダ}.{リソースタイプ}.{名前}という形式で参照できます。 ノード同士の関係性は無向の場合は-、有向の場合は>><<で表すことができます。

クライアントからのイベントデータの流れを書いてみます。

sample.py

from diagrams import Diagram
from diagrams.aws.compute import Lambda
from diagrams.aws.ml import Personalize
from diagrams.aws.analytics import KinesisDataStreams, KinesisDataFirehose, Athena, Quicksight, Glue
from diagrams.onprem.client import Client
from diagrams.aws.storage import S3

with Diagram('イベントストリーミング'):
    # インスタンス化によってノードを作成
    # ノードにラベルを付与でき、\nを入れることでラベルの改行も可能
    stream = KinesisDataStreams('Kinesis\nData Streams')
    s3 = S3('S3')
    athena = Athena('Athena')

    # 定義したノードを始点とした流れを作成
    # 変数に代入せずとも、ノードは作成可能
    Client() >> stream >> Lambda('Lambda') >> Personalize('Personalize\nEventTracker')
    stream >> KinesisDataFirehose('Kinesis\nData Firehose') >> s3
    s3 - athena >> Quicksight('QuickSight') << Client()
    s3 >> Glue('Glue') >> athena

スクリプトを実行し、図を作成します。

python sample.py

実行が完了すると、作成した図が表示されます。

図はPNG形式で保存されています。

Diagramの設定

Diagramでは次のような引数で図に関する情報を設定できます。

  • name: 図の名前
  • filename: ファイル名(デフォルト: nameによって決まる)
    • 拡張子はoutformatによって定まるため含めない
  • outformat: 図の保存形式(デフォルト: png)
    • png、jpg、svg、pdf
  • show: スクリプト実行時に作成した図を表示するかどうか(デフォルト: True)
  • direction: データフローの向き(デフォルト: LR)
    • TB、BT、LR、RL
  • graph_attr、node_attr、edge_attr: Graphvizでの図全体、ノード、エッジの設定情報

先ほどと同様の構成で、図の設定を次のように変更してみます。

from diagrams import Diagram
from diagrams.aws.compute import Lambda
from diagrams.aws.ml import Personalize
from diagrams.aws.analytics import KinesisDataStreams, KinesisDataFirehose, Athena, Quicksight, Glue
from diagrams.onprem.client import Client
from diagrams.aws.storage import S3

graph_attr = {
    'bgcolor': 'gray',
    'fontsize': '28'
}

node_attr = {
    'fontsize': '14'
}

edge_attr = {
    'arrowsize': '2.0',
    'penwidth': '5.0'
}

with Diagram(name='イベントストリーミング2', filename='event_streaming', show=True, direction='TB', graph_attr=graph_attr, edge_attr=edge_attr, node_attr=node_attr):

    # インスタンス化によってノードを作成
    # ノードにラベルを付与でき、\nを入れることでラベルの改行も可能
    stream = KinesisDataStreams('Kinesis\nData Streams')
    s3 = S3('S3')
    athena = Athena('Athena')

    # 定義したノードを始点とした流れを作成
    # 変数に代入せずとも、ノードは作成可能
    Client() >> stream >> Lambda('Lambda') >> Personalize('Personalize\nEventTracker')
    stream >> KinesisDataFirehose('Kinesis\nData Firehose') >> s3
    s3 - athena >> Quicksight('QuickSight') << Client()
    s3 >> Glue('Glue') >> athena

見やすい図とは言えませんが、先ほどとは雰囲気が変わった図になりました。好みや用途に応じて設定をカスタマイズすると良さそうです。

グループ化

ノードをリストに格納することで、ひとまとめに扱うことができます。

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

with Diagram('グループサンプル'):
    ELB() >> [EC2(), EC2(), EC2()]

クラスター

diagrams.Clusterを使うことで、複数のノードを網掛けしてクラスターとして設定することができます。 クラスターは引数としてlabeldirectionが設定できますが、directionは今の所、機能していないようです。

from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.network import ELB
from diagrams.onprem.client import Client


with Diagram('クラスターサンプル'):

    client = Client()

    with Cluster('AWS'):
        elb = ELB()
        client >> elb

        # クラスターはネストさせることもできる
        with Cluster('Auto Scaling Group'):
            elb >> [EC2(), EC2()]

エッジ

diagrams.Edgeを使うことで、ノード間のエッジ(辺、Edge)をカスタマイズできます。 エッジは引数としてlabelcolorstyleが主に設定できます。他にもGraphVizが対応している各項目も設定可能です。

from diagrams import Diagram, Edge
from diagrams.aws.compute import EC2
from diagrams.onprem.client import Client

with Diagram('エッジサンプル'):
    Client() >> Edge(color='blue', style='dashed') >> EC2() >> Edge(style='bold', arrowsize='2') >> EC2()

さいごに

Diagramsを使ったシステム構成図の作成について試した内容を紹介しました。Diagramsを使った構成図作成は、要素間を結ぶ線(エッジ)のことをあまり考えなくて良いのと、コードなのでコンポーネントの切り貼りや修正が楽で、試行錯誤がしやすかったです。こういうツールを積極的に活用し、楽できるところは楽したいですね。