- Home »

Создание диаграмм в 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% задач по созданию технических схем это идеальное решение. Главное — начать использовать и постепенно наращивать автоматизацию.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.