Guide

netlab

netlab builds a lab from a YAML topology and starts each node under containerlab. Ze runs as one of those nodes. netlab calls this the daemon tier: one YAML file and one directory of Jinja2 templates, with no Ansible task lists and no Vagrant box.

The ze side of that integration lives in contrib/netlab/. contrib/netlab/README.md is the source of truth for the artifacts. This page explains how to run them.

What you need

Component Why
netlab 26.08 Renders the topology and calls containerlab
containerlab and docker Start the nodes
netlab/ze:latest The lab image, built from. docker/Dockerfile.lab

The lab image is not the deployment image. See Docker for the two images and what separates them.

Step 1: build the image

docker build -t netlab/ze:latest -f docker/Dockerfile.lab .

contrib/netlab/ze.yml sets clab.build: False and names netlab/ze:latest, so netlab starts this image and builds nothing. Change its image: value when you choose a different Docker tag.

Step 2: give netlab the daemon definition

There are two routes, and contrib/netlab/README.md gives both. Copy the daemon definition and the templates into the netlab package:

cp contrib/netlab/ze.yml  <netlab>/netsim/daemons/ze.yml
cp -R contrib/netlab/ze   <netlab>/netsim/daemons/ze

Or leave the netlab install alone and let a topology carry them, which is what ./le netlab render-check does. netlab reads a topology-defaults.yml beside the topology and a templates/ze/ directory beside it.

Step 3: run the reference topology

netlab up -t contrib/netlab/topology.yml

contrib/netlab/topology.yml has three nodes:

r1 ---- internal ---- r2      AS 65001, iBGP + OSPF + IS-IS + BFD
 \
  ---- external ---- r3       AS 65002, eBGP only

netlab runs an IGP on internal links only, so the eBGP peer sits on its own link. r1 also carries two static routes. The topology declares every module ze.yml declares: bgp, ospf, isis, bfd, and routing.

How netlab configures a node

netlab renders contrib/netlab/ze/ze.j2 into one file, /etc/ze/ze.conf, and containerlab bind-mounts it into the node. Ze has no include directive, so one file holds the whole running configuration. Each other module key points at an ignore file that nothing reads.

The node starts with ze start /etc/ze/ze.conf. netlab assigns the interface addresses with ip inside the container, so the rendered configuration carries no interface block.

Ze re-reads its configuration on SIGHUP only. handleSIGHUPReload stages the file as a candidate and reloads it. netlab sends no SIGHUP, and ze.yml says so with features.initial.reload: false. A configuration change in a running lab therefore needs kill -HUP on the ze process inside the node, or a node restart.

netlab validate reads the daemon through the CLI. ze.yml declares the show command as ze cli -c "show $@ | json compact", and netlab runs it with docker exec. An explicit format pipe beats the --format flag, so that command emits JSON.

The lab login

The rendered configuration declares one user, netlab, with the password netlab. ze.yml puts the same pair in the container environment, so the CLI inside the node has a credential. This is a well-known password in a throwaway container. Nothing in ze defaults to it and no image carries it.

The template writes the password as plaintext-password. Ze hashes that leaf when it loads the file, and it warns that the file still holds the secret. See Authentication.

What is proven, and what is not

The lab has never been started on the machine that wrote this integration. That machine has no containerlab, so netlab up and netlab validate were not run. The declared bgp, ospf, isis, bfd, and routing features are rendered and parsed. They are not validated against netlab's own integration tests.

Statement Evidence
netlab accepts the daemon definition and finds a template for each module netlab create exits 0 on the reference topology, in ./le netlab render-check
The render is valid ze configuration ze config validate exits 0 on each file under. contrib/netlab/golden/
A daemon runs one of those renders and answers the show command with JSON test/plugin/netlab-lab-profile.ci
Routes reach the FIB of a running lab, and a ping validation passes Not run
Each declared feature passes netlab's integration test for it Not run

Ze also sends and receives no LLDP frame, so a netlab validation that reads LLDP data cannot pass. containerlab does not need LLDP, because the topology names the veth links.

Keeping the templates from drifting

./le netlab render-check

It renders the templates with a real netlab, compares the result with contrib/netlab/golden/, and runs ze config validate on each golden file. A missing netlab is an error exit, never a skip. Use ./le netlab render-update to rewrite the golden files. test/plugin/netlab-lab-profile.ci is the other half and needs no netlab: it starts a daemon from a golden file and parses the show command output.