krafty is a CNI plugin built for testing and development use only — it is not designed or hardened for production clusters. Its purpose is to make it easy to bring up a local kind cluster with a working secondary network so you can validate CNI behavior without any external infrastructure.
The repo includes make targets to:
- spin up a kind cluster pre-wired with Cilium as the primary CNI, Multus, and krafty as a secondary CNI
- deploy a lightweight pod loaded with IP tooling to verify the second NIC is attached and reachable
krafty runs as a secondary CNI via Multus. For each pod annotated with a NetworkAttachmentDefinition it:
- Creates (idempotently) a Linux VRF and a bridge enslaved to it on the node.
- Allocates a pod IP via
host-localIPAM (or a staticpodIP). - Creates a veth pair — host end attached to the bridge, peer end moved into the pod netns, renamed, and given the pod IP and default route.
Teardown reverses these steps. All operations are idempotent.
- Go 1.22+
- Docker
kind,kubectl,helmgolangci-lint(linttarget only)
make upBuilds the plugin binary, builds the nettools container image, and creates a kind cluster named krafty with:
- Cilium as the primary CNI
- Multus for secondary CNI attachment
- The krafty binary deployed to every node's
/opt/cni/bin - A
NetworkAttachmentDefinition(krafty) applied to thedefaultnamespace
The cluster name and other defaults can be overridden:
make up CLUSTER_NAME=my-lab NETTOOLS_IMAGE=nettools:devmake deploymentApplies resources/nettools.yaml into the cluster — a single-replica Deployment and a Service, both in the default namespace. The pod template carries the Multus annotation k8s.v1.cni.cncf.io/networks: krafty, so every nettools pod receives two interfaces:
| Interface | CNI | Address |
|---|---|---|
eth0 |
Cilium | cluster-assigned |
net1 |
krafty | 172.16.10.x/24 (via host-local IPAM) |
Once the rollout completes, the nettools HTTP service is reachable via port-forward:
kubectl --context kind-krafty port-forward svc/nettools 8080:8080make validateRuns scripts/validate.sh against the live cluster and prints a structured report covering:
- Deployment readiness and pod phase
- Per-interface addresses inside the pod (
eth0andnet1) - VRF device and routing table on the worker node
- Bridge enslaved to the VRF
- Veth pairs wired from the bridge into the pod netns
A summary line at the end reports pass or fail. Validation failure does not abort the shell session — it exits non-zero so CI can catch it while still printing the full report.
make downDeletes the kind cluster and all associated containers, networks, and kubeconfig entries.
All interfaces are named per-pod using the CNI container ID as the uniqueness key. Given a container ID of a3f2b1c4d5e6f7a8...:
| Interface | Name pattern | Example | Scope |
|---|---|---|---|
| VRF | krv + first 12 chars of container ID |
krva3f2b1c4d5e6 |
node |
| Bridge | krb + first 12 chars of container ID |
krba3f2b1c4d5e6 |
node |
| Host veth | veth + first 11 chars of container ID |
vetha3f2b1c4d5e |
node |
| Pod veth | interface name requested by the runtime (typically net1) |
net1 |
pod netns |
The 15-character Linux interface name limit (IFNAMSIZ - 1) is the constraint driving the prefix lengths.
krafty is configured via a NetworkAttachmentDefinition. The cluster created by make up applies this NAD automatically:
{
"cniVersion": "1.0.0",
"name": "krafty",
"type": "krafty",
"subnet": "172.16.10.0/24",
"gateway": "172.16.10.1",
"ipam": {
"type": "host-local",
"ranges": [[{
"subnet": "172.16.10.0/24",
"rangeStart": "172.16.10.10",
"rangeEnd": "172.16.10.250",
"gateway": "172.16.10.1"
}]],
"routes": [{"dst": "0.0.0.0/0"}]
}
}| Field | Required | Description |
|---|---|---|
subnet |
yes | CIDR block for the network |
gateway |
yes | Gateway IP; assigned to the bridge |
ipam |
one of | Standard CNI IPAM block (host-local, etc.) |
podIP |
one of | Static IP when no IPAM block is present |
vrfTable |
no | Linux routing table ID; derived from name via FNV-32a if omitted |
To attach krafty to any pod, add this annotation to the pod template:
annotations:
k8s.v1.cni.cncf.io/networks: kraftyThis project is licensed under the GNU Affero General Public License, version 3 or, at your option, any later version. See LICENSE.