Home » Создание диаграмм в Python с помощью инструментов diagram-as-code
Создание диаграмм в Python с помощью инструментов diagram-as-code

Создание диаграмм в Python с помощью инструментов diagram-as-code

Наверное, каждый из нас хотя бы раз в жизни втыкал в Paint или LibreOffice Draw, пытаясь нарисовать схему инфраструктуры для документации. Или тратил часы на создание красивых диаграмм в Visio, которые через неделю уже устарели. Если ты устал от этой рутины и хочешь генерировать диаграммы прямо из кода — добро пожаловать в мир diagram-as-code в Python! Это не только сэкономит время, но и позволит версионировать схемы через git, автоматизировать их создание и поддерживать в актуальном состоянии.

Сегодня разберёмся, как создавать красивые диаграммы инфраструктуры, сетевых схем и архитектуры приложений с помощью Python-библиотек. Это особенно полезно для документирования серверных решений, создания схем для заказчиков и автоматизации отчётности.

Что такое diagram-as-code и зачем это нужно?

Diagram-as-code — это подход к созданию диаграмм через программный код вместо графических редакторов. Основные преимущества:

  • Версионирование: диаграммы хранятся в git вместе с кодом
  • Автоматизация: можно интегрировать в CI/CD пайплайны
  • Консистентность: единый стиль для всех схем
  • Скорость: быстрее рисовать код, чем таскать блоки мышкой
  • Интеграция: можно генерировать схемы из данных мониторинга

Основные Python-библиотеки для diagram-as-code

Рассмотрим три топовые библиотеки с их плюсами и минусами:

Библиотека Плюсы Минусы Лучше всего подходит для
Diagrams Красивые иконки AWS/GCP/Azure, простой синтаксис Ограниченная кастомизация, только растровые форматы Схемы облачной инфраструктуры
Graphviz Мощные алгоритмы размещения, векторный вывод Сложный синтаксис, не очень красивые иконки Сложные графы зависимостей
Mermaid Поддержка в GitHub/GitLab, интерактивность Ограниченные возможности стилизации Быстрые схемы в документации

Установка и настройка Diagrams

Начнём с самой популярной библиотеки для инфраструктурных схем. Для работы потребуется Python 3.6+ и Graphviz:

# Ubuntu/Debian
sudo apt-get install graphviz
pip install diagrams

# CentOS/RHEL
sudo yum install graphviz
pip install diagrams

# macOS
brew install graphviz
pip install diagrams

Если планируешь запускать это на сервере, лучше использовать виртуальное окружение:

python3 -m venv diagram_env
source diagram_env/bin/activate
pip install diagrams pillow

Создание первой диаграммы

Начнём с простой схемы веб-приложения с балансировщиком нагрузки:

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

with Diagram("Simple Web App", show=False, direction="TB"):
    lb = ELB("Load Balancer")
    
    web_servers = [
        EC2("Web Server 1"),
        EC2("Web Server 2"),
        EC2("Web Server 3")
    ]
    
    db = RDS("Database")
    storage = S3("Static Files")
    
    lb >> web_servers
    web_servers >> db
    web_servers >> storage

Этот код создаст PNG-файл с красивой схемой. Параметр show=False отключает автоматическое открытие файла (полезно для серверов без GUI).

Продвинутые возможности и кастомизация

Теперь создадим более сложную схему с группировкой и кластерами:

from diagrams import Cluster, Diagram
from diagrams.aws.compute import EC2, AutoScaling
from diagrams.aws.network import ELB, CloudFront
from diagrams.aws.database import RDS, ElastiCache
from diagrams.aws.storage import S3
from diagrams.aws.security import WAF
from diagrams.onprem.client import Users

