Skip to content
Switch branches/tags
Go to file

Latest commit


Failed to load latest commit information.
Latest commit message
Commit time

Docker Pulls


Arbitrary network topology builder for network simulations inside Kubernetes. Analogous to docker-topo. Relies on either meshnet CNI plugin (default) or Network Service Mesh.

Local installation

Make sure you've got python3-dev and build-essential/build-base packages installed and then do

pip install git+

Hosted K8s installation

The following manifest will install the k8s-topo as a deployment inside the Kubernetes cluster and create all the necessary RBAC rules:

kubectl create -f

Connect to the k8s-topo pod to get access to the script:

kubectl exec -it deployment/k8s-topo sh


Create a topology definition file. Example below is for a full-mesh 3-node topology.

  - endpoints: ["host-1:eth1:", "host-2:eth1:"]
  - endpoints: ["host-1:eth2:", "host-3:eth1:"]
  - endpoints: ["host-2:eth2:", "host-3:eth2:"]

Instantiate the topology inside Kubernetes

k8s-topo --create examples/3node-host.yml

List all pods in the topology and their respective locations

k8s-topo --show examples/3node-host.yml

Test connectivity

kubectl exec -it host-1 -- ping -c 1
kubectl exec -it host-1 -- ping -c 1
kubectl exec -it host-2 -- ping -c 1

Destroy the topology

k8s-topo --destroy examples/3node-host.yml


After the topology has been created, it is possible to view the resulting graph. The k8s-topo --graph topology_name command will create a json representation of the topology graph and feed it into a simple D3.js-based web page.

k8s-topo --graph examples/builder/random.yml 
INFO:__main__:D3 graph created

This web page, running inside a k8s-topo pod, is exposed externally as a NodePort service on port 32000 of every node.

The colour of vertices represent the node the pod is running on. In this case the topology is spread across 4 different nodes.

Network Service Mesh

By default all pod connectivity is setup by the meshnet CNI plugin. Alternatively, connectivity can be setup at runtime by NSM. You first would need to install NSM:

git clone
cd networkservicemesh
make helm-init
SPIRE_ENABLED=false INSECURE=true FORWARDING_PLANE=kernel make helm-install-nsm 

Once installed, any topology definition file can be made "nsm-compliant" by adding a nsm: true flag to the top of the file, e.g.:

nsm: true
  - endpoints: ["qrtr-1:eth12", "qrtr-2:eth21"]

See nsm-5node.yml for another example.

Private docker registry setup

It's possible to setup a private docker registry to speed up the image pull process and store cEOS images locally:

kubectl create -f examples/docker-registry/docker-registry.yml 

The private registry can be accessed by its cluster IP:

kubectl get service docker-registry
NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
docker-registry   ClusterIP   <none>        5000/TCP   10s

The following environment variable will be used by k8s-topo script to set the default cEOS image:

export CEOS_IMAGE=$(kubectl get service docker-registry -o json | jq -r '.spec.clusterIP'):5000/ceos:4.20.5F

Now we can upload the cEOS docker image to this registry:

docker import cEOS-4.20.5F-lab.tar.xz ceos:4.20.5F
docker image tag ceos:4.20.5F $CEOS_IMAGE
docker image push $CEOS_IMAGE 
The push refers to repository []
7d3e293b5c56: Pushed 
4.20.5F: digest: sha256:caee130f23d25206ae5a3381c6c716b83fa12122f9a092ba99b09bd106c5f970 size: 529

This registry and cEOS image can now be used in the examples below



Working K8s cluster with meshnet-CNI installed is required. Refer to meshnet-cni for setup scripts.

To use vrnetlab images, refer to this guide

3-node cEOS topology

Topology definition file (cEOS is stored in a private Docker registry)

conf_dir: ./config-3node
  - endpoints: ["sw-1:eth1", "sw-2:eth1"]
  - endpoints: ["sw-1:eth2", "sw-3:eth1"]
  - endpoints: ["sw-2:eth2", "sw-3:eth2"]

Create the topology

k8s-topo --create examples/3node-ceos.yml

List all pods in the topology

k8s-topo --show examples/3node-ceos.yml

Interact with any pod

/k8s-topo # sw-1
sw-1#sh run 
! Command: show running-config
! device: sw-1 (cEOSSim, EOS-4.20.5F)
transceiver qsfp default-mode 4x10G
hostname sw-1
spanning-tree mode mstp
no aaa root
interface Ethernet1
   no switchport
   ip address
interface Ethernet2
   no switchport
   ip address
no ip routing
PING ( 72(100) bytes of data.
80 bytes from icmp_seq=1 ttl=64 time=33.9 ms
80 bytes from icmp_seq=2 ttl=64 time=10.2 ms
80 bytes from icmp_seq=3 ttl=64 time=13.3 ms
80 bytes from icmp_seq=4 ttl=64 time=13.2 ms
80 bytes from icmp_seq=5 ttl=64 time=9.28 ms

--- ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 122ms
rtt min/avg/max/mdev = 9.280/16.004/33.929/9.105 ms, ipg/ewma 30.596/24.630 ms

Destroy the topology

k8s-topo --destroy examples/3node-ceos.yml
INFO:__main__:All pods have been destroyed successfully
unalias sw-1
unalias sw-2
unalias sw-3
INFO:__main__:All data has been cleaned up from etcd

20-node random cEOS topology

Generate a random 20-node cEOS topology

./examples/builder/builder 20 0 --prefix sw

Create the topology (takes about 2 minutes)

k8s-topo --create examples/builder/random.yml

Enable ip forwarding inside cEOS containers

k8s-topo --eif examples/builder/random.yml

Generate the topology graph

k8s-topo --graph examples/builder/random.yml
INFO:__main__:D3 graph created

Check connectivity

19/k8s-topo # kubectl exec -it sw-1 bash
/ # export PREFIX=192.0.2
/ # for i in `seq 0 19`; do echo "${PREFIX}.$i =>"  $(ping -c 1 -W 1 ${PREFIX}.$i|grep loss); done
1 packets transmitted, 1 packets received, 0% packet loss

Destroy the topology

k8s-topo --destroy examples/builder/random.yml

750-node random Quagga router topology

Note: max limit for random topology builder is 768 nodes, based on the available address space reserved for documentation - '', '', ''

Generate a random 750-node network topology

./examples/builder/builder 750 0
Total number of links generated: 749

Create the topology (takes about 2 minutes)

k8s-topo --create examples/builder/random.yml

Check connectivity (repeat for all loopback ranges - '', '', '')

/k8s-topo # qrtr-143
/ # export PREFIX=192.0.2
/ # for i in `seq 0 255`; do echo "${PREFIX}.$i =>"  $(ping -c 1 -W 1 ${PREFIX}.$i|grep loss); done
1 packets transmitted, 1 packets received, 0% packet loss

Destroy the topology

k8s-topo --destroy examples/builder/random.yml