Skip to content

networkop/k8s-topo

Repository files navigation

Docker Pulls

k8s-topo

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+https://github.com/networkop/k8s-topo.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 https://raw.githubusercontent.com/networkop/k8s-topo/master/manifest.yml

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

kubectl exec -it deployment/k8s-topo sh

Usage

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

links:
  - endpoints: ["host-1:eth1:12.12.12.1/24", "host-2:eth1:12.12.12.2/24"]
  - endpoints: ["host-1:eth2:13.13.13.1/24", "host-3:eth1:13.13.13.3/24"]
  - endpoints: ["host-2:eth2:23.23.23.2/24", "host-3:eth2:23.23.23.3/24"]

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
host-1@kind-worker
host-2@kind-worker2
host-3@kind-worker2

Test connectivity

kubectl exec -it host-1 -- ping -c 1 12.12.12.2
kubectl exec -it host-1 -- ping -c 1 13.13.13.3
kubectl exec -it host-2 -- ping -c 1 23.23.23.3

Destroy the topology

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

Visualisation

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
INFO:__main__:URL: http://172.17.0.2:30000

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 https://github.com/networkservicemesh/networkservicemesh
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
links:
  - 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   10.233.6.223   <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 [10.233.6.223:5000/ceos]
7d3e293b5c56: Pushed 
4.20.5F: digest: sha256:caee130f23d25206ae5a3381c6c716b83fa12122f9a092ba99b09bd106c5f970 size: 529

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

Examples

Prerequisites

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
links:
  - 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
sw-1@node1
sw-2@node1
sw-3@node1

Interact with any pod

/k8s-topo # sw-1
sw-1>en
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 12.12.12.1/24
!
interface Ethernet2
   no switchport
   ip address 13.13.13.1/24
!
no ip routing
!
end
sw-1#ping  12.12.12.2
PING 12.12.12.2 (12.12.12.2) 72(100) bytes of data.
80 bytes from 12.12.12.2: icmp_seq=1 ttl=64 time=33.9 ms
80 bytes from 12.12.12.2: icmp_seq=2 ttl=64 time=10.2 ms
80 bytes from 12.12.12.2: icmp_seq=3 ttl=64 time=13.3 ms
80 bytes from 12.12.12.2: icmp_seq=4 ttl=64 time=13.2 ms
80 bytes from 12.12.12.2: icmp_seq=5 ttl=64 time=9.28 ms

--- 12.12.12.2 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
sw-1#

Destroy the topology

k8s-topo --destroy examples/3node-ceos.yml
INFO:__main__:All pods have been destroyed successfully
INFO:__main__:
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
INFO:__main__:URL: http://10.83.30.251:30000

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 - '192.0.2.0/24', '198.51.100.0/24', '203.0.113.0/24'

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 - '192.0.2.0/24', '198.51.100.0/24', '203.0.113.0/24')

/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