docs: add styled infrastructure dependency diagram (generator + png + svg)
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Генератор схемы зависимостей облачных сервисов (PNG + SVG).
|
||||
|
||||
Содержание подтверждено YAML-контрактами generated/dev/resources_yaml.
|
||||
PNG рисуется в 2x и уменьшается (сглаживание), SVG — вектор.
|
||||
"""
|
||||
import os
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
W, H = 1600, 720
|
||||
SS = 2 # supersample
|
||||
|
||||
FONT_R = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
|
||||
FONT_B = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
|
||||
|
||||
DARK = "#1A1A1A"
|
||||
GRAY = "#5F6B76"
|
||||
MUTED = "#7A8794"
|
||||
TEXT = "#2E3A45"
|
||||
RED = "#C62828"
|
||||
LINE = "#455A64"
|
||||
|
||||
COLS = [
|
||||
(16, "Шаг 1. Тенант", "базовый уровень изоляции", "#1565C0", "#E8F3FB"),
|
||||
(340, "Шаг 2. Пул ресурсов", "CPU / RAM / Storage", "#E65100", "#FDF1E3"),
|
||||
(664, "Шаг 3. Сетевой периметр", "маршрутизация и балансировка", "#4527A0", "#EEEAF8"),
|
||||
(988, "Шаг 4. Среда запуска", "контейнер и внешние адреса", "#EF6C00", "#FDF4E3"),
|
||||
(1312, "Шаг 5. Потребители", "что разворачивается в итоге", "#2E7D32", "#E9F5EA"),
|
||||
]
|
||||
COL_W = 270
|
||||
|
||||
# блоки: (x, y, w, h, заголовок-строки, подпись, строки, бейдж, рамка, фон, пунктир)
|
||||
BLOCKS = [
|
||||
(31, 150, 240, 150, ["Организация", "в Cloud Director"], "Сервис 19 · vcOrg",
|
||||
["Типы: iaas / saas"], None, "#0288D1", "#FFFFFF", False),
|
||||
(355, 130, 240, 230, ["Виртуальный", "датацентр (vDC)"], "Сервис 21 · vcVdc",
|
||||
["cpuGuaranteed: 0% / 50% / 80%", "cpuAllocated, memAllocated", "storageConfig"],
|
||||
"здесь выделяются CPU / RAM / Диск", "#F57C00", "#FFF3E0", False),
|
||||
(679, 120, 240, 200, ["Сетевой шлюз", "периметра (Edge)"], "Сервис 22 · vcNsxt",
|
||||
["AVI Load Balancer", "routed-сеть 10.10.102.0/24"],
|
||||
"SNAT настраивается операцией modify", "#5E35B1", "#EDE7F6", False),
|
||||
(1003, 100, 240, 110, ["Каталог ВМ (vApp)"], "Сервис 26 · vapp",
|
||||
["логический контейнер для ВМ"], None, "#F57C00", "#FFF3E0", False),
|
||||
(1003, 245, 180, 150, ["Внешние IP"], "Сервис 25",
|
||||
["выделение: vcOrg", "NAT: сервис 25", "квота IP (ipSpace)"],
|
||||
"здесь выделяются IP", "#9E9E9E", "#FAFAFA", True),
|
||||
(1327, 100, 240, 120, ["Виртуальная машина"], "Сервис 28 · vc_vm_v3",
|
||||
["vmCpu · vmRam · vmDisk"], None, "#2E7D32", "#E8F5E9", False),
|
||||
(1327, 255, 240, 170, ["Kubernetes кластер", "Штурвал"], "Сервис 150",
|
||||
["sizingPolicy · sizingDisk", "· count"], "требует ALB + VS ≥ 3",
|
||||
"#2E7D32", "#E8F5E9", False),
|
||||
]
|
||||
|
||||
# связи: (точки, цвет, толщина, пунктир, подпись, позиция подписи, вертикальная)
|
||||
EDGES = [
|
||||
([(271, 225), (355, 225)], LINE, 2, False, "organizationUid", (313, 262), True),
|
||||
([(595, 200), (679, 200)], LINE, 2, False, "vdcUid", (637, 186), False),
|
||||
([(500, 130), (500, 92), (961, 92), (961, 140), (1003, 140)], LINE, 2, False,
|
||||
"vdcUid", (706, 96), False),
|
||||
([(919, 180), (1003, 180)], LINE, 2, False, "nsxtUid", (961, 166), False),
|
||||
([(1243, 140), (1327, 140)], LINE, 2, False, "vappUid", (1285, 126), False),
|
||||
([(500, 360), (500, 470), (1447, 470), (1447, 425)], LINE, 2, False,
|
||||
"vdcUid", (1180, 456), False),
|
||||
([(799, 320), (799, 505), (1467, 505), (1467, 425)], LINE, 2, False,
|
||||
"nsxtUid", (1180, 491), False),
|
||||
([(151, 300), (151, 540), (1050, 540), (1050, 395)], MUTED, 2, True,
|
||||
"modify: vIPConfigure", (161, 526), False),
|
||||
([(870, 320), (870, 400), (1140, 400), (1140, 395)], MUTED, 2, True,
|
||||
"modify: SNAT", (880, 386), False),
|
||||
([(1183, 270), (1255, 270), (1255, 160), (1327, 160)], MUTED, 2, True,
|
||||
"внешний IP", (1187, 222), False),
|
||||
([(1183, 350), (1327, 350)], RED, 2, True, "≥ 3 адреса", (1187, 330), False),
|
||||
]
|
||||
|
||||
CAPTION = [
|
||||
"Порядок создания: Организация → vDC → Edge → (vApp + внешние IP) → ВМ / Штурвал.",
|
||||
"SNAT — не отдельный сервис, а операция modify у Edge.",
|
||||
"vDC и Edge могут быть переиспользованы существующие.",
|
||||
]
|
||||
|
||||
|
||||
def op_rect(x, y, w, h, fill, outline, lw=2, r=10, dash=False):
|
||||
return ("rect", (x, y, w, h, fill, outline, lw, r, dash))
|
||||
|
||||
|
||||
def op_text(x, y, s, size, color, bold=False, anchor="lt", vertical=False):
|
||||
return ("text", (x, y, s, size, color, bold, anchor, vertical))
|
||||
|
||||
|
||||
def op_path(pts, color, lw, dash):
|
||||
return ("path", (pts, color, lw, dash))
|
||||
|
||||
|
||||
def op_dot(x, y, r, color):
|
||||
return ("dot", (x, y, r, color))
|
||||
|
||||
|
||||
def build():
|
||||
ops = []
|
||||
for cx, title, sub, accent, tint in COLS:
|
||||
ops.append(op_rect(cx, 8, COL_W, 552, tint, "#FFFFFF", 0, 12))
|
||||
ops.append(op_rect(cx, 14, COL_W, 44, accent, accent, 0, 8))
|
||||
ops.append(op_text(cx + COL_W / 2, 25, title, 15, "#FFFFFF", True, "mt"))
|
||||
ops.append(op_text(cx + COL_W / 2, 68, sub, 12, MUTED, False, "mt"))
|
||||
|
||||
for x, y, w, h, titles, sub, lines, badge, border, fill, dashed in BLOCKS:
|
||||
ops.append(op_rect(x, y, w, h, fill, border, 2, 10, dashed))
|
||||
ops.append(op_rect(x + 12, y + 12, 22, 22, border, border, 0, 5))
|
||||
tx = x + 42
|
||||
ty = y + 12
|
||||
for i, t in enumerate(titles):
|
||||
ops.append(op_text(tx, ty + i * 20, t, 15, DARK, True))
|
||||
sy = ty + len(titles) * 20
|
||||
ops.append(op_text(tx, sy, sub, 11, GRAY))
|
||||
ly = sy + 22
|
||||
for ln in lines:
|
||||
ops.append(op_dot(x + 20, ly + 7, 2.4, border))
|
||||
ops.append(op_text(x + 30, ly, ln, 10, TEXT))
|
||||
ly += 20
|
||||
if badge:
|
||||
ops.append(op_rect(x + 12, y + h - 42, w - 24, 30, "#FFFFFF", border, 1, 6))
|
||||
ops.append(op_text(x + w / 2, y + h - 32, badge, 10, border, False, "mt"))
|
||||
|
||||
for pts, color, lw, dash, label, pos, vertical in EDGES:
|
||||
ops.append(op_path(pts, color, lw, dash))
|
||||
ops.append(op_text(pos[0], pos[1], label, 10, color, False,
|
||||
"lt" if not vertical else "lt", vertical))
|
||||
|
||||
for i, s in enumerate(CAPTION):
|
||||
ops.append(op_text(24, 590 + i * 26, "> " + s, 14, TEXT))
|
||||
|
||||
ops.append(op_path([(980, 606), (1040, 606)], LINE, 2, False))
|
||||
ops.append(op_text(1052, 597, "Сплошная линия — обязательная зависимость", 11, TEXT))
|
||||
ops.append(op_text(1052, 613, "(ссылка на UUID существующего инстанса)", 10, MUTED))
|
||||
ops.append(op_path([(980, 650), (1040, 650)], MUTED, 2, True))
|
||||
ops.append(op_text(1052, 641, "Пунктир — выделение ресурса / операция modify", 11, TEXT))
|
||||
|
||||
swatches = [("#1565C0", "Тенант"), ("#F57C00", "Ресурсы"), ("#5E35B1", "Сеть"),
|
||||
("#2E7D32", "Потребители"), ("#9E9E9E", "Адреса")]
|
||||
sx = 980
|
||||
for color, name in swatches:
|
||||
ops.append(op_rect(sx, 684, 12, 12, color, color, 0, 3))
|
||||
ops.append(op_text(sx + 16, 682, name, 10, TEXT))
|
||||
sx += 20 + int(len(name) * 6.4)
|
||||
return ops
|
||||
|
||||
|
||||
def accent_of(border):
|
||||
return border
|
||||
|
||||
|
||||
def dash_segments(p1, p2, on=9, off=6):
|
||||
(x1, y1), (x2, y2) = p1, p2
|
||||
segs, total = [], ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
|
||||
if total == 0:
|
||||
return segs
|
||||
ux, uy = (x2 - x1) / total, (y2 - y1) / total
|
||||
pos = 0.0
|
||||
while pos < total:
|
||||
end = min(pos + on, total)
|
||||
segs.append(((x1 + ux * pos, y1 + uy * pos), (x1 + ux * end, y1 + uy * end)))
|
||||
pos = end + off
|
||||
return segs
|
||||
|
||||
|
||||
def arrow_head(d, tip, tail, color, size=9):
|
||||
(tx, ty), (px, py) = tip, tail
|
||||
dx, dy = tx - px, ty - py
|
||||
n = (dx * dx + dy * dy) ** 0.5 or 1
|
||||
ux, uy = dx / n, dy / n
|
||||
bx, by = tx - ux * size, ty - uy * size
|
||||
ox, oy = -uy * size * 0.42, ux * size * 0.42
|
||||
d.polygon([(tx, ty), (bx + ox, by + oy), (bx - ox, by - oy)], fill=color)
|
||||
|
||||
|
||||
def draw_polyline(d, pts, color, lw, dash):
|
||||
for a, b in zip(pts, pts[1:]):
|
||||
segs = dash_segments(a, b) if dash else [(a, b)]
|
||||
for s in segs:
|
||||
d.line([s[0], s[1]], fill=color, width=lw)
|
||||
if len(pts) >= 2:
|
||||
tail = pts[-2]
|
||||
tip = pts[-1]
|
||||
dx, dy = tip[0] - tail[0], tip[1] - tail[1]
|
||||
n = (dx * dx + dy * dy) ** 0.5 or 1
|
||||
shrink = 9
|
||||
tip2 = (tip[0] - dx / n * shrink, tip[1] - dy / n * shrink)
|
||||
d.line([tail, tip2], fill=color, width=lw)
|
||||
arrow_head(d, tip, tail, color)
|
||||
|
||||
|
||||
def render_png(ops, path):
|
||||
img = Image.new("RGB", (W * SS, H * SS), "#FFFFFF")
|
||||
d = ImageDraw.Draw(img)
|
||||
fonts = {}
|
||||
|
||||
def fnt(size, bold):
|
||||
key = (size, bold)
|
||||
if key not in fonts:
|
||||
fonts[key] = ImageFont.truetype(FONT_B if bold else FONT_R, size * SS)
|
||||
return fonts[key]
|
||||
|
||||
for kind, a in ops:
|
||||
if kind == "rect":
|
||||
x, y, w, h, fill, outline, lw, r, dashed = a
|
||||
box = [x * SS, y * SS, (x + w) * SS, (y + h) * SS]
|
||||
if dashed:
|
||||
d.rounded_rectangle(box, radius=r * SS, fill=fill)
|
||||
for a1, b1 in [((x, y), (x + w, y)), ((x + w, y), (x + w, y + h)),
|
||||
((x + w, y + h), (x, y + h)), ((x, y + h), (x, y))]:
|
||||
for s in dash_segments((a1[0] * SS, a1[1] * SS), (b1[0] * SS, b1[1] * SS),
|
||||
on=8 * SS, off=6 * SS):
|
||||
d.line([s[0], s[1]], fill=outline, width=max(1, lw * SS))
|
||||
else:
|
||||
d.rounded_rectangle(box, radius=r * SS, fill=fill,
|
||||
outline=outline if lw else None,
|
||||
width=max(1, lw * SS) if lw else 0)
|
||||
elif kind == "text":
|
||||
x, y, s, size, color, bold, anchor, vertical = a
|
||||
f = fnt(size, bold)
|
||||
if vertical:
|
||||
bbox = f.getbbox(s)
|
||||
tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||
tmp = Image.new("RGBA", (tw + 4, th + 4), (0, 0, 0, 0))
|
||||
ImageDraw.Draw(tmp).text((-bbox[0] + 2, -bbox[1] + 2), s, font=f, fill=color)
|
||||
tmp = tmp.rotate(90, expand=True)
|
||||
img.paste(tmp, (int(x * SS - tmp.width / 2), int(y * SS - tmp.height / 2)), tmp)
|
||||
else:
|
||||
d.text((x * SS, y * SS), s, font=f, fill=color, anchor=anchor)
|
||||
elif kind == "path":
|
||||
pts, color, lw, dash = a
|
||||
draw_polyline(d, [(px * SS, py * SS) for px, py in pts], color,
|
||||
max(1, lw * SS), dash)
|
||||
elif kind == "dot":
|
||||
x, y, r, color = a
|
||||
d.ellipse([(x - r) * SS, (y - r) * SS, (x + r) * SS, (y + r) * SS], fill=color)
|
||||
|
||||
img = img.resize((W, H), Image.LANCZOS)
|
||||
img.save(path)
|
||||
return path
|
||||
|
||||
|
||||
def render_svg(ops, path):
|
||||
out = [f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" '
|
||||
f'viewBox="0 0 {W} {H}" font-family="DejaVu Sans, Verdana, sans-serif">',
|
||||
f'<rect width="{W}" height="{H}" fill="#FFFFFF"/>']
|
||||
|
||||
def esc(s):
|
||||
return s.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
|
||||
for kind, a in ops:
|
||||
if kind == "rect":
|
||||
x, y, w, h, fill, outline, lw, r, dashed = a
|
||||
stroke = f' stroke="{outline}" stroke-width="{lw}"' if lw else ""
|
||||
dash = ' stroke-dasharray="9 6"' if dashed else ""
|
||||
out.append(f'<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="{r}" '
|
||||
f'fill="{fill}"{stroke}{dash}/>')
|
||||
elif kind == "text":
|
||||
x, y, s, size, color, bold, anchor, vertical = a
|
||||
weight = ' font-weight="bold"' if bold else ""
|
||||
if vertical:
|
||||
ta = ' text-anchor="middle" dominant-baseline="middle"'
|
||||
transform = f' transform="rotate(-90 {x} {y})"'
|
||||
else:
|
||||
ta = (' text-anchor="middle" dominant-baseline="hanging"' if anchor == "mt"
|
||||
else ' dominant-baseline="hanging"')
|
||||
transform = ""
|
||||
out.append(f'<text x="{x}" y="{y}" font-size="{size}" fill="{color}"'
|
||||
f'{weight}{ta}{transform}>{esc(s)}</text>')
|
||||
elif kind == "path":
|
||||
pts, color, lw, dash = a
|
||||
d = " ".join(("M" if i == 0 else "L") + f"{p[0]} {p[1]}"
|
||||
for i, p in enumerate(pts))
|
||||
dash = ' stroke-dasharray="9 6"' if dash else ""
|
||||
out.append(f'<path d="{d}" fill="none" stroke="{color}" '
|
||||
f'stroke-width="{lw}"{dash} stroke-linejoin="round"/>')
|
||||
(tx, ty), (px, py) = pts[-1], pts[-2]
|
||||
dx, dy = tx - px, ty - py
|
||||
n = (dx * dx + dy * dy) ** 0.5 or 1
|
||||
ux, uy = dx / n, dy / n
|
||||
s_ = 9
|
||||
bx, by = tx - ux * s_, ty - uy * s_
|
||||
ox, oy = -uy * s_ * 0.42, ux * s_ * 0.42
|
||||
out.append(f'<polygon points="{tx},{ty} {bx + ox},{by + oy} '
|
||||
f'{bx - ox},{by - oy}" fill="{color}"/>')
|
||||
elif kind == "dot":
|
||||
x, y, r, color = a
|
||||
out.append(f'<circle cx="{x}" cy="{y}" r="{r}" fill="{color}"/>')
|
||||
|
||||
out.append("</svg>")
|
||||
with open(path, "w", encoding="utf-8") as fh:
|
||||
fh.write("\n".join(out))
|
||||
return path
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
base = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "docs")
|
||||
base = os.path.normpath(base)
|
||||
ops = build()
|
||||
print(render_png(ops, os.path.join(base, "infra_services_diagram.png")))
|
||||
print(render_svg(ops, os.path.join(base, "infra_services_diagram.svg")))
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 258 KiB |
@@ -0,0 +1,142 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="720" viewBox="0 0 1600 720" font-family="DejaVu Sans, Verdana, sans-serif">
|
||||
<rect width="1600" height="720" fill="#FFFFFF"/>
|
||||
<rect x="16" y="8" width="270" height="552" rx="12" fill="#E8F3FB"/>
|
||||
<rect x="16" y="14" width="270" height="44" rx="8" fill="#1565C0"/>
|
||||
<text x="151.0" y="25" font-size="15" fill="#FFFFFF" font-weight="bold" text-anchor="middle" dominant-baseline="hanging">Шаг 1. Тенант</text>
|
||||
<text x="151.0" y="68" font-size="12" fill="#7A8794" text-anchor="middle" dominant-baseline="hanging">базовый уровень изоляции</text>
|
||||
<rect x="340" y="8" width="270" height="552" rx="12" fill="#FDF1E3"/>
|
||||
<rect x="340" y="14" width="270" height="44" rx="8" fill="#E65100"/>
|
||||
<text x="475.0" y="25" font-size="15" fill="#FFFFFF" font-weight="bold" text-anchor="middle" dominant-baseline="hanging">Шаг 2. Пул ресурсов</text>
|
||||
<text x="475.0" y="68" font-size="12" fill="#7A8794" text-anchor="middle" dominant-baseline="hanging">CPU / RAM / Storage</text>
|
||||
<rect x="664" y="8" width="270" height="552" rx="12" fill="#EEEAF8"/>
|
||||
<rect x="664" y="14" width="270" height="44" rx="8" fill="#4527A0"/>
|
||||
<text x="799.0" y="25" font-size="15" fill="#FFFFFF" font-weight="bold" text-anchor="middle" dominant-baseline="hanging">Шаг 3. Сетевой периметр</text>
|
||||
<text x="799.0" y="68" font-size="12" fill="#7A8794" text-anchor="middle" dominant-baseline="hanging">маршрутизация и балансировка</text>
|
||||
<rect x="988" y="8" width="270" height="552" rx="12" fill="#FDF4E3"/>
|
||||
<rect x="988" y="14" width="270" height="44" rx="8" fill="#EF6C00"/>
|
||||
<text x="1123.0" y="25" font-size="15" fill="#FFFFFF" font-weight="bold" text-anchor="middle" dominant-baseline="hanging">Шаг 4. Среда запуска</text>
|
||||
<text x="1123.0" y="68" font-size="12" fill="#7A8794" text-anchor="middle" dominant-baseline="hanging">контейнер и внешние адреса</text>
|
||||
<rect x="1312" y="8" width="270" height="552" rx="12" fill="#E9F5EA"/>
|
||||
<rect x="1312" y="14" width="270" height="44" rx="8" fill="#2E7D32"/>
|
||||
<text x="1447.0" y="25" font-size="15" fill="#FFFFFF" font-weight="bold" text-anchor="middle" dominant-baseline="hanging">Шаг 5. Потребители</text>
|
||||
<text x="1447.0" y="68" font-size="12" fill="#7A8794" text-anchor="middle" dominant-baseline="hanging">что разворачивается в итоге</text>
|
||||
<rect x="31" y="150" width="240" height="150" rx="10" fill="#FFFFFF" stroke="#0288D1" stroke-width="2"/>
|
||||
<rect x="43" y="162" width="22" height="22" rx="5" fill="#0288D1"/>
|
||||
<text x="73" y="162" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Организация</text>
|
||||
<text x="73" y="182" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">в Cloud Director</text>
|
||||
<text x="73" y="202" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 19 · vcOrg</text>
|
||||
<circle cx="51" cy="231" r="2.4" fill="#0288D1"/>
|
||||
<text x="61" y="224" font-size="10" fill="#2E3A45" dominant-baseline="hanging">Типы: iaas / saas</text>
|
||||
<rect x="355" y="130" width="240" height="230" rx="10" fill="#FFF3E0" stroke="#F57C00" stroke-width="2"/>
|
||||
<rect x="367" y="142" width="22" height="22" rx="5" fill="#F57C00"/>
|
||||
<text x="397" y="142" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Виртуальный</text>
|
||||
<text x="397" y="162" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">датацентр (vDC)</text>
|
||||
<text x="397" y="182" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 21 · vcVdc</text>
|
||||
<circle cx="375" cy="211" r="2.4" fill="#F57C00"/>
|
||||
<text x="385" y="204" font-size="10" fill="#2E3A45" dominant-baseline="hanging">cpuGuaranteed: 0% / 50% / 80%</text>
|
||||
<circle cx="375" cy="231" r="2.4" fill="#F57C00"/>
|
||||
<text x="385" y="224" font-size="10" fill="#2E3A45" dominant-baseline="hanging">cpuAllocated, memAllocated</text>
|
||||
<circle cx="375" cy="251" r="2.4" fill="#F57C00"/>
|
||||
<text x="385" y="244" font-size="10" fill="#2E3A45" dominant-baseline="hanging">storageConfig</text>
|
||||
<rect x="367" y="318" width="216" height="30" rx="6" fill="#FFFFFF" stroke="#F57C00" stroke-width="1"/>
|
||||
<text x="475.0" y="328" font-size="10" fill="#F57C00" text-anchor="middle" dominant-baseline="hanging">здесь выделяются CPU / RAM / Диск</text>
|
||||
<rect x="679" y="120" width="240" height="200" rx="10" fill="#EDE7F6" stroke="#5E35B1" stroke-width="2"/>
|
||||
<rect x="691" y="132" width="22" height="22" rx="5" fill="#5E35B1"/>
|
||||
<text x="721" y="132" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Сетевой шлюз</text>
|
||||
<text x="721" y="152" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">периметра (Edge)</text>
|
||||
<text x="721" y="172" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 22 · vcNsxt</text>
|
||||
<circle cx="699" cy="201" r="2.4" fill="#5E35B1"/>
|
||||
<text x="709" y="194" font-size="10" fill="#2E3A45" dominant-baseline="hanging">AVI Load Balancer</text>
|
||||
<circle cx="699" cy="221" r="2.4" fill="#5E35B1"/>
|
||||
<text x="709" y="214" font-size="10" fill="#2E3A45" dominant-baseline="hanging">routed-сеть 10.10.102.0/24</text>
|
||||
<rect x="691" y="278" width="216" height="30" rx="6" fill="#FFFFFF" stroke="#5E35B1" stroke-width="1"/>
|
||||
<text x="799.0" y="288" font-size="10" fill="#5E35B1" text-anchor="middle" dominant-baseline="hanging">SNAT настраивается операцией modify</text>
|
||||
<rect x="1003" y="100" width="240" height="110" rx="10" fill="#FFF3E0" stroke="#F57C00" stroke-width="2"/>
|
||||
<rect x="1015" y="112" width="22" height="22" rx="5" fill="#F57C00"/>
|
||||
<text x="1045" y="112" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Каталог ВМ (vApp)</text>
|
||||
<text x="1045" y="132" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 26 · vapp</text>
|
||||
<circle cx="1023" cy="161" r="2.4" fill="#F57C00"/>
|
||||
<text x="1033" y="154" font-size="10" fill="#2E3A45" dominant-baseline="hanging">логический контейнер для ВМ</text>
|
||||
<rect x="1003" y="245" width="180" height="150" rx="10" fill="#FAFAFA" stroke="#9E9E9E" stroke-width="2" stroke-dasharray="9 6"/>
|
||||
<rect x="1015" y="257" width="22" height="22" rx="5" fill="#9E9E9E"/>
|
||||
<text x="1045" y="257" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Внешние IP</text>
|
||||
<text x="1045" y="277" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 25</text>
|
||||
<circle cx="1023" cy="306" r="2.4" fill="#9E9E9E"/>
|
||||
<text x="1033" y="299" font-size="10" fill="#2E3A45" dominant-baseline="hanging">выделение: vcOrg</text>
|
||||
<circle cx="1023" cy="326" r="2.4" fill="#9E9E9E"/>
|
||||
<text x="1033" y="319" font-size="10" fill="#2E3A45" dominant-baseline="hanging">NAT: сервис 25</text>
|
||||
<circle cx="1023" cy="346" r="2.4" fill="#9E9E9E"/>
|
||||
<text x="1033" y="339" font-size="10" fill="#2E3A45" dominant-baseline="hanging">квота IP (ipSpace)</text>
|
||||
<rect x="1015" y="353" width="156" height="30" rx="6" fill="#FFFFFF" stroke="#9E9E9E" stroke-width="1"/>
|
||||
<text x="1093.0" y="363" font-size="10" fill="#9E9E9E" text-anchor="middle" dominant-baseline="hanging">здесь выделяются IP</text>
|
||||
<rect x="1327" y="100" width="240" height="120" rx="10" fill="#E8F5E9" stroke="#2E7D32" stroke-width="2"/>
|
||||
<rect x="1339" y="112" width="22" height="22" rx="5" fill="#2E7D32"/>
|
||||
<text x="1369" y="112" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Виртуальная машина</text>
|
||||
<text x="1369" y="132" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 28 · vc_vm_v3</text>
|
||||
<circle cx="1347" cy="161" r="2.4" fill="#2E7D32"/>
|
||||
<text x="1357" y="154" font-size="10" fill="#2E3A45" dominant-baseline="hanging">vmCpu · vmRam · vmDisk</text>
|
||||
<rect x="1327" y="255" width="240" height="170" rx="10" fill="#E8F5E9" stroke="#2E7D32" stroke-width="2"/>
|
||||
<rect x="1339" y="267" width="22" height="22" rx="5" fill="#2E7D32"/>
|
||||
<text x="1369" y="267" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Kubernetes кластер</text>
|
||||
<text x="1369" y="287" font-size="15" fill="#1A1A1A" font-weight="bold" dominant-baseline="hanging">Штурвал</text>
|
||||
<text x="1369" y="307" font-size="11" fill="#5F6B76" dominant-baseline="hanging">Сервис 150</text>
|
||||
<circle cx="1347" cy="336" r="2.4" fill="#2E7D32"/>
|
||||
<text x="1357" y="329" font-size="10" fill="#2E3A45" dominant-baseline="hanging">sizingPolicy · sizingDisk</text>
|
||||
<circle cx="1347" cy="356" r="2.4" fill="#2E7D32"/>
|
||||
<text x="1357" y="349" font-size="10" fill="#2E3A45" dominant-baseline="hanging">· count</text>
|
||||
<rect x="1339" y="383" width="216" height="30" rx="6" fill="#FFFFFF" stroke="#2E7D32" stroke-width="1"/>
|
||||
<text x="1447.0" y="393" font-size="10" fill="#2E7D32" text-anchor="middle" dominant-baseline="hanging">требует ALB + VS ≥ 3</text>
|
||||
<path d="M271 225 L355 225" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="355,225 346.0,228.78 346.0,221.22" fill="#455A64"/>
|
||||
<text x="313" y="262" font-size="10" fill="#455A64" text-anchor="middle" dominant-baseline="middle" transform="rotate(-90 313 262)">organizationUid</text>
|
||||
<path d="M595 200 L679 200" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="679,200 670.0,203.78 670.0,196.22" fill="#455A64"/>
|
||||
<text x="637" y="186" font-size="10" fill="#455A64" dominant-baseline="hanging">vdcUid</text>
|
||||
<path d="M500 130 L500 92 L961 92 L961 140 L1003 140" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="1003,140 994.0,143.78 994.0,136.22" fill="#455A64"/>
|
||||
<text x="706" y="96" font-size="10" fill="#455A64" dominant-baseline="hanging">vdcUid</text>
|
||||
<path d="M919 180 L1003 180" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="1003,180 994.0,183.78 994.0,176.22" fill="#455A64"/>
|
||||
<text x="961" y="166" font-size="10" fill="#455A64" dominant-baseline="hanging">nsxtUid</text>
|
||||
<path d="M1243 140 L1327 140" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="1327,140 1318.0,143.78 1318.0,136.22" fill="#455A64"/>
|
||||
<text x="1285" y="126" font-size="10" fill="#455A64" dominant-baseline="hanging">vappUid</text>
|
||||
<path d="M500 360 L500 470 L1447 470 L1447 425" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="1447,425 1450.78,434.0 1443.22,434.0" fill="#455A64"/>
|
||||
<text x="1180" y="456" font-size="10" fill="#455A64" dominant-baseline="hanging">vdcUid</text>
|
||||
<path d="M799 320 L799 505 L1467 505 L1467 425" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="1467,425 1470.78,434.0 1463.22,434.0" fill="#455A64"/>
|
||||
<text x="1180" y="491" font-size="10" fill="#455A64" dominant-baseline="hanging">nsxtUid</text>
|
||||
<path d="M151 300 L151 540 L1050 540 L1050 395" fill="none" stroke="#7A8794" stroke-width="2" stroke-dasharray="9 6" stroke-linejoin="round"/>
|
||||
<polygon points="1050,395 1053.78,404.0 1046.22,404.0" fill="#7A8794"/>
|
||||
<text x="161" y="526" font-size="10" fill="#7A8794" dominant-baseline="hanging">modify: vIPConfigure</text>
|
||||
<path d="M870 320 L870 400 L1140 400 L1140 395" fill="none" stroke="#7A8794" stroke-width="2" stroke-dasharray="9 6" stroke-linejoin="round"/>
|
||||
<polygon points="1140,395 1143.78,404.0 1136.22,404.0" fill="#7A8794"/>
|
||||
<text x="880" y="386" font-size="10" fill="#7A8794" dominant-baseline="hanging">modify: SNAT</text>
|
||||
<path d="M1183 270 L1255 270 L1255 160 L1327 160" fill="none" stroke="#7A8794" stroke-width="2" stroke-dasharray="9 6" stroke-linejoin="round"/>
|
||||
<polygon points="1327,160 1318.0,163.78 1318.0,156.22" fill="#7A8794"/>
|
||||
<text x="1187" y="222" font-size="10" fill="#7A8794" dominant-baseline="hanging">внешний IP</text>
|
||||
<path d="M1183 350 L1327 350" fill="none" stroke="#C62828" stroke-width="2" stroke-dasharray="9 6" stroke-linejoin="round"/>
|
||||
<polygon points="1327,350 1318.0,353.78 1318.0,346.22" fill="#C62828"/>
|
||||
<text x="1187" y="330" font-size="10" fill="#C62828" dominant-baseline="hanging">≥ 3 адреса</text>
|
||||
<text x="24" y="590" font-size="14" fill="#2E3A45" dominant-baseline="hanging">> Порядок создания: Организация → vDC → Edge → (vApp + внешние IP) → ВМ / Штурвал.</text>
|
||||
<text x="24" y="616" font-size="14" fill="#2E3A45" dominant-baseline="hanging">> SNAT — не отдельный сервис, а операция modify у Edge.</text>
|
||||
<text x="24" y="642" font-size="14" fill="#2E3A45" dominant-baseline="hanging">> vDC и Edge могут быть переиспользованы существующие.</text>
|
||||
<path d="M980 606 L1040 606" fill="none" stroke="#455A64" stroke-width="2" stroke-linejoin="round"/>
|
||||
<polygon points="1040,606 1031.0,609.78 1031.0,602.22" fill="#455A64"/>
|
||||
<text x="1052" y="597" font-size="11" fill="#2E3A45" dominant-baseline="hanging">Сплошная линия — обязательная зависимость</text>
|
||||
<text x="1052" y="613" font-size="10" fill="#7A8794" dominant-baseline="hanging">(ссылка на UUID существующего инстанса)</text>
|
||||
<path d="M980 650 L1040 650" fill="none" stroke="#7A8794" stroke-width="2" stroke-dasharray="9 6" stroke-linejoin="round"/>
|
||||
<polygon points="1040,650 1031.0,653.78 1031.0,646.22" fill="#7A8794"/>
|
||||
<text x="1052" y="641" font-size="11" fill="#2E3A45" dominant-baseline="hanging">Пунктир — выделение ресурса / операция modify</text>
|
||||
<rect x="980" y="684" width="12" height="12" rx="3" fill="#1565C0"/>
|
||||
<text x="996" y="682" font-size="10" fill="#2E3A45" dominant-baseline="hanging">Тенант</text>
|
||||
<rect x="1038" y="684" width="12" height="12" rx="3" fill="#F57C00"/>
|
||||
<text x="1054" y="682" font-size="10" fill="#2E3A45" dominant-baseline="hanging">Ресурсы</text>
|
||||
<rect x="1102" y="684" width="12" height="12" rx="3" fill="#5E35B1"/>
|
||||
<text x="1118" y="682" font-size="10" fill="#2E3A45" dominant-baseline="hanging">Сеть</text>
|
||||
<rect x="1147" y="684" width="12" height="12" rx="3" fill="#2E7D32"/>
|
||||
<text x="1163" y="682" font-size="10" fill="#2E3A45" dominant-baseline="hanging">Потребители</text>
|
||||
<rect x="1237" y="684" width="12" height="12" rx="3" fill="#9E9E9E"/>
|
||||
<text x="1253" y="682" font-size="10" fill="#2E3A45" dominant-baseline="hanging">Адреса</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
Reference in New Issue
Block a user