Skip to main content

Containerlab

This page covers the optional containerlab integration: what runs, which PEs are substituted, how to deploy, and known limitations.


Overview

The containerlab artifact (clab-mpls-topology) is generated from Infrahub data by the clab_topology transform and renders a valid containerlab YAML topology. It wires up the lab-deployable PE nodes plus the L3VPN CE nodes for end-to-end testing. The backbone links are data-driven — derived from the shared /31 addressing rather than fixed in the template — so the lab tracks whatever backbone the active dataset defines.

Which PEs are deployable depends on the dataset:

  • financial (default) — all 8 PEs are Arista cEOS, so all 8 boot in the lab and all 15 backbone links render, plus the 4 cEOS CE routers and their PE-CE access links.
  • isp — only the Arista and Nokia PEs have a lab-runnable image, so 2 PE nodes boot with the single backbone link between them.

The topology is written to lab/mpls-backbone.clab.yml by invoke lab.deploy before containerlab brings it up.


Node map

A device is lab-deployable only when its platform carries a containerlab_os image. Today that means two vendors:

VendorPlatformContainerlab imageNotes
Arista EOSarista_eosceos-image (see Architecture)Full configuration push via invoke lab.push-arista
Nokia SR OSnokia_srosSR Linux (ghcr.io/nokia/srlinux)SR Linux used in place of SR OS (see below)
Cisco IOS-XRcisco_iosxrNo lab image — omitted from the topology
Juniper Junosjuniper_junosNo lab image — omitted from the topology

Which PEs that yields depends on the active dataset:

  • financial (default) — all 8 PEs (pe-01pe-08) are Arista cEOS, so all 8 boot in the lab and all 15 backbone links render.
  • isp — only pe-lon-arista (cEOS) and pe-par-nokia (SR Linux) are deployable; pe-fra-cisco and pe-ams-juniper are omitted.
MPLS data plane

The lab brings up IS-IS, the full iBGP mesh and PE-CE eBGP, and every customer prefix lands in the right VRF. It does not forward traffic between customer sites: cEOS never starts its LDP agent, so there is no MPLS label path between PEs. See Troubleshooting.

CE nodes are real routers, not stand-ins. On financial the four pre-provisioned CEs are Arista cEOS and boot from their own ce-arista-eos configuration artifact, so the PE-CE eBGP session establishes in the lab. A site whose CE is unmanaged (no ce_device), or whose L3VPN generator has not run yet, contributes no CE node and no PE-CE link.

Behind each CE the topology also synthesises one customer host — a nicolaka/netshoot container named cust-<site> (for example cust-ib-zrh behind ce-ib-zrh). It is lab scaffolding, not Infrahub data: it exists so the LAN port on the CE has carrier. Without it the port stays down, the dot1q sub-interface sits lowerlayerdown, and the customer prefix is never advertised because a down interface contributes no connected route for the BGP network statement to match. Each host tags its own frames with the same VLAN the CE expects and takes .10 of the customer subnet, with the CE sub-interface .1 as its default gateway — so the encapsulation is exercised, and the host is a usable ping source across the VPN.


SR OS → SR Linux substitution

This applies only when the active backbone includes a Nokia PE — i.e. the isp dataset. The default financial backbone is all-Arista, so no substitution happens there.

Nokia's containerlab-friendly image is SR Linux, not SR OS. SR OS is available only with a paid Nokia licence and is not suitable for a public demo. The demo uses SR Linux as a stand-in for the Nokia PE. The Infrahub data model remains nokia_sros for schema consistency; the containerlab artifact swaps in the SR Linux image automatically.

The SR Linux node boots with the generated Nokia SR OS configuration loaded as a startup configuration, but SR Linux does not parse SR OS CLI syntax. Configuration push to the Nokia PE is therefore not available in v1 (see Known gaps).


Prerequisites

Host

containerlab drives the host kernel directly (network namespaces, veth pairs, bridges), so the lab needs a Linux host. On macOS or Windows, run it inside a Linux VM — OrbStack, Lima, UTM or a cloud instance — not against Docker Desktop from the host side.

