پالت فرمان

دنبال فرمانی برای اجرا بگردید…

ZarynZaryn
مخزن‌های طراحی شبکه·۲۶ دقیقه مطالعه·

مخزن طراحی شبکه

طراحی شبکه به‌صورت متن در یک مخزن، که مثل کد بازبینی و با آنچه دستگاه‌ها واقعاً می‌گویند مقایسه می‌شود.

## این چیست **مخزن طراحی شبکه** منبع حقیقت شبکه است و چیزی را نگه می‌دارد که شبکه قرار است باشد: سایت‌هایش، دستگاه‌های هر سایت، پورت‌هایشان، لینک‌های میانشان، مدارهایی که از سرویس‌دهنده خریده‌اید و داکت‌هایی که این مدارها از آن می‌گذرند. همه متن ساده است (فایل‌های `.zevtopo`) و مثل کد نسخه‌بندی می‌شود: هر تغییر یک کامیت با نویسنده و دلیل است و پیش از پذیرفته‌شدن در یک درخواست ادغام بازبینی می‌شود. Zaryn چیزی اضافه می‌کند که از دیاگرام یا صفحه‌گسترده برنمی‌آید: طراحی **با واقعیت سنجیده می‌شود**. وقتی به یک [سایت](/docs/fa/network-sites) پیوند داده شود، با آنچه دستگاه‌های سایت دربارهٔ خودشان گزارش می‌کنند (همسایه‌ها، آدرس‌ها و پورت‌هایشان) مقایسه می‌شود، تا مستندات بی‌صدا از شبکه دور نشوند. ## مشکلی که حل می‌کند هر شبکه‌ای جایی طراحی‌ای دارد: یک فایل Visio، یک صفحهٔ ویکی، یک جدول کابل‌ها. چند ماه بعد دیگر درست نیست. دستگاهی با عجله اضافه شد، لینکی به پورت دیگری رفت، اتصالی «موقت» دائمی شد. کسی متوجه نمی‌شود تا روز قطعی، وقتی دیاگرامی که همه به آن اعتماد دارند مهندس را به رک اشتباه می‌فرستد. نیمهٔ دیگر مشکل ریسک پنهان است. دو لینک ممکن است روی دیاگرام افزونه به نظر برسند و باز هم با هم قطع شوند، چون از یک داکت فیبر، از زیر یک پل یا از ستون فقرات یک سرویس‌دهنده می‌گذرند. دیاگرام این را نمی‌داند؛ طراحی‌ای که آن را نام ببرد، می‌داند. Zaryn سه نگاه به شبکه را یک چرخه می‌بیند: | | چیست | کجا | |---|---|---| | **طراحی** | شبکه چه باید باشد | همین مخزن | | **واقعیت** | دستگاه‌ها می‌گویند چیست | [سایت‌ها](/docs/fa/network-sites) | | **پیش‌بینی** | یک تغییر چه می‌کند | [دوقلوی دیجیتال](/docs/fa/network-twin) | ```diagram type: flow title: سه نگاه به یک شبکه، هماهنگ با هم loop: هر تغییر ادغام‌شده طراحی را به‌روز می‌کند، هر گزارش دستگاه آن را می‌سنجد --- طراحی | شبکه باید چطور باشد: سایت‌ها، دستگاه‌ها، پیوندها، مدارها | accent | 📐 ~ مقایسه با واقعیت | دستگاه‌ها چه می‌گویند: همسایه‌ها، آدرس‌ها، پورت‌ها | good | 📡 ~ پیش‌بینی پیش‌بینی | یک تغییر چه می‌کند، پیش از آنکه کسی آن را اعمال کند | warn | 🔮 ``` ## واردکردن یک سایت در حال کار لازم نیست طراحی را از صفر بنویسید. اگر شبکه همین حالا یک سایت در Zaryn است، واردش کنید: ```bash zev clone <you>/network-design && cd network-design zev topo import <owner>/<site> zev add topology && zev commit -m "Design from the live network" && zev push ``` `zev topo import` فایل `topology/<site>.zevtopo` را می‌نویسد، با همهٔ دستگاه‌های سایت (نام، سازنده، مدل، آدرس مدیریت) و همهٔ لینک‌هایی که دستگاه‌ها می‌بینند (با پورت هر دو سر). در زبانهٔ **نقشه** سایت، **دریافت سایت به‌صورت .zevtopo** همین فایل را می‌دهد. بعد آن را طراحی کنید: نقش دستگاه‌ها را بدهید، مدارها را نام ببرید، و مشخص کنید کدام لینک‌ها چه چیزی مشترک دارند. ## قالب .zevtopo `.zevtopo` شبیه TOML است: بلوک‌هایی که با `[[kind]]` شروع می‌شوند و بعد خط‌های `key = value`. `#` توضیح را شروع می‌کند. ```toml [[site]] name = "thr-dc1" address = "Frankfurt, data center 1" lat = 35.70 lon = 51.40 [[device]] name = "core1" vendor = "cisco" role = "core" site = "thr-dc1" model = "C9500-48Y4C" mgmt = "10.0.0.1" owner = "sara" [[interface]] device = "core1" name = "Te1/0/1" lag = "Po1" ip = "10.1.12.1/30" description = "to core2" [[link]] a = "core1" b = "core2" a_if = "Te1/0/1" b_if = "Te1/0/1" kind = "fiber" capacity = 10 weight = 10 provider = "TIC" circuit = "TIC-4411" srlg = ["duct-north", "valiasr-bridge"] [[vlan]] id = 10 name = "users" subnet = "10.10.0.0/24" [[static_route]] device = "core1" network = "0.0.0.0/0" next_hop = "10.255.0.1" ``` | بلوک | کلیدها | |---|---| | `[[site]]` | `name`، `address`، `lat`، `lon` | | `[[device]]` | `name`، `vendor`، `role` (core، distribution، access، edge…)، `site`، `model`، `mgmt` (آدرس مدیریت)، `owner`، `lat`، `lon`، `mtbf` و `mttr` (به ساعت، ببینید [دسترس‌پذیری](#دسترسپذیری-ظرفیت-و-مسیرهای-جدا)) | | `[[interface]]` | `device`، `name`، `ip`، `description`، `lag` (پورت‌چنلی که عضوش است)، `vlan` | | `[[link]]` | `a`، `b`، `a_if`، `b_if` (پورت‌ها)، `kind` (fiber، copper، wireless، vpn، virtual)، `capacity`، `weight`، `provider`، `circuit`، `srlg` (گروه‌های ریسک مشترک: یک فهرست)، `mtbf`، `mttr` | | `[[srlg]]` | `name`، `mtbf`، `mttr`: خرابی‌های خودِ یک گروه ریسک مشترک (بریده شدن کانال، قطع برق یک ساختمان) | | `[[vlan]]` | `id`، `name`، `subnet`، `description` | | `[[static_route]]` | `device`، `network`، `next_hop`، `distance` | جز `name` دستگاه و `a` و `b` لینک، همهٔ کلیدها اختیاری‌اند. فایل‌هایی که پیش از این کلیدها نوشته شده‌اند دقیقاً مثل قبل خوانده می‌شوند. ### یک طراحی، چند فایل هر فایل `.zevtopo` در ریشهٔ مخزن یا هر جای پوشهٔ `topology/` بخشی از طراحی است و همه به ترتیب نام، با هم خوانده می‌شوند. هر طور که تیمتان کار می‌کند تقسیمش کنید: یک فایل برای هر سایت (`topology/thr-dc1.zevtopo`، `topology/mhd-pop.zevtopo`)، یا یکی برای دستگاه‌ها و یکی برای مدارها. یک لینک می‌تواند دستگاه‌های دو فایل را به هم وصل کند. ## ویرایش: کد و بوم زبانهٔ **ویرایشگر طراحی** در مخزن، طراحی را دو بار کنار هم نشان می‌دهد: فایل‌های `.zevtopo` در یک ویرایشگر کد، و شبکه کشیده‌شده روی یک بوم. هر دو یک طراحی‌اند و زنده: - **در فایل بنویسید** تا بوم همزمان دوباره کشیده شود. دستگاه‌هایی که جا گرفته‌اند سر جایشان می‌مانند؛ دستگاه‌های تازه کنار چیزی که به آن وصل‌اند جا پیدا می‌کنند. - **بوم را تغییر دهید** تا همان جای فایل ویرایش شود: فقط خط‌های همان دستگاه یا پیوند عوض می‌شوند، پس توضیح‌ها، ترتیب و فاصله‌هایی که نوشته‌اید می‌مانند. - **مکان‌نما را درون یک بلوک بگذارید** تا آن دستگاه یا پیوند روی بوم انتخاب شود؛ **چیزی را روی بوم انتخاب کنید** تا خط‌هایش در فایل علامت بخورند (و اگر در فایل دیگری است، آن فایل باز شود). روی بوم: | کار | چطور | |---|---| | افزودن دستگاه | **+ دستگاه**، یا `n` | | پیوند دادن دو دستگاه | یکی را انتخاب کنید و با Shift روی دیگری کلیک کنید؛ یا `l` و بعد کلیک روی سر دیگر | | ویرایش جزئیات | بخش جزئیات زیر بوم: سازنده، نقش، سایت، مدل و نشانی مدیریت برای دستگاه؛ پورت‌ها، وزن، ظرفیت، نوع، ارائه‌دهنده، مدار و گروه‌های ریسک مشترک برای پیوند | | تغییر نام دستگاه | نامش در بخش جزئیات؛ هر پیوند، interface و مسیر ایستایی که نامش را دارد، در همهٔ فایل‌ها، همراهش تغییر نام می‌دهد | | حذف | `Delete`؛ دستگاه همراه پیوندها، interfaceها و مسیرهای ایستایی که نامش را دارند حذف می‌شود | | چیدن | دستگاه‌ها را بکشید (فقط تصویر جابه‌جا می‌شود؛ جای دستگاه‌ها در طراحی ذخیره نمی‌شود) | نقطه‌های شکست تکی و پیوندهای حیاتی با هر تغییر دوباره حساب می‌شوند، پس پیوندی که اضافه می‌کنید همان لحظه نشان می‌دهد یکی از آن‌ها را برداشته یا نه. زیر ویرایشگر اشکال‌ها با شمارهٔ خطشان فهرست می‌شوند: خطی که `key = value` نیست، مقدار متنی بدون گیومهٔ بسته، دستگاهی که دو بار تعریف شده، پیوند به دستگاهی که بلوک `[[device]]` ندارد، وزنی که عدد نیست. روی هر کدام کلیک کنید تا به آن خط بروید. **ذخیره.** **ذخیره** (یا `Ctrl S`) فایل‌های تغییرکرده را از مرورگر commit می‌کند، با کلید مرورگرتان امضا شده مثل هر commit وب. پیش‌فرض **پیشنهاد به صورت pull request** است: یک شاخهٔ تازه و بعد صفحهٔ pull request، که بررسی‌های شبکه و [نیت‌ها](#نیتها-intent) پیش از رسیدن هر چیزی به شاخه آنجا اجرا می‌شوند. **commit مستقیم** برای مخزن‌هایی است که بازبینی لازم ندارند. اگر کسی بعد از باز کردن شما در شاخه ذخیره کرده باشد، چیزی بازنویسی نمی‌شود: کارتان پیش‌نویس می‌ماند، صفحه را دوباره بارگذاری می‌کنید و آن را بازمی‌گردانید. کار ذخیره‌نشده به صورت پیش‌نویس در همین مرورگر نگه داشته می‌شود و دفعهٔ بعد که ویرایشگر را باز کنید پیشنهاد می‌شود. **+** بالای ویرایشگر فایلی زیر `topology/` اضافه می‌کند (ببینید [یک طراحی، چند فایل](#یک-طراحی-چند-فایل))؛ دستگاه‌ها و پیوندهای تازه به فایلی می‌روند که باز است. ```diagram type: flow title: از یک ویرایش تا یک تغییر گواهی‌شده or: یا loop: تغییر بعدی از همین طراحی شروع می‌شود --- ویرایش | در فایل یا روی بوم، هر دو هماهنگ می‌مانند | accent | ✎ ~ commit pull request | یک شاخه با خط‌های تغییرکردهٔ ‎.zevtopo | | ⎇ ~ در هر تغییر بررسی‌ها | گراف، بعد هر نیت | warn | ✓ ~ اگر برقرار بمانند ادغام | طراحی روی شاخهٔ مقصد عوض می‌شود | good | ⇄ ? مسدود | نیتی که برقرار بود دیگر نیست: pull request خرابی را نام می‌برد | bad | ✕ ~ پریمیوم گواهی | امضاشده، پیوندخورده به گواهی قبلی | accent | ✍ ``` ## نماها **نمای کلی شبکه** در مخزن، طراحی را به چهار شکل می‌کشد: - **منطقی**: دستگاه‌ها و لینک‌ها، با نقاط شکست تکی و لینک‌های حیاتی (نقاط مفصلی و پل‌ها با الگوریتم تارجان). - **سایت‌ها**: دستگاه‌ها گروه‌بندی‌شده بر اساس سایت، تا لینک‌های میان سایت‌ها (WAN شما) دیده شوند. - **ریسک مشترک**: لینک‌ها به رنگ گروه ریسک مشترکشان، و فهرستی از لینک‌هایی که با هم قطع می‌شوند. دو لینک «افزونه» با یک رنگ، با یک خرابی هر دو از دست می‌روند. - **طراحی و واقعیت**: طراحی روی آنچه سایت پیوندشده گزارش می‌کند (پایین‌تر). روی یک دستگاه کلیک کنید تا مدل، سایت، آدرس مدیریت، پورت‌ها و مدارهای لینک‌هایش را ببینید. ## طراحی و واقعیت در یک سایت، **جمع‌آوری‌کننده و تنظیمات** ← **مخزن طراحی** طراحی را پیوند می‌دهد (باید مدیر سایت و مدیر مخزن باشید). از آن پس Zaryn آن‌ها را مقایسه می‌کند، هم در نمای کلی شبکهٔ مخزن (**طراحی و واقعیت**) و هم در زبانهٔ نقشهٔ سایت: - **طراحی‌شده، روی شبکه نیست** (قرمز خط‌چین): دستگاهی که هیچ جمع‌آوری‌کننده‌ای به آن نمی‌رسد، لینکی که هیچ دستگاهی نمی‌بیند. هنوز ساخته نشده، یا خراب است. - **روی شبکه هست، در طراحی نیست** (کهربایی نقطه‌چین): دستگاه یا لینکی که طراحی ندارد. بدون به‌روزکردن طراحی اضافه شده، یا نباید آنجا باشد. - **ناهمخوانی‌ها**: همان دستگاه با سازنده، آدرس مدیریت یا نام دیگر؛ همان لینک روی پورت‌هایی غیر از طراحی. دستگاه‌ها بر اساس نام (بدون توجه به حروف بزرگ و دامنه: `CORE1.lab` همان `core1` است) یا آدرس مدیریت جفت می‌شوند؛ لینک‌ها بر اساس دو دستگاه و بعد پورت‌ها. واقعیت از آخرین گفته‌های دستگاه‌ها می‌آید (CDP، LLDP، همسایه‌های MikroTik، همتاهای OSPF و BGP، زیرشبکه‌های مشترک)، پس لینکی که هر دو سرش دربارهٔ آن ساکت‌اند دیده نمی‌شود. دیدن مقایسه هر دو را می‌خواهد: خواندن مخزن و دیدن سایت. هم‌تیمی‌ای که فقط سایت را می‌بیند، می‌بیند که طراحی‌ای پیوند شده، نه اینکه در آن چیست. ## نیت‌ها (intent) یک نمودار می‌تواند افزونه به‌نظر برسد و نباشد. **نیت** تعهدی دربارهٔ طراحی است که در یک خط متن نوشته می‌شود، مثل «اگر هر کانال (duct) بریده شود، HQ به دیتاسنتر وصل می‌ماند». Zaryn هر نیت را روی طراحی می‌سنجد، خرابی‌هایی را که آن را می‌شکنند نشان می‌دهد، و ادغام pull requestی را که نیتی برقرار را بشکند رد می‌کند. نیت‌ها در فایل‌های `.zevintent` کنار طراحی هستند: در ریشهٔ مخزن یا زیر `topology/`، به ترتیب نام و به‌عنوان یک متن خوانده می‌شوند. ```text # topology/wan.zevintent links = survive site:hq site:dc link ducts = survive site:hq site:dc srlg hq-to-dc = max-hops hq1 dc2 3 no-spof ``` | خط | وقتی برقرار است که | |---|---| | `reach A B` | A و B به هم وصل‌اند | | `survive A B [link\|srlg\|device\|any]` | A و B پس از هر خرابیِ تکی از آن نوع هنوز وصل‌اند (پیش‌فرض `any`) | | `max-hops A B N` | کوتاه‌ترین مسیر میانشان حداکثر N لینک باشد | | `no-spof` | خرابی هیچ دستگاهِ تنهایی شبکه را دو تکه نکند | | `no-bridge` | خرابی هیچ لینکِ تنهایی شبکه را دو تکه نکند | | `no-shared-risk` | خرابی هیچ گروه ریسک مشترکِ تنهایی (کانال، ساختمان، ارائه‌دهنده) شبکه را دو تکه نکند | | `availability A B P` | A دست‌کم P درصد زمان به B برسد (پریمیوم، [پایین‌تر](#دسترسپذیری-ظرفیت-و-مسیرهای-جدا)) | | `capacity A B N [link\|srlg\|device\|any\|none]` | A دست‌کم N به B بفرستد، حتی بعد از هر خرابی تکی از آن نوع (پریمیوم) | | `disjoint A B [link\|device]` | دو مسیر باشد که هیچ پیوند مشترکی، یا هیچ دستگاه میانی مشترکی، نداشته باشند (پریمیوم) | A و B نام یک دستگاه‌اند، یا `site:NAME` برای هر دستگاهِ آن سایت. نامِ پیش از ` = ` اختیاری است؛ بدون آن، خودِ خط نامش است. `#` توضیح را شروع می‌کند. ### یک نیتِ شکسته چه نشان می‌دهد نه «شکست خورد»، بلکه خرابی‌ای که آن را می‌شکند: ```text ducts: 1 single failure(s) cut site:hq off from site:dc shared risk group duct-north (2 links) → site:hq and site:dc are cut apart ``` دو مدار که افزونه به‌نظر می‌رسند ولی هر دو `srlg` یکسان دارند، با یک بریدگی هر دو از کار می‌افتند. خرابی یک لینک این را نشان نمی‌داد؛ برای همین `survive … srlg` هست. در API هر جمله هم به صورت یک الگو با `{0}`، `{1}`… و مقدارهایش می‌آید (`parts` روی یک نتیجه، `effect_t` و `effect_a` روی یک خرابی)، تا کلاینت بتواند آن را به زبان دیگری بگوید؛ همین صفحه این کار را برای فارسی می‌کند. ```diagram type: graph title: روی نقشه افزونه، در عمل یک بریدگی alt: دو سایت با دو مدار به هم وصل‌اند که هر دو از یک کانال می‌گذرند؛ با بریدن کانال هر دو مدار قطع و سایت‌ها از هم جدا می‌شوند legend: down=مدار بریده start: دو مدار caption: دو مدار، دو پورت، دو برچسب ارائه‌دهنده. نقشه می‌گوید افزونه است. --- box دفتر مرکزی | 3 8 38 40 | accent box مرکز داده | 59 8 38 40 | good node hq1 | hq1 | 14 22 | router | | روتر هستهٔ دفتر مرکزی، سر مدار TIC-1 node hq2 | hq2 | 14 40 | router | | روتر هستهٔ دوم، سر مدار TIC-2 node dc1 | dc1 | 86 22 | router | | روتر مرکز داده node dc2 | dc2 | 86 40 | router | | روتر مرکز داده link hq1 hq2 link dc1 dc2 link hq1 dc1 | TIC-1 | | duct-north link hq2 dc2 | TIC-2 | | duct-north step طراحی کانال را نام می‌برد | هر دو مدار `srlg = ["duct-north"]` دارند: طراحی چیزی را می‌داند که نقشه نمی‌داند. note 50 53 | هر دو مدار: duct-north | warn step یک بریدگی در کانال شمالی | یک بیل مکانیکی، یک بریدگی، دو مدار قطع: سایت‌ها از هم جدا می‌شوند. `survive site:hq site:dc srlg` این را پیش از وقوع پیدا می‌کند. link hq1 dc1 | down link hq2 dc2 | down node dc1 | bad node dc2 | bad note 50 53 | بریدگی duct-north: ۲ مدار، ۱ خرابی | bad ``` ### زمین بازی خرابی در صفحهٔ **تحلیل توپولوژی** مخزن، زبانهٔ **نیت‌ها** (کلید `4`) همهٔ نیت‌ها را فهرست می‌کند و جعبهٔ **اگر این‌ها خراب شوند؟** دارد: گروه‌های ریسک مشترک، لینک‌ها و دستگاه‌ها را انتخاب کنید و گراف نشان می‌دهد چه می‌ماند. تکه‌هایی را که شبکه به آن‌ها می‌شکند، دستگاه‌های جدا‌افتاده و نیت‌هایی را که دیگر برقرار نیستند فهرست می‌کند. هر خرابی زیر یک نیتِ شکسته دکمهٔ **امتحانش کن** دارد. همین پاسخ‌ها در `GET /v1/repos/<owner>/<repo>/topology-failure?down=srlg:duct-north,device:core2,link:hq1~hq2` هستند (یک لینک با دو سرش، یا با شماره‌اش در پاسخ). ### روی pull requestها هر pull requestی که طراحی را عوض کند با نیت‌ها سنجیده می‌شود: - **نیت‌های شاخهٔ مقصد قرارداد هستند.** حذف یک نیت در pull request آن را معاف نمی‌کند؛ نیت‌های مقصد همچنان اعمال می‌شوند، و نیت‌هایی که تغییر اضافه می‌کند هم. - نیتی که برقرار بود و دیگر نیست **ادغام را مسدود می‌کند**، و pull request می‌گوید کدام خرابی آن را می‌شکند. نیتِ تازه‌ای که طراحی برآورده نمی‌کند، با نویسندهٔ تغییر است که درستش کند. - نیتی که از قبل روی شاخهٔ مقصد شکسته بود **هشدار** است: بدهی است، نه کاری که این تغییر کرده. - مدیر مخزن باز هم می‌تواند به‌هر حال ادغام کند؛ این ثبت می‌شود. pull request **تغییر را می‌کشد** هم: زیر *اثر روی توپولوژی شبکه*، طراحی پیش و پس به صورت یک گراف، با دستگاه‌ها و پیوندهای افزوده به سبز، حذف‌شده به قرمز خط‌چین و تغییرکرده به کهربایی. روی هر کدام کلیک کنید تا ببینید چه تغییر کرده (مثلاً `circuit: TCI-4411 → TCI-9000` یا `role: distribution → core`). ```diagram type: flow title: نیت‌های شاخهٔ مقصد چه چیزی را تعیین می‌کنند or: یا --- pull request | طراحی را عوض می‌کند | accent | ⎇ ~ سنجیده با نیت‌ها | نیت‌های شاخهٔ مقصد، به‌علاوهٔ آنچه این تغییر اضافه می‌کند | | ✓ ~ هر کدام از قبل برقرار بود | هنوز برقرار است: چیزی برای گفتن نیست | good | ✓ ? برقرار بود، حالا شکسته | ادغام را مسدود می‌کند و خرابی‌ای را که می‌شکندش نام می‌برد | bad | ✕ ? از قبل شکسته بود | هشدار: بدهی است، نه کاری که این تغییر کرده | warn | ! ``` ### محدودیت‌ها - بررسی روی گراف طراحی انجام می‌شود: لینک‌ها و دستگاه‌ها بالا یا پایین‌اند. از مسیرها، ACLها یا ظرفیت چیزی نمی‌داند؛ [Path Explain](/docs/fa/network-paths) و [دوقلو](/docs/fa/network-twin) آن‌ها را روی کانفیگ‌های واقعی می‌سنجند. - `survive`، `no-spof`، `no-bridge`، `no-shared-risk` و `capacity` هر بار یک خرابی را امتحان می‌کنند؛ `availability` یک و دو خرابی را. زمین بازی هر ترکیبی را می‌پذیرد و نشان می‌دهد `capacity` (با آنچه هنوز روشن است) و `disjoint` هنوز برقرارند یا نه. - ریسک مشترک فقط همان است که نوشته‌اید. کانالی که هیچ `srlg` نامش را نبرده برای بررسی دیده نمی‌شود، پس مدارهای یک کانال را با یک گروه یکسان فهرست کنید. - طراحی‌ها تا ۵٬۰۰۰ دستگاه. ## دسترس‌پذیری، ظرفیت و مسیرهای جدا «افزونه» فقط می‌گوید دو مسیر هست. نمی‌گوید سرویس چقدر قطع است، مسیر پشتیبان ترافیک را می‌کشد یا نه، یا کدام دو مسیر را باید ساخت. سه نیت پریمیوم به این‌ها جواب می‌دهند، روی همان طراحی و در همان بررسی pull request: ```text # topology/campus.zevintent up = availability edge dc 99.95 uplinks = capacity edge dc 10000 link two-ways = disjoint edge dc device ``` ### دسترس‌پذیری `availability A B 99.95` وقتی برقرار است که A دست‌کم ۹۹٫۹۵٪ زمان به B برسد. هر دستگاه و پیوند یک **میانگین زمان بین خرابی‌ها** و یک **میانگین زمان تعمیر** به ساعت دارد (`mtbf`، `mttr`)، پس `mttr / (mtbf + mttr)` از زمان قطع است. گروه ریسک مشترکی که بلوک `[[srlg]]` خودش را دارد هم جداگانه خراب می‌شود و همهٔ پیوندهایش را با هم می‌برد: ```diagram type: stats title: «نُه»ها در یک سال چه معنایی دارند caption: فاصلهٔ ۹۹٫۹٪ تا ۹۹٫۹۹٪ فاصلهٔ یک روز کاری از دست رفته تا یک استراحت ناهار است. دسترس‌پذیری سهم زمانی است که A می‌تواند به B برسد. --- 99% | دو نُه | حدود ۳ روز و ۱۵ ساعت قطعی | 100 | bad 99.9% | سه نُه | حدود ۸ ساعت و ۴۶ دقیقه | 73 | warn 99.99% | چهار نُه | حدود ۵۳ دقیقه | 47 | accent 99.999% | پنج نُه | حدود ۵ دقیقه | 19 | good ``` ```toml [[device]] name = "core1" mtbf = 200000 # حدود ۲۳ سال mttr = 4 # قطعهٔ یدکی در محل [[link]] a = "edge" b = "core1" srlg = ["riser"] mtbf = 50000 mttr = 8 [[srlg]] name = "riser" mtbf = 50000 # بریده شدن رایزر هر ~۶ سال mttr = 48 # دو روز تا کشیدن دوبارهٔ فیبر ``` Zaryn هر خرابی تکی و هر جفت خرابی‌ای را که A را از B جدا می‌کند پیدا می‌کند، جمع می‌زند هر کدام چقدر پیش می‌آید، و دسترس‌پذیری، دقیقه‌های قطعی مورد انتظار در سال و پرهزینه‌ترین برش‌ها را گزارش می‌کند، هر کدام با **امتحانش کن**. دستگاه یا پیوندی که عدد ندارد ۱۵۰٬۰۰۰ ساعت / ۴ ساعت (دستگاه) یا ۵۰٬۰۰۰ ساعت / ۸ ساعت (پیوند) می‌گیرد، و نتیجه می‌گوید چندتا از این عددها استفاده کرده‌اند. چطور حساب می‌شود: خرابی‌ها مستقل‌اند و برش‌ها جمع زده می‌شوند (تقریب رویداد نادر). سه خرابی همزمان کنار گذاشته می‌شود؛ برش‌های هم‌پوشان دو بار شمرده می‌شوند، پس عدد به سمت کمتر خطا می‌کند. در طراحی‌هایی که برای امتحان همهٔ جفت‌ها بزرگ‌اند، فقط خرابی‌های تکی شمرده می‌شوند و نتیجه این را می‌گوید. ### ظرفیت هنگام خرابی `capacity edge dc 10000 link` وقتی برقرار است که A وقتی چیزی خراب نیست دست‌کم ۱۰۰۰۰ (به واحد `capacity` پیوندها) به B بفرستد، و بعد از خرابی هر پیوند تکی هم. نوع خرابی `link`، `srlg`، `device`، `any` (پیش‌فرض) یا `none` (فقط وقتی همه روشن‌اند) است. این یک جریان بیشینه (max flow) روی ظرفیت پیوندها در هر دو جهت است؛ پیوند بدون `capacity` نامحدود حساب می‌شود و نتیجه می‌گوید چندتا هستند. جواب بدترین خرابی تکی و آنچه باقی می‌گذارد را نام می‌برد. ```diagram type: graph title: ظرفیت هنگام خرابی: دو لینک بالادست، یک رایزر alt: edge از راه دو core به مرکز داده می‌رسد با ۱۰۰۰۰ روی هر لینک؛ قطع یک لینک ۱۰۰۰۰ باقی می‌گذارد و بریدن رایزر هیچ legend: path=لینک بالادست به core1; path2=لینک بالادست به core2; down=قطع start: هیچ خرابی caption: ۲۰۰۰۰ رد می‌شود: ۱۰۰۰۰ روی هر لینک بالادست، با جای کافی بعد از coreها. --- node edge | edge | 10 30 | router | accent | سوئیچ دسترسی که کاربران به آن وصل‌اند node core1 | core1 | 45 14 | router | | ۴۰۰۰۰ به سمت مرکز داده node core2 | core2 | 45 46 | router | | ۴۰۰۰۰ به سمت مرکز داده node dc | dc | 88 30 | server | good | ترافیک کاربران به اینجا می‌رود link edge core1 | 10000 | path | riser link edge core2 | 10000 | path2 | riser link core1 dc | 40000 | path link core2 dc | 40000 | path2 step قطع یک لینک بالادست | لینک به core1 که بیفتد باز هم ۱۰۰۰۰ رد می‌شود. `capacity edge dc 10000 link` برقرار است. link edge core1 | down link core1 dc | dim step بریدن رایزر | هر دو لینک از یک رایزر بالا می‌روند: یک بریدگی هر دو را می‌برد و هیچ‌چیز رد نمی‌شود. `capacity edge dc 10000 srlg` پیش از آنکه کسی کابلی بکشد شکست می‌خورد. link edge core2 | down link core2 dc | dim node dc | bad note 66 30 | هیچ‌چیز رد نمی‌شود | bad ``` ### مسیرهای جدا `disjoint A B link` وقتی برقرار است که دو مسیر از A به B باشد که هیچ پیوند مشترکی ندارند؛ `device` آن‌ها را در هر دستگاه میانی هم جدا نگه می‌دارد. جواب، اثبات است: دو مسیر، جفتی با کمترین مجموع `weight` (الگوریتم Suurballe، که جفت را پیدا می‌کند حتی وقتی کوتاه‌ترین مسیر به‌تنهایی راه مسیر دوم را می‌بندد). **نمایش روی گراف** آن‌ها را با دو رنگ می‌کشد. اگر هر دو مسیر از یک گروه ریسک مشترک بگذرند، این را می‌گوید: دو مسیر جدا در یک کانال با یک برش هر دو قطع می‌شوند، که `survive A B srlg` آن را می‌گیرد. ```diagram type: graph title: چرا جفت مسیر فقط «کوتاه‌ترین و بعد کوتاه‌ترینِ بعدی» نیست alt: ارزان‌ترین مسیر تکی از s به t از پیوند میانی می‌گذرد و مسیر دومی نمی‌گذارد؛ ارزان‌ترین جفت جدا از دو مسیر بیرونی می‌رود legend: path=مسیر اول; path2=مسیر دوم; ghost=استفاده نشده start: اول کوتاه‌ترین مسیر caption: کوتاه‌ترین مسیر، s-x-y-t، هزینه‌اش ۳ است. آن را که بردارید، هر راه دیگری از s به t پیوندی با آن مشترک دارد: مسیر دومی نمی‌ماند. --- node s | s | 8 30 | user | accent node x | x | 38 12 | router node y | y | 62 48 | router node t | t | 92 30 | server | good link s x | 1 | path link x y | 1 | path link y t | 1 | path link x t | 5 | dim link s y | 5 | dim step ارزان‌ترین جفت | الگوریتم Suurballe جفتی را پیدا می‌کند که هیچ اشتراکی ندارند و روی هم ارزان‌ترین‌اند: s-x-t به‌علاوهٔ s-y-t، روی هم ۱۲. link x y | ghost link x t | path link s y | path2 link y t | path2 ``` ### در پلن رایگان در مخزنی که مالکش پریمیوم ندارد، این سه نیت «منتظر پریمیوم» فهرست می‌شوند. شکست حساب نمی‌شوند و هرگز جلوی ادغام را نمی‌گیرند؛ بقیهٔ نیت‌ها مثل همیشه بررسی می‌شوند. ## تاب‌آوری، و پیوندهایی که کمک می‌کنند نمای کلی شبکه به طراحی نمره می‌دهد: **تاب‌آوری** سهم خرابی‌های تکی (هر بار یک دستگاه یا یک پیوند) است که هیچ‌کس را جدا نمی‌کنند. برای هر خرابی‌ای که جدا می‌کند، می‌گوید چه کسانی جدا می‌شوند، بدترین اول (`core1 fails: cuts off 3 devices: dist1, acc1, acc2`). **نمایش گرما** هر دستگاه را بر اساس اینکه خرابی خودش چقدر جدا می‌کند، از کهربایی تا قرمز رنگ می‌زند. سپس دنبال راه‌حل می‌گردد. هر پیوندی را که طراحی هنوز ندارد امتحان می‌کند و آن‌ها را همان‌طور که یک مهندس انتخاب می‌کند رتبه می‌دهد: اول آنچه هر کدام برمی‌دارد (نقطه‌های شکست تکی و پیوندهای حیاتی)، کابل کوتاه پیش از بلند (همان سایت پیش از یک مدار تازه میان سایت‌ها)، و هرگز دو دستگاه برگ به هم. چند تای بهتر با آنچه برمی‌دارند نشان داده می‌شوند. **افزودن در ویرایشگر** [ویرایشگر](#ویرایش-کد-و-بوم) را با همان پیوند افزوده‌شده باز می‌کند، آماده برای بازبینی، ذخیره روی یک شاخه و باز کردن یک درخواست ادغام، جایی که [نیت‌ها](#نیتها-intent) و دوقلو آن را می‌سنجند. ```diagram type: graph title: بهترین پیوند برای افزودن alt: core1 نقطهٔ شکست تکی dist1 و دو سوئیچ دسترسی آن است؛ افزودن پیوندی از core2 به acc1 به آن‌ها راه دومی می‌دهد، پس خرابی core1 دیگر جدایشان نمی‌کند legend: down=نقطهٔ شکست تکی; new=پیوند پیشنهادی start: امروز caption: روی یک دستگاه بروید. امروز خرابی core1، dist1 و acc1 و acc2 را جدا می‌کند: همه به آن بندند. height: 46 --- node core1 | core1 | 30 8 | router | bad | نقطهٔ شکست تکی: سه دستگاه به آن بندند node core2 | core2 | 70 8 | router node dist1 | dist1 | 30 24 | switch | warn node acc1 | acc1 | 18 40 | switch | warn node acc2 | acc2 | 42 40 | switch | warn link core1 core2 link core1 dist1 | | down link dist1 acc1 link dist1 acc2 link core2 acc1 | | ghost step افزودن core2 ⟷ acc1 | پیشنهاد: یک پیوند در همان سایت. core1 دیگر نقطهٔ شکست تکی نیست، و core1 — dist1 و dist1 — acc1 دیگر پیوند حیاتی نیستند. link core2 acc1 | new | پیشنهادی link core1 dist1 | normal node core1 | normal node dist1 | normal node acc1 | good ``` ## طراحی در گذر زمان **طراحی در گذر زمان** طراحی امروز را با هر یک از آخرین کامیت‌هایش مقایسه می‌کند. لغزنده را به عقب ببرید تا نمودار نشان دهد از آن زمان چه چیزی عوض شده: دستگاه‌ها و پیوندهای افزوده سبز، حذف‌شده قرمز خط‌چین، تغییرکرده کهربایی، همراه با کامیت، کسی که آن را push کرد و زمانش. **پخش** از قدیمی‌ترینشان تا اکنون پیش می‌رود. سریع‌ترین راه برای پاسخ به «از قطعی تا حالا چه چیزی را عوض کردیم؟». ## کپی برای عامل هوش مصنوعی **کپی برای عامل هوش مصنوعی (Markdown)** طراحی را در چند خط Markdown کپی می‌کند: دستگاه‌ها و پیوندها به‌صورت جدول، نمرهٔ تاب‌آوری، خرابی‌های تکی که دستگاهی را جدا می‌کنند و پیوندهای پیشنهادی. آن را در Claude Code، Codex یا یک تیکت بچسبانید: کسری از توکن‌های فایل‌های `.zevtopo`، با تحلیلی که از پیش انجام شده. عامل‌هایی که از راه [`zev mcp`](/docs/fa/automation-and-agents) وصل‌اند، نیت‌ها و خرابی‌های یک طراحی را خودشان هم می‌توانند بخوانند. ## اجرای طراحی به صورت آزمایشگاه طراحی‌ای که هرگز اجرا نشده یک فرضیه است. دکمهٔ **دانلود ‎.clab.yml** در نمای کلی شبکه طراحی را به توپولوژی [Containerlab](https://containerlab.dev) تبدیل می‌کند (یا با **دانلود ‎.gns3** به پروژهٔ GNS3)، تا آن را در کانتینر یا ماشین مجازی اجرا کنید، از میانش پینگ بگیرید، پیوندی را بکشید و ببینید آنچه نیت‌ها و زمین بازی خرابی پیش‌بینی کردند واقعاً رخ می‌دهد. ```diagram type: flow title: از طراحی تا آزمایشگاه loop: طراحی را عوض کنید، دوباره اجرا کنید --- طراحی | فایل‌های ‎.zevtopo در مخزن | accent | 📐 ~ دانلود ‎.clab.yml فایل آزمایشگاه | گره‌ها به‌تفکیک سازنده، پیوندها با پورت‌هایشان | | 📄 ~ containerlab deploy آزمایشگاه در حال اجرا | کانتینرها یا ماشین‌های مجازی، سیم‌کشی‌شده طبق طراحی | good | ▶ ~ ping، کشیدن یک پیوند چه می‌شود | با نیت‌ها و زمین بازی خرابی مقایسه کنید | warn | 🔬 ``` ```bash containerlab deploy -t my-network.clab.yml ``` همچنین در `GET /v1/repos/<owner>/<repo>/topology-export?format=containerlab|gns3[&ref=<branch>]`، به صورت `{file, text, warnings, nodes, links}`. رایگان است، مثل بقیهٔ مخزن طراحی. نگاشت طراحی: | طراحی | آزمایشگاه | |---|---| | یک `[[device]]` | یک گره؛ `vendor` نوع و image را تعیین می‌کند: `frr` کانتینر FRRouting، `arista` همان `ceos`، `cisco` همان `cisco_iol`، `juniper` همان `juniper_crpd`، `mikrotik` همان `mikrotik_ros`، `vyos` همان `vyosnetworks_vyos`؛ هر سازندهٔ دیگر یک کانتینر لینوکس ساده | | `site`، `role`، `model` | برچسب‌های گره | | یک `[[link]]` | دو نقطهٔ پایانی، یکی برای هر دستگاه | | پورت‌ها (`a_if`، `b_if`) | فقط وقتی نگه داشته می‌شوند که از قبل `ethN` باشند؛ هر نام دیگر (`Gi0/1`، `Te1/0/1`) در توضیحی کنار پیوند نوشته می‌شود و نقطهٔ پایانی `ethN` آزاد بعدی را می‌گیرد | | دستگاهی که فقط پیوندی نامش را برده | آن هم یک گره | آنچه برایتان نمی‌تواند بکند، و در فهرستی از نکته‌ها می‌گوید: imageهای سازنده‌ها (`ceos`، `cisco_iol`، `crpd`، `vrnetlab/*`) آزادانه قابل دانلود نیستند، پس فایل جانشین می‌نویسد که خودتان وارد یا بسازید؛ نام‌هایی که Containerlab نمی‌پذیرد (فاصله، اسلش) پاک‌سازی و فهرست می‌شوند؛ پیوند یک دستگاه به خودش کنار گذاشته می‌شود؛ سازنده‌هایی که نوع Containerlab ندارند کانتینر لینوکس می‌شوند. آزمایشگاه شکل طراحی را دارد، نه پیکربندی‌اش را: پیکربندی‌های واقعی را از [سایت](/docs/fa/network-sites) یا مخزن پیکربندی بارگذاری کنید. ### در GNS3 اگر تیم شما آزمایشگاه‌ها را به‌جای Containerlab در [GNS3](https://gns3.com) می‌سازد، **دانلود ‎.gns3** همان طراحی را به صورت پروژهٔ GNS3 می‌دهد. در GNS3 گزینهٔ **File → Open project** را بزنید و فایل را انتخاب کنید: دستگاه‌ها از پیش چیده (لبه در بالا، سپس هسته، توزیع، دسترسی و میزبان‌ها در پایین، هر ردیف به‌ترتیب سایت) و سیم‌کشی شده‌اند. | طراحی | GNS3 | |---|---| | `frr`، `arista`، `juniper` | گره‌های Docker: کانتینر FRRouting، `ceos:latest` (با متغیرهای محیطی و فرمان شروعی که cEOS لازم دارد)، `crpd:latest` | | `cisco`، `mikrotik`، `vyos` | ماشین‌های مجازی QEMU: ‏IOSv (`vios-adventerprisek9-m.spa.159-3.m8.qcow2`)، MikroTik CHR (`chr-7.16.img`)، VyOS (`vyos-1.4.qcow2`)، با RAM و آداپتورهای تنظیم‌شده | | بدون سازنده، با نقش سوئیچ (`access`، `leaf`، `switch`) | سوئیچ اترنت داخلی GNS3: بدون هیچ imageای اجرا می‌شود | | بدون سازنده، با نقش میزبان و یک پیوند | یک میزبان VPCS: آن هم بدون image | | هر سازندهٔ دیگر | یک کانتینر لینوکس (network-multitool) | | پورت‌ها | پورتی که طراحی با نام‌گذاری خود گره نام برده (`eth2`، `ether3`، `Gi0/1`) همان آداپتور است؛ هر نام دیگر آداپتور آزاد بعدی را می‌گیرد و روی بوم به عنوان نام همان پورت نشان داده می‌شود، پس `Te1/0/1` همچنان `Te1/0/1` خوانده می‌شود | | `vendor`، `role`، `site`، `model` | یادداشت‌های گره | یک طراحی همیشه همان فایل را می‌دهد (شناسهٔ گره‌ها و پیوندها از نام‌ها ساخته می‌شود)، پس فایل ‎.gns3ای که کنار طراحی نگه می‌دارید فقط جایی عوض می‌شود که طراحی عوض شده. imageها نام برده می‌شوند، نه فرستاده، و GNS3 پروژه‌ای را که یکی از آن‌ها را ندارد باز نمی‌کند؛ پس نخستین نکته فهرستشان را می‌دهد: اول imageهای Docker را روی سرور GNS3 (یا GNS3 VM) و دیسک‌های QEMU را در پوشهٔ images آن بگذارید. با GNS3 2.2 آزموده شده. API: ‏`?format=gns3`، فایل `<repo>.gns3`. ## گواهی‌های تغییر حسابرس، مشتری یا بازبینی حادثهٔ خودتان می‌پرسد: چه کسی طراحی شبکه را عوض کرد، چه چیزی بررسی شد و چه کسی موافقت کرد؟ صفحهٔ pull request امروز به این جواب می‌دهد؛ **گواهی تغییر** به شکلی جواب می‌دهد که بعداً بی‌صدا ویرایش نمی‌شود و بدون اعتماد به پایگاه داده Zaryn قابل بررسی است. با پریمیوم، هر pull request ادغام‌شده‌ای که فایل‌های `.zevtopo` یا `.zevintent` طراحی را عوض کند یک گواهی می‌گیرد. در آن ثبت می‌شود: - مخزن، pull request، عنوان و نویسنده‌اش، چه کسی و کِی ادغامش کرد، چه کسانی تأییدش کردند - commitهای پیش و پس، و SHA-256 هر فایل طراحی و نیت در هر دو طرف - نتیجهٔ بررسی‌های شبکه، آنچه در گراف عوض شد (دستگاه‌ها، تکه‌ها، نقطه‌های شکست تکی و پیوندهای حیاتی تازه) و نتیجهٔ هر نیت - اینکه با وجود بررسی‌های ناموفق ادغام شد یا نه (**اجباری**) - `prev`: گواهی قبلی همان مخزن این یک سند dag-cbor است که با کلید Ed25519 خود Zaryn امضا شده، همان کلیدی که [لاگ شفافیت](/docs/fa/verified-storage) را امضا می‌کند، و یک برگ از همان لاگ است. چون هر گواهی گواهی قبلی را نام می‌برد، گواهی‌های یک مخزن یک زنجیره‌اند: تاریخچهٔ طراحی، قدم به قدم، بی‌آنکه چیزی بی‌صدا جا بیفتد (نمای کلی شبکه زنجیره را فهرست می‌کند و گسست را نشان می‌دهد). ```diagram type: flow title: زنجیرهٔ گواهی‌ها caption: هر گواهی گواهی قبلی را نام می‌برد (`prev`)، پس گواهی گم‌شده یا دست‌خورده معلوم می‌شود. --- #۱ · لینک بالادست دوم | ادغام توسط sara، تأیید omid، نیت‌ها برقرار | good | 1 ~ prev #۲ · تعمیر رایزر ۲۴ ساعته | ادغام توسط sara، نیت‌ها برقرار | good | 2 ~ prev #۳ · یک لینک بالادست | با وجود بررسی‌های ناموفق ادغام شد (اجباری) | bad | 3 ``` **بررسی یک گواهی.** در pull request ادغام‌شده، **بررسی در همین مرورگر** پنج چیز را فقط با خود بایت‌ها بررسی می‌کند: نشانی محتوا (CID) با سند امضاشده می‌خواند، بایت‌های امضاشده همان را می‌گویند که صفحه نشان می‌دهد، امضای Ed25519، اینکه کلید همان کلید امضای لاگ شفافیت است، و اینکه فایل‌های گواهی‌شده همان فایل‌های مخزن در آن commit هستند. **دانلود** گواهی را به صورت JSON ذخیره می‌کند تا جای دیگری بررسی شود. API: ```text GET /v1/repos/<owner>/<repo>/pulls/<n>/certificate payload (base64), payload_cid, signature, public_key, log_index, certificate (JSON) GET /v1/repos/<owner>/<repo>/design-certificates زنجیره، تازه‌ترین اول GET /v1/transparency/proof?leaf_index=<log_index> جای گواهی در لاگ ``` بررسی دستی: `payload` را از base64 باز کنید؛ CID آن CIDv1، dag-cbor و BLAKE3-256 همان بایت‌هاست (`b3sum`)؛ امضا Ed25519 روی همان بایت‌ها با `public_key` است (`openssl pkeyutl -verify -rawin`). ```diagram type: sequence title: بررسی در همین مرورگر lanes: مرورگر شما | Zaryn | لاگ شفافیت alt: مرورگر گواهی را می‌گیرد، نشانی محتوا را دوباره حساب می‌کند، امضا و کلید را می‌سنجد و فایل‌ها را با مخزن مقایسه می‌کند --- مرورگر شما -> Zaryn : گواهی و بایت‌های امضاشده مرورگر شما -> مرورگر شما : ۱ · CID بایت‌ها می‌خواند مرورگر شما -> مرورگر شما : ۲ · بایت‌ها همان را می‌گویند که صفحه نشان می‌دهد مرورگر شما -> مرورگر شما : ۳ · امضای Ed25519 معتبر است مرورگر شما -> لاگ شفافیت : ۴ · این کلید لاگ را هم امضا می‌کند لاگ شفافیت --> مرورگر شما : سر درخت امضاشده مرورگر شما -> Zaryn : ۵ · فایل‌ها در آن commit Zaryn --> مرورگر شما : SHA-256 آن‌ها با گواهی می‌خواند | good ``` گواهی بررسی‌های طراحی را پوشش می‌دهد که Zaryn هنگام ادغام اجرا کرد. نتیجه‌های twin برای سایت‌های پیوندخورده و نتیجه‌های eval روی pull request هستند، نه در گواهی. در پلن رایگان ادغام همان‌طور کار می‌کند، بدون گواهی. ## قدم بعدی طراحی آغاز چرخه است: [دوقلو](/docs/fa/network-twin) پیش‌بینی می‌کند یک تغییر کانفیگ چه می‌کند، و [اعمال تغییر](/docs/fa/network-rollouts) آن را روی دستگاه‌ها انجام می‌دهد و بررسی می‌کند. طراحی و کانفیگ‌ها در مخزن‌های جدا هستند: طراحی می‌گوید شبکه چیست، مخزن کانفیگ می‌گوید هر دستگاه چطور تنظیم شده است.