with Diagram("Production Infrastructure", show=False, direction="TB"):
    users = Users("Users")
    
    with Cluster("CDN & Security"):
        cdn = CloudFront("CloudFront")
        waf = WAF("Web Application Firewall")
    
    with Cluster("Load Balancing"):
        alb = ELB("Application Load Balancer")
    
    with Cluster("Web Tier"):
        with Cluster("Auto Scaling Group"):
            web_servers = [
                EC2("Web 1"),
                EC2("Web 2"),
                EC2("Web 3")
            ]
            asg = AutoScaling("Auto Scaling")
    
    with Cluster("Database Tier"):
        db_primary = RDS("Primary DB")
        db_replica = RDS("Read Replica")
        cache = ElastiCache("Redis Cache")
    
    with Cluster("Storage"):
        s3_static = S3("Static Assets")
        s3_backup = S3("Backups")
    
    # Connections
    users >> cdn >> waf >> alb
    alb >> web_servers
    web_servers >> cache
    web_servers >> db_primary
    db_primary >> db_replica
    web_servers >> s3_static
    db_primary >> s3_backup

Создание схем с Graphviz

Для более сложных графов зависимостей лучше использовать Graphviz напрямую:

import graphviz

def create_network_topology():
    dot = graphviz.Digraph('network', comment='Network Topology')
    dot.attr(rankdir='TB', size='10,8')
    
    # Стили узлов
    dot.attr('node', shape='box', style='rounded,filled')
    
    # Интернет
    dot.node('internet', 'Internet', fillcolor='lightblue')
    
    # Файрвол
    dot.node('fw', 'Firewall\n192.168.1.1', fillcolor='red')
    
    # Коммутаторы
    dot.node('sw1', 'Switch 1\nVLAN 10', fillcolor='yellow')
    dot.node('sw2', 'Switch 2\nVLAN 20', fillcolor='yellow')
    
    # Серверы
    dot.node('web1', 'Web Server 1\n192.168.10.10', fillcolor='lightgreen')
    dot.node('web2', 'Web Server 2\n192.168.10.11', fillcolor='lightgreen')
    dot.node('db1', 'Database\n192.168.20.10', fillcolor='orange')
    
    # Соединения
    dot.edge('internet', 'fw', label='WAN')
    dot.edge('fw', 'sw1', label='eth0')
    dot.edge('fw', 'sw2', label='eth1')
    dot.edge('sw1', 'web1', label='1Gbps')
    dot.edge('sw1', 'web2', label='1Gbps')
    dot.edge('sw2', 'db1', label='1Gbps')
    dot.edge('web1', 'db1', label='3306', style='dashed')
    dot.edge('web2', 'db1', label='3306', style='dashed')
    
    return dot

# Создание и сохранение диаграммы
network_diagram = create_network_topology()
network_diagram.render('network_topology', format='png', cleanup=True)

Интеграция с мониторингом и автоматизация

Самая крутая фича — автоматическое создание диаграмм из данных мониторинга. Вот пример скрипта, который создаёт схему на основе данных из Prometheus:

import requests
import json
from diagrams import Diagram
from diagrams.generic.compute import Rack
from diagrams.generic.network import Switch

def get_servers_from_prometheus():
    # Запрос к Prometheus API
    response = requests.get('http://prometheus:9090/api/v1/query?query=up')
    data = response.json()
    
    servers = []
    for result in data['data']['result']:
        if result['value'][1] == '1':  # Сервер доступен
            instance = result['metric']['instance']
            servers.append(instance)
    
    return servers

def create_monitoring_diagram():
    servers = get_servers_from_prometheus()
    
    with Diagram("Active Servers", show=False):
        switch = Switch("Network Switch")
        
        server_nodes = []
        for server in servers:
            server_node = Rack(f"Server\n{server}")
            server_nodes.append(server_node)
            switch >> server_node

create_monitoring_diagram()

Создание диаграмм для Docker и Kubernetes

Для контейнерных решений есть специальные иконки:

from diagrams import Cluster, Diagram
from diagrams.k8s.compute import Pod, ReplicaSet
from diagrams.k8s.network import Service, Ingress
from diagrams.k8s.storage import PV, PVC
from diagrams.onprem.container import Docker