The financial dataset is the demanding one: 12 Arista cEOS routers and 4 customer hosts, alongside the Infrahub stack itself.

Resourcefinancial (default)isp
Lab containers16 (12 cEOS + 4 hosts)2 (1 cEOS + 1 SR Linux)
RAM for the lab~24 GB (cEOS wants ~2 GB/node)~4 GB
RAM including the Infrahub stack32 GB or more~16 GB
vCPU8+ recommended4

A host with less RAM than that does not fail cleanly — cEOS nodes thrash or get OOM-killed and the deploy stalls in postdeploy. If you have less, use the isp dataset, or run the Infrahub side only: everything except invoke lab.deploy works on a modest machine.

Architecture

The lab needs an x86_64 host. Apple Silicon cannot run it.

Every cEOS-lab build Arista publishes has a 32-bit x86 userland — SWI_ARCH=i686 in the image's /etc/swi-version, amd64 tags included. Rosetta 2 does not translate 32-bit x86 at all, so the only thing left to execute it on Apple Silicon is qemu-i386 user-mode emulation. Under emulation EOS gets as far as agentsToStart=[...], loops on ProcMgr.service, and systemd eventually gives up: the container exits 255 about 17 minutes in, with nothing naming the cause. There is no arm64 cEOS-lab tag to substitute — a tag whose registry metadata claims arm64 is a mislabelled x86 image, not an ARM build.

invoke lab.deploy therefore refuses 64-bit ARM hosts outright, in under a second, rather than letting twelve routers die one at a time:

✗ cEOS-lab cannot run on this host (arm64).

Set LAB_ALLOW_UNSUPPORTED_ARCH=true to attempt it anyway.

Host uname -mcEOS image
x86_64registry.opsmill.io/external/ceos-image:4.36.0.1F
aarch64 / arm64unsupported — lab.deploy refuses

The rendered topology reads ${CEOS_IMAGE:=<default>}, so a different build can be pinned with CEOS_IMAGE without re-rendering the artifact.

On an Apple Silicon machine everything except invoke lab.deploy works unchanged — schemas, generators, transforms, checks, artifact rendering and the service catalog. Only the containerlab side needs an x86_64 host.

SR Linux is the exception: ghcr.io/nokia/srlinux:26.7.1-554 is a genuine multi-arch image and boots natively on ARM. That only covers the single srl node in the isp dataset; the financial dataset is all cEOS.

Do not pin a cEOS-lab image older than 4.32.0F. Earlier builds require a cgroups v1 host and never finish booting on a cgroups v2 one — the default on Ubuntu 21.04+, OrbStack and most current distributions — and the failure is silent. See Troubleshooting.

Software

  • containerlab >= 0.50
  • Docker, with network access to pull:
    • registry.opsmill.io/external/ceos-image (public mirror — no Arista account or manual import needed)
    • ghcr.io/nokia/srlinux (isp dataset only)
    • nicolaka/netshoot (the cust-* customer hosts on the CE LAN side)
  • A running Infrahub instance with bootstrap data loaded (invoke init)

Deploy

# Fetch the clab artifact from Infrahub and write lab/mpls-backbone.clab.yml,
# then call containerlab deploy.
uv run invoke lab.deploy

Expected output (default financial dataset — 8 Arista cEOS PEs, the four pre-provisioned Arista cEOS CE routers, and one customer host behind each CE):

