Document Networks as Code with D2!

Let's do something a bit more stereotypical when we talk about IT diagramming - building Network Diagrams with D2.

D2's OSS layout engines (Dagre, ELK) are both centered around hierarchical layouts, which was a bit part of why we needed to hack D2 to get vSphere diagrams to draw. Here, it quickly becomes our best friend - Network Engineers will arrange just about anything into a tree hierarchy if permitted - and our network topologies reflect that.

First, let's load some stencils! We'll use Crayon Visio for this exercise. The Cisco SAFE Architecture Toolkit listed here is a bit more serious and visually appealing.

If you want to see why I did it, check out this lovely firewall icon:

Firewall Icon

This is a Visio stencil, so it'll take a bit of work to convert. The vssx extension for Microsoft Visio is a Zip-compressed file, and the images are listed under visio/media, and convert with transparency using GIMP (this is not fun). Drop the exported png files (it's a raster image, not a vector) in a folder, in this case dwg/.

Drawing Networks

Let's try it out!

 1direction: right
 2Firewall {
 3    icon: dwg/firewall.png
 4}
 5Outside Router {
 6    icon: dwg/router.png
 7}
 8Inside Router {
 9    icon: dwg/router.png
10}
11Inside Router -- Firewall -- Outside Router

Simple Network Diagram

Now, let's try a hierarchy (Layer 3 Clos Fabric):

 1direction: right
 2AS65533 {
 3  spine-1: "as65533-spine-1" {
 4    icon: "dwg/router.png"
 5  }
 6  spine-2: "as65533-spine-2" {
 7    icon: "dwg/router.png"
 8  }
 9  spine-3: "as65533-spine-3" {
10    icon: "dwg/router.png"
11  }
12  spine-4: "as65533-spine-4" {
13    icon: "dwg/router.png"
14  }
15  leaf-1: "as65533-leaf-1" {
16    icon: "dwg/switch.png"
17  }
18  leaf-2: "as65533-leaf-2" {
19    icon: "dwg/switch.png"
20  }
21  leaf-3: "as65533-leaf-3" {
22    icon: "dwg/switch.png"
23  }
24  leaf-4: "as65533-leaf-4" {
25    icon: "dwg/switch.png"
26  }
27  leaf-5: "as65533-leaf-5" {
28    icon: "dwg/switch.png"
29  }
30  leaf-6: "as65533-leaf-6" {
31    icon: "dwg/switch.png"
32  }
33  spine-1 -- leaf-1: "eth1/1<->eth1/49"
34  spine-1 -- leaf-2: "eth1/2<->eth1/49"
35  spine-1 -- leaf-3: "eth1/3<->eth1/49"
36  spine-1 -- leaf-4: "eth1/4<->eth1/49"
37  spine-1 -- leaf-5: "eth1/5<->eth1/49"
38  spine-1 -- leaf-6: "eth1/6<->eth1/49"
39  spine-2 -- leaf-1: "eth1/1<->eth1/50"
40  spine-2 -- leaf-2: "eth1/2<->eth1/50"
41  spine-2 -- leaf-3: "eth1/3<->eth1/50"
42  spine-2 -- leaf-4: "eth1/4<->eth1/50"
43  spine-2 -- leaf-5: "eth1/5<->eth1/50"
44  spine-2 -- leaf-6: "eth1/6<->eth1/50"
45  spine-3 -- leaf-1: "eth1/1<->eth1/51"
46  spine-3 -- leaf-2: "eth1/2<->eth1/51"
47  spine-3 -- leaf-3: "eth1/3<->eth1/51"
48  spine-3 -- leaf-4: "eth1/4<->eth1/51"
49  spine-3 -- leaf-5: "eth1/5<->eth1/51"
50  spine-3 -- leaf-6: "eth1/6<->eth1/51"
51  spine-4 -- leaf-1: "eth1/1<->eth1/52"
52  spine-4 -- leaf-2: "eth1/2<->eth1/52"
53  spine-4 -- leaf-3: "eth1/3<->eth1/52"
54  spine-4 -- leaf-4: "eth1/4<->eth1/52"
55  spine-4 -- leaf-5: "eth1/5<->eth1/52"
56  spine-4 -- leaf-6: "eth1/6<->eth1/52"
57}

D2 Diagram - Clos Fabric

Note that I used the direction: right directive to make this readable on blog and mobile. direction: down and some custom padding would be more appropriate when describing a solution in a Visio/Print-style media.

Let's make this fun, and add externalities:

 1direction: right
 2AS65534: {
 3    firewall-cluster-1: "AS65534 Firewall Cluster" {
 4        icon: "dwg/firewall.png"
 5    }
 6}
 7Storage: {
 8    nfs-array-1: "General-Use NFS" {
 9        icon: "dwg/storage.png"
10    }
11    nfs-array-2: "PCI NFS" {
12        icon: "dwg/storage.png"
13    }
14}
15Compute: {
16    vsphere-cluster-1: "General Use vSphere" {
17        icon: "dwg/server-cluster.png"
18    }
19    vsphere-cluster-2: "PCI vSphere" {
20        icon: "dwg/server-cluster.png"
21    }
22}
23AS65534.firewall-cluster-1<->AS65533.leaf-1
24AS65534.firewall-cluster-1<->AS65533.leaf-2
25Storage.nfs-array-1<->AS65533.leaf-3
26Storage.nfs-array-2<->AS65533.leaf-4
27Compute.vsphere-cluster-1<->AS65533.leaf-5
28Compute.vsphere-cluster-1<->AS65533.leaf-6
29Compute.vsphere-cluster-2<->AS65533.leaf-5
30Compute.vsphere-cluster-2<->AS65533.leaf-6

D2 Diagram - Clos Fabric with Externalities

If you click on the image, it will direct you towards a ELK diagram format with direction: down.

Conclusion

The automatic layout settings for D2 require a certain amount of tweaking to get just right, and as a topology gets "full" curating the layout becomes more difficult.

That being said, changing between formats (blog/web to a stricter canvas) only takes a few seconds, as opposed to hours. D2 (as a solution) excels in situations where a topology or solution may be fluid or repeatable, and it doesn't necessarily need to be presentation grade.

Terrastruct's layout engine (TALA) appears to have the highest quality output of the bunch - several ELK layouts crashed go while executing these examples, and Dagre as a layout engine is unmaintained since 2018. TALA does have the potential to routinely deliver presentation-grade solutions, and D2 ships with a variety of "freebie" resources to make it a good end-to-end solution.

D2 also performed exceptionally well with ridiculous large topologies, it's difficult to consume a full second of CPU time with a diagram, and it can run server-side with an API - Kroki implements one. If automatic documentation is a regular part of business, I'd recommend publishing the stencils to an object store or HTTP server and make it accessible to a system like Kroki - this effectively lets you auto-diagram with no user intervention.

Posts in this Series