with Diagram("Kubernetes Architecture", show=False, direction="TB"):
    
    ingress = Ingress("Ingress Controller")
    
    with Cluster("Namespace: production"):
        svc = Service("Web Service")
        
        with Cluster("ReplicaSet"):
            pods = [
                Pod("Pod 1"),
                Pod("Pod 2"),
                Pod("Pod 3")
            ]
        
        with Cluster("Storage"):
            pv = PV("Persistent Volume")
            pvc = PVC("PVC")
    
    with Cluster("Docker Registry"):
        registry = Docker("Private Registry")
    
    ingress >> svc >> pods
    pvc >> pv
    pods >> pvc
    registry >> pods

Автоматизация через CI/CD

Чтобы диаграммы всегда были актуальными, можно интегрировать их создание в pipeline. Пример для GitLab CI:

# .gitlab-ci.yml
generate_diagrams:
  stage: documentation
  image: python:3.9
  before_script:
    - apt-get update && apt-get install -y graphviz
    - pip install diagrams
  script:
    - python generate_diagrams.py
    - mkdir -p public/diagrams
    - mv *.png public/diagrams/
  artifacts:
    paths:
      - public/diagrams/
  only:
    - main

Создание интерактивных диаграмм с Plotly

Для более интерактивного опыта можно использовать Plotly:

import plotly.graph_objects as go
import plotly.offline as offline

def create_interactive_network():
    # Узлы
    node_x = [0, 1, 2, 1, 1.5, 0.5]
    node_y = [0, 1, 0, 2, 3, 3]
    node_text = ['Internet', 'Firewall', 'Switch', 'Load Balancer', 'Web Server 1', 'Web Server 2']
    
    # Рёбра
    edge_x = []
    edge_y = []
    edges = [(0, 1), (1, 2), (2, 3), (3, 4), (3, 5)]
    
    for edge in edges:
        x0, y0 = node_x[edge[0]], node_y[edge[0]]
        x1, y1 = node_x[edge[1]], node_y[edge[1]]
        edge_x.extend([x0, x1, None])
        edge_y.extend([y0, y1, None])
    
    # Создание графика
    fig = go.Figure()
    
    # Добавление рёбер
    fig.add_trace(go.Scatter(x=edge_x, y=edge_y,
                            line=dict(width=2, color='#888'),
                            hoverinfo='none',
                            mode='lines'))
    
    # Добавление узлов
    fig.add_trace(go.Scatter(x=node_x, y=node_y,
                            mode='markers+text',
                            text=node_text,
                            textposition="middle center",
                            hoverinfo='text',
                            marker=dict(size=50,
                                       color='lightblue',
                                       line=dict(width=2, color='black'))))
    
    fig.update_layout(title='Interactive Network Diagram',
                     showlegend=False,
                     width=800,
                     height=600)
    
    offline.plot(fig, filename='network_interactive.html')

create_interactive_network()

Нестандартные способы использования

Вот несколько крутых идей для продвинутого использования:

  • Генерация диаграмм из логов: парсинг access.log и создание схемы трафика
  • Визуализация Ansible playbooks: автоматическое создание схем развёртывания
  • Диаграммы безопасности: визуализация firewall rules и network policies
  • Capacity planning: схемы с метриками загрузки из мониторинга

Пример создания диаграммы из конфигурации Terraform:

import json
import hcl2
from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.network import VPC

def parse_terraform_config(tf_file):
    with open(tf_file, 'r') as file:
        tf_dict = hcl2.load(file)
    
    resources = tf_dict.get('resource', {})
    
    with Diagram("Terraform Infrastructure", show=False):
        vpc = VPC("Main VPC")
        
        instances = []
        for resource_type, resource_configs in resources.items():
            if resource_type == 'aws_instance':
                for name, config in resource_configs.items():
                    instance = EC2(f"Instance: {name}")
                    instances.append(instance)
                    vpc >> instance