[INFO] Fetching clab-mpls-topology artifact from Infrahub...
[INFO] Writing lab/mpls-backbone.clab.yml
[INFO] Running: containerlab deploy -t lab/mpls-backbone.clab.yml
...
+----+---------------------------------+-----------+---------------------------------+
| # | Name | Kind | Image |
+----+---------------------------------+-----------+---------------------------------+
| 1 | pe-01 | ceos | ceos-image:4.36.0.1F |
| 2 | pe-02 | ceos | ceos-image:4.36.0.1F |
| 3 | pe-03 | ceos | ceos-image:4.36.0.1F |
| 4 | pe-04 | ceos | ceos-image:4.36.0.1F |
| 5 | pe-05 | ceos | ceos-image:4.36.0.1F |
| 6 | pe-06 | ceos | ceos-image:4.36.0.1F |
| 7 | pe-07 | ceos | ceos-image:4.36.0.1F |
| 8 | pe-08 | ceos | ceos-image:4.36.0.1F |
| 9 | ce-ib-lon | ceos | ceos-image:4.36.0.1F |
| 10 | ce-ib-zrh | ceos | ceos-image:4.36.0.1F |
| 11 | ce-trading-lon | ceos | ceos-image:4.36.0.1F |
| 12 | ce-trading-zrh | ceos | ceos-image:4.36.0.1F |
| 13 | cust-ib-lon | linux | nicolaka/netshoot:latest |
| 14 | cust-ib-zrh | linux | nicolaka/netshoot:latest |
| 15 | cust-trading-lon | linux | nicolaka/netshoot:latest |
| 16 | cust-trading-zrh | linux | nicolaka/netshoot:latest |
+----+---------------------------------+-----------+---------------------------------+

On the isp dataset the same command brings up just pe-lon-arista (Arista cEOS) and pe-par-nokia (Nokia SR Linux), with the single backbone link between them. That dataset defines no CE routers, and a site without a ce_device contributes no CE node and no PE-CE link, so the isp lab exercises the backbone only — use the financial dataset for the PE-CE story.


Push Arista configuration

After the lab is up, push the Arista EOS configuration artifact from Infrahub:

uv run invoke lab.push-arista

This pushes the per-device configs that invoke lab.deploy already wrote to lab/devices/<node>.cfg, applying each over the containerlab management network via eAPI. It does not re-fetch them, so if you changed a template since the last deploy, re-run invoke lab.deploy (or scripts/fetch_lab_configs.py) first — otherwise the previous render is what reaches the device. On the default financial backbone every PE is Arista (pe-01pe-08) plus the four CEs; on the isp dataset it is the single pe-lon-arista node.

The command shows a diff of what changed. Verify with (financial default — substitute pe-lon-arista on the isp dataset):

containerlab exec -t lab/mpls-backbone.clab.yml --label clab-node-name=pe-01 \
--cmd "Cli -p 15 -c 'show ip bgp summary vrf all'"

containerlab exec runs its --cmd in the container, not in the EOS CLI, so the Cli -p 15 -c '…' wrapper is what gets an EOS command executed; without it the node answers executable file not found in $PATH. show ip bgp summary vrf all covers both the iBGP mesh in the default VRF and each PE-CE session in its customer VRF. Expect seven Estab neighbours in VRF default on every PE, plus one per L3VPN site on pe-01 and pe-08.

Note that the VPNv4 address family has no show command on the pinned cEOS 4.29 image — show bgp vpn-ipv4 summary returns % Not supported. That is a CLI gap, not a signalling failure: the sessions carry the address family, and show ip route vrf <name> on a hub PE lists the customer prefix learned from its CE.


Destroy

uv run invoke lab.destroy

This calls containerlab destroy on the generated topology. The topology file itself is left in place — invoke lab.status and invoke lab.destroy both read it, so removing it would strand the lab. invoke lab.deploy overwrites it from Infrahub on the next run.


Lab status

uv run invoke lab.status

Shows container health without modifying anything.


Login credentials

containerlab registers each node in its embedded DNS as clab-<lab-name>-<node-name>. For the bundled MPLS backbone the lab name is mpls-backbone-1, so on the default financial dataset the Arista PEs are at clab-mpls-backbone-1-pe-01clab-mpls-backbone-1-pe-08. On the isp dataset the Arista PE is clab-mpls-backbone-1-pe-lon-arista and the Nokia PE is clab-mpls-backbone-1-pe-par-nokia.

NodeImageUserPasswordNotes
Arista PE (pe-01pe-08 on financial, pe-lon-arista on isp)Arista cEOSadminadmincontainerlab's cEOS default, demo-only
Arista CE (ce-trading-lon, ce-trading-zrh, ce-ib-lon, ce-ib-zrh) — financial onlyArista cEOSadminadminSame containerlab default, demo-only
pe-par-nokia (CLI) — isp onlyNokia SR LinuxadminNokiaSrl1!SR Linux 22.11+ vendor default
pe-par-nokia (shell) — isp onlyNokia SR LinuxlinuxadminNokiaSrl1!Shell access, same default
Customer host (cust-trading-lon, cust-trading-zrh, cust-ib-lon, cust-ib-zrh) — financial onlynicolaka/netshootroot(none)Plain Linux container, docker exec only

To reach the CLIs:

# Arista — via SSH or docker exec (financial default; use pe-lon-arista on isp)
ssh admin@clab-mpls-backbone-1-pe-01
docker exec -it clab-mpls-backbone-1-pe-01 Cli

# Nokia SR Linux (isp dataset only)
ssh admin@clab-mpls-backbone-1-pe-par-nokia
docker exec -it clab-mpls-backbone-1-pe-par-nokia sr_cli

# CE router (financial default) — same cEOS CLI as the PEs
ssh admin@clab-mpls-backbone-1-ce-trading-lon
docker exec -it clab-mpls-backbone-1-ce-trading-lon Cli

# Customer host behind a CE (financial default) — plain shell, no SSH
docker exec -it clab-mpls-backbone-1-cust-trading-lon bash

The cEOS password (admin) is set by the startup-configuration we render — specifically the username admin privilege 15 role network-admin secret 0 admin line in templates/pe_arista_eos.j2. It's demo-only; if you ever publish from this template to real Arista hardware, swap the secret or gate the line behind a flag.

The Nokia password is the SR Linux 22.11+ default. Older SR Linux releases used admin as the password — adjust if you've pinned a different image tag in templates/clab_topology.j2.


Known gaps

GapDetails
Nokia SR Linux configuration pushSR Linux uses a different CLI/API from SR OS, and the public SR Linux 23.10 image lacks several constructs SR OS supports (LDP, l3vpn-ipv4-unicast afi-safi, bgp-vpn under network-instance). The dedicated pe-nokia-srlinux artifact intentionally renders a lab-minimum configuration — hostname + interfaces + ISIS underlay only. BGP and per-VPN ip-vrf signalling are skipped on the SRL lab node. The production-quality configuration lives in the pe-nokia-sros artifact (real SR OS syntax) and is meant for a real Nokia box.
Cisco / Juniper PEsIOS-XR and Junos container images require vendor licences; these PEs are absent from the v1 lab topology.
Inter-site VPN forwardingPE-CE eBGP establishes and every customer prefix reaches the right VRF, but cEOS never starts its LDP agent, so there is no MPLS label path between PEs and traffic does not cross the backbone. See Troubleshooting.
Unmanaged CEsOnly sites with a ce_device get a lab CE. On the isp dataset no site names one, so that lab has no CE nodes, no PE-CE links, and no customer hosts.

Image pull failures

If containerlab fails with Error response from daemon: pull access denied:

  1. SR Linux (ghcr.io/nokia/srlinux) — requires a GitHub login: docker login ghcr.io -u <github-user> -p <PAT>

  2. cEOS — the OpsMill mirror (registry.opsmill.io/external/ceos-image) is public and needs no login, so a pull failure here is usually a tag that does not exist rather than an access problem. Note that the mirror's registry metadata is not a reliable guide to architecture: at least one tag declares arm64 while carrying an x86 image, and pulling it on Apple Silicon succeeds and then fails to boot. Check what you asked for:

    uname -m
    echo "${CEOS_IMAGE:-<unset, template default applies>}"

    To use your own Arista-supplied build instead, import it and point CEOS_IMAGE at it:

    docker import cEOS-lab-4.36.0F.tar.xz ceos:local
    CEOS_IMAGE=ceos:local uv run invoke lab.deploy
  3. netshoot (nicolaka/netshoot) — public image used by the cust-* customer hosts; if it fails, check Docker Hub rate limits or mirror it via a local registry.

The CE routers use the same cEOS image as the PEs, so one image covers both.