🚀 Introducing netclab-xp

Declarative Router Configuration with Crossplane


Manage physical, virtual, and containerized routers just like cloud resources — with Kubernetes-native GitOps workflows.

🔧 Why netclab-xp Matters


  • Declarative & GitOps-ready → manage routers like cloud resources
  • OpenConfig foundation → vendor differences handled automatically
  • RESTCONF support → starting with Arista EOS / cEOS
  • Kubernetes-native state → real-time reconciliation vs. Terraform
  • Fast onboarding → add new routers or services easily

⚙️ Abstractions


High-Level Services FabricIP / EvpnService

Mid-Level Router Abstractions Router

Low-Level XRDs Loopback / RoutedInterface / BgpGlobal / BgpNeighbor

RESTCONF Provider provider-http

RoutedInterface

cat <<EOF | kubectl apply -f -
apiVersion: eos.netclab.dev/v1alpha1
kind: RoutedInterface
metadata:
  name: r1e1ip
spec:
  nodePort: ceos01.default.svc.cluster.local:6020
  creds: YXJpc3RhOmFyaXN0YQ==
  name: Ethernet1
  ipv4Address: 10.10.10.1
  ipv4PrefixLength: 24
EOF

Check device

kubectl exec -ti ceos01 -- Cli
ceos01>en
ceos01#show run int Ethernet1
interface Ethernet1
   no switchport
   ip address 10.10.10.1/24

Two routers with BGP

cat <<EOF | kubectl apply -f -
apiVersion: eos.netclab.dev/v1alpha1
kind: Router
metadata:
  name: ceos01
spec:
  nodePort: ceos01.default.svc.cluster.local:6020
  creds: YXJpc3RhOmFyaXN0YQ==
  asn: 65001
  routerId: 10.0.0.1
  routedInterfaces:
  - name: Ethernet1
    ipv4Address: 10.1.2.1
    ipv4PrefixLength: 24
  bgpNeighbors:
  - networkInstance: default
    neighborAsn: 65002
    neighborIp: 10.1.2.2
EOF
cat <<EOF | kubectl apply -f -
apiVersion: eos.netclab.dev/v1alpha1
kind: Router
metadata:
  name: ceos02
spec:
  nodePort: ceos02.default.svc.cluster.local:6020
  creds: YXJpc3RhOmFyaXN0YQ==
  asn: 65002
  routerId: 10.0.0.2
  routedInterfaces:
  - name: Ethernet1
    ipv4Address: 10.1.2.2
    ipv4PrefixLength: 24
  bgpNeighbors:
  - networkInstance: default
    neighborAsn: 65001
    neighborIp: 10.1.2.1
EOF

Check resources

kubectl get routers
NAME     NODE-PORT                               ASN     ROUTER-ID   SYNCED   READY   COMPOSITION              AGE
ceos01   ceos01.default.svc.cluster.local:6020   65001   10.0.0.1    True     True    router.eos.netclab.dev   8m14s
ceos02   ceos02.default.svc.cluster.local:6020   65002   10.0.0.2    True     True    router.eos.netclab.dev   35s

Check BGP on ceos01

kubectl exec ceos01 -- Cli -p15 -c "show ip bgp summary"
BGP summary information for VRF default
Router identifier 10.0.0.1, local AS number 65001
Neighbor Status Codes: m - Under maintenance
  Neighbor V AS           MsgRcvd   MsgSent  InQ OutQ  Up/Down State   PfxRcd PfxAcc PfxAdv
  10.1.2.2 4 65002             12        16    0    0 00:01:11 Estab   0      0      0

Verify more SYNCED and READY

kubectl get netclab
NAME                                            NODE-PORT                               ASN     ROUTER-ID   SYNCED   READY   COMPOSITION                  AGE
bgpglobal.eos.netclab.dev/ceos01-2eedd4b1cab4   ceos01.default.svc.cluster.local:6020   65001   10.0.0.1    True     True    bgpglobals.eos.netclab.dev   3m52s

NAME                                              NODE-PORT                               NI        REMOTE-AS   REMOTE-IP   SYNCED   READY   COMPOSITION                    AGE
bgpneighbor.eos.netclab.dev/ceos01-3e0f1822de8d   ceos01.default.svc.cluster.local:6020   default   65002       10.1.2.2    True     True    bgpneighbors.eos.netclab.dev   3m52s

NAME                                            NODE-PORT                               SYNCED   READY   COMPOSITION                  AGE
iprouting.eos.netclab.dev/ceos01-8c1ecd5acc68   ceos01.default.svc.cluster.local:6020   True     True    iproutings.eos.netclab.dev   3m52s

NAME                                                    NODE-PORT                               NAME        SYNCED   READY   COMPOSITION                          AGE
loopbackinterface.eos.netclab.dev/ceos01-06a18fc6671a   ceos01.default.svc.cluster.local:6020   Loopback0   True     True    loopbackinterfaces.eos.netclab.dev   3m52s

NAME                                                  NODE-PORT                               NAME        IPV4-ADDRESS   IPV4-PREFIX   SYNCED   READY   COMPOSITION                        AGE
routedinterface.eos.netclab.dev/ceos01-95e43dc583a0   ceos01.default.svc.cluster.local:6020   Ethernet1   10.1.2.1       24            True     True    routedinterfaces.eos.netclab.dev   3m52s
routedinterface.eos.netclab.dev/ceos01-e2781936df2b   ceos01.default.svc.cluster.local:6020   Loopback0   10.0.0.1       32            True     True    routedinterfaces.eos.netclab.dev   3m52s

NAME                            NODE-PORT                               ASN     ROUTER-ID   SYNCED   READY   COMPOSITION              AGE
router.eos.netclab.dev/ceos01   ceos01.default.svc.cluster.local:6020   65001   10.0.0.1    True     True    router.eos.netclab.dev   3m52s

🎯 Next Steps

GH Repo:
https://github.com/mbakalarski/netclab-xp

Upbound Marketplace:
https://marketplace.upbound.io/configurations/netclab/netclab-xp

Listed in Crossplane Adopters:
curl -s https://github.com/crossplane/crossplane/blob/main/ADOPTERS.md | grep -o -E 'github.com/[a-z]+/netclab-xp'