parse_terraform_config('main.tf')

Производительность и оптимизация

При работе с большими схемами важно учитывать производительность:

  • Кэширование: сохраняй промежуточные результаты для больших диаграмм
  • Параллелизация: используй multiprocessing для генерации множества схем
  • Оптимизация памяти: очищай объекты после использования
import multiprocessing as mp
from diagrams import Diagram
from diagrams.aws.compute import EC2

def create_diagram(server_group):
    name, servers = server_group
    
    with Diagram(f"Server Group: {name}", show=False):
        server_nodes = []
        for server in servers:
            server_node = EC2(server)
            server_nodes.append(server_node)

# Параллельная генерация диаграмм
server_groups = [
    ('Web Servers', ['web1', 'web2', 'web3']),
    ('DB Servers', ['db1', 'db2']),
    ('Cache Servers', ['cache1', 'cache2'])
]

with mp.Pool(processes=3) as pool:
    pool.map(create_diagram, server_groups)

Интеграция с облачными провайдерами

Можно автоматически создавать диаграммы, опрашивая API облачных провайдеров:

import boto3
from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.network import VPC

def create_aws_diagram():
    ec2 = boto3.client('ec2')
    
    # Получение информации о VPC
    vpcs = ec2.describe_vpcs()
    
    # Получение информации об инстансах
    instances = ec2.describe_instances()
    
    with Diagram("AWS Infrastructure", show=False):
        for vpc in vpcs['Vpcs']:
            vpc_id = vpc['VpcId']
            
            with Cluster(f"VPC: {vpc_id}"):
                vpc_node = VPC(f"VPC\n{vpc_id}")
                
                # Инстансы в данном VPC
                for reservation in instances['Reservations']:
                    for instance in reservation['Instances']:
                        if instance['VpcId'] == vpc_id:
                            instance_name = instance.get('InstanceId', 'Unknown')
                            instance_node = EC2(instance_name)
                            vpc_node >> instance_node

create_aws_diagram()

Альтернативные решения и сравнение

Кроме Python-библиотек есть и другие инструменты для diagram-as-code:

Инструмент Язык Плюсы Минусы
PlantUML Java/DSL Богатый функционал, много типов диаграмм Требует Java, сложный синтаксис
Mermaid JavaScript Встроен в GitHub/GitLab Ограниченная кастомизация
Nomnoml JavaScript Простой синтаксис Только UML диаграммы
Diagrams (Python) Python Красивые иконки, простота Только инфраструктурные схемы

Деплой и хостинг решений

Для автоматизации создания диаграмм понадобится сервер. Если нужен простой VPS для скриптов, то подойдёт минимальная конфигурация. Для серьёзных задач с обработкой больших схем лучше взять выделенный сервер.

Пример Dockerfile для контейнеризации:

FROM python:3.9-slim

RUN apt-get update && apt-get install -y \
    graphviz \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "diagram_generator.py"]

Заключение и рекомендации

Diagram-as-code — это мощный инструмент для современных DevOps-инженеров и системных администраторов. Вот основные рекомендации:

  • Начни с Diagrams: если нужны схемы инфраструктуры — это лучший выбор
  • Используй Graphviz: для сложных графов зависимостей и нестандартных схем
  • Интегрируй в CI/CD: автоматическое обновление диаграмм сэкономит массу времени
  • Версионируй схемы: храни код диаграмм в git рядом с основным кодом
  • Автоматизируй: подключай к мониторингу и облачным API

Самые полезные кейсы использования:

  • Документирование инфраструктуры для новых сотрудников
  • Создание схем для презентаций заказчикам
  • Автоматическое обновление диаграмм при изменении конфигурации
  • Визуализация мониторинга и алертов
  • Планирование изменений и миграций

Diagram-as-code не заменит все графические редакторы, но для 80% задач по созданию технических схем это идеальное решение. Главное — начать использовать и постепенно наращивать автоматизацию.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked