README
ΒΆ
k8s-netbox-controller
A Kubernetes controller that automatically assigns IP addresses from NetBox to LoadBalancer type Services.
Overview
k8s-netbox-controller watches for Kubernetes Service resources of type LoadBalancer and automatically allocates IP addresses from NetBox IP Address Management (IPAM) system. When a Service is created with the appropriate annotations, the controller:
- π Queries NetBox for the next available IP from a specified subnet
- π Assigns the IP to the Service's
spec.loadBalancerIPfield - π§Ή Automatically releases the IP from NetBox when the Service is deleted
This enables seamless integration between Kubernetes and NetBox for IP address lifecycle management, particularly useful in on-premises or bare-metal Kubernetes deployments.
Features
- β Automatic IP allocation from NetBox prefixes (subnets)
- β VRF support for multi-tenant environments
- β Automatic cleanup using Kubernetes finalizers
- β Opt-in behavior via annotations (doesn't affect all Services)
- β Idempotent reconciliation (safe to run multiple times)
- β Comprehensive logging with structured logs
- β Metrics endpoint for monitoring
Prerequisites
- Kubernetes: v1.32.x - v1.35.x+ (compatibility matrix)
- NetBox: v3.5+ or v4.0+ with API access
- kubectl: v1.32+
- Go: v1.25+ (for building from source)
- Docker/Podman: For building container images
Quick Start
1. Deploy the Controller
Option A: Using Helm (Recommended)
# Install the chart from GitHub Container Registry
helm install k8s-netbox-controller \
oci://ghcr.io/ascalotoru/charts/k8s-netbox-controller \
--version 0.1.0 \
--namespace k8s-netbox-controller-system \
--create-namespace \
--set netbox.url=https://netbox.example.com \
--set netbox.token=your-netbox-api-token
Option B: Using kubectl with pre-built manifest
kubectl apply -f https://raw.githubusercontent.com/ascalotoru/k8s-netbox-controller/main/dist/install.yaml
Then configure NetBox credentials:
kubectl create secret generic netbox-credentials \
--namespace k8s-netbox-controller-system \
--from-literal=NETBOX_URL=https://netbox.example.com \
--from-literal=NETBOX_TOKEN=your-netbox-api-token
kubectl patch deployment k8s-netbox-controller-controller-manager \
-n k8s-netbox-controller-system \
--type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/containers/0/envFrom", "value": [{"secretRef": {"name": "netbox-credentials"}}]}]'
Option C: Using Kustomize
# Clone the repository
git clone https://github.com/ascalotoru/k8s-netbox-controller.git
cd k8s-netbox-controller
# Build and deploy
export IMG=ghcr.io/ascalotoru/k8s-netbox-controller:latest
make deploy IMG=$IMG
2. Verify Installation
2. Verify Installation
Check that the controller is running:
kubectl get pods -n k8s-netbox-controller-system
3. Create a LoadBalancer Service
Apply a Service with NetBox annotations:
apiVersion: v1
kind: Service
metadata:
name: my-application
annotations:
netbox-controller.ascalotoru.io/netbox-sync: "true"
netbox-controller.ascalotoru.io/subnet: "192.168.1.0/24"
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
The controller will automatically assign an IP from NetBox:
kubectl get svc my-application
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# my-application LoadBalancer 10.96.123.45 192.168.1.100 80:31234/TCP
Configuration
Annotations
| Annotation | Required | Description | Example |
|---|---|---|---|
netbox-controller.ascalotoru.io/netbox-sync |
Yes | Enable NetBox IP allocation | "true" |
netbox-controller.ascalotoru.io/subnet |
Yes | NetBox prefix (CIDR) to allocate from | "192.168.1.0/24" |
netbox-controller.ascalotoru.io/vrf-name |
No | VRF name (if using VRFs) | "production" |
Environment Variables
The controller requires these environment variables (typically set via Secret):
| Variable | Required | Description |
|---|---|---|
NETBOX_URL |
Yes | NetBox API base URL |
NETBOX_TOKEN |
Yes | NetBox API authentication token |
Helm Chart Values
Key Helm values you can configure:
| Parameter | Description | Default |
|---|---|---|
netbox.url |
NetBox API URL | "" |
netbox.token |
NetBox API token | "" |
netbox.existingSecret |
Use existing secret for credentials | "" |
replicaCount |
Number of controller replicas | 1 |
image.repository |
Controller image repository | ghcr.io/ascalotoru/k8s-netbox-controller |
image.tag |
Controller image tag | Chart's appVersion |
resources.limits.memory |
Memory limit | 128Mi |
resources.requests.cpu |
CPU request | 10m |
leaderElection.enabled |
Enable leader election (for HA) | false |
See charts/k8s-netbox-controller/values.yaml for all available options.
Examples
See the examples/ directory for complete examples:
- loadbalancer-service.yaml - Basic LoadBalancer Service
With VRF Support
apiVersion: v1
kind: Service
metadata:
name: production-service
annotations:
netbox-controller.ascalotoru.io/netbox-sync: "true"
netbox-controller.ascalotoru.io/subnet: "10.100.0.0/24"
netbox-controller.ascalotoru.io/vrf-name: "production"
spec:
type: LoadBalancer
selector:
app: prod-app
ports:
- port: 443
targetPort: 8443
Kubernetes Compatibility
This controller uses Kubernetes client libraries v0.34.x and is compatible with:
| Kubernetes Version | Support Status |
|---|---|
| 1.32.x | β Compatible |
| 1.33.x | β Officially Supported |
| 1.34.x | β Tested |
| 1.35.x+ | β Expected to work |
Following Kubernetes version skew policy, the controller maintains compatibility with Β±1 minor version from the client library version.
Development
Local Development
# Clone the repository
git clone https://github.com/ascalotoru/k8s-netbox-controller.git
cd k8s-netbox-controller
# Install dependencies
go mod download
# Run tests
make test
# Run locally (requires kubeconfig)
export NETBOX_URL=http://localhost:8000
export NETBOX_TOKEN=your-dev-token
make run
Building
# Build the binary
make build
# Build Docker image
make docker-build IMG=your-registry/k8s-netbox-controller:dev
# Run linting
make lint
Testing
# Unit tests
make test
# E2E tests (requires Kind)
make test-e2e
# Check coverage
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out
Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Kubernetes Cluster β
β ββββββββββββββββ ββββββββββββββββββββββββββββ β
β β Service β watches β k8s-netbox-controller β β
β β (LoadBalancer)ββββββββββΆβ - ServiceReconciler β β
β β β β - NetBox Client β β
β ββββββββββββββββ ββββββββββββ¬ββββββββββββββββ β
β β API Calls β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββ
β NetBox β
β IPAM System β
βββββββββββββββββββ
How it works:
- Controller watches for
Serviceresources with annotationnetbox-sync: "true" - When a LoadBalancer Service is created without an IP:
- Queries NetBox API for next available IP in specified subnet
- Updates Service
spec.loadBalancerIPwith allocated IP - Adds finalizer for cleanup tracking
- When Service is deleted:
- Finalizer triggers cleanup
- Releases IP back to NetBox
- Removes finalizer
Troubleshooting
Controller logs
kubectl logs -n k8s-netbox-controller-system \\
deployment/k8s-netbox-controller-controller-manager \\
-c manager -f
Common Issues
Service IP not assigned:
- Check controller logs for errors
- Verify NetBox URL and token are correct
- Ensure the subnet exists in NetBox
- Verify subnet has available IPs
IP not released on deletion:
- Check if finalizer is present:
kubectl get svc <name> -o yaml | grep finalizers - Review controller logs during Service deletion
Permission errors:
- Ensure RBAC manifests are applied:
make install - Verify ServiceAccount has proper permissions
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Code Guidelines
- Follow Go best practices and formatting (
make fmt) - Add tests for new features
- Update documentation as needed
- Run linter before submitting (
make lint-fix)
Roadmap
- Support for IP allocation on Service update
- Configurable IP description templates
- Webhook for validation
- Helm chart distribution
- Metrics dashboard examples
- Multi-IP support for Services
Acknowledgments
Built with Kubebuilder and inspired by the need for better IP address management in bare-metal Kubernetes environments.
Support
- π Documentation
- π Issue Tracker
- π¬ Discussions
Related Projects
- NetBox - IP address management (IPAM) and data center infrastructure management (DCIM) tool
- MetalLB - Load balancer implementation for bare metal Kubernetes
- Kubebuilder - SDK for building Kubernetes APIs
NOTE: Run make help for more information on all available make targets.
More information can be found via the Kubebuilder Documentation
License
Copyright 2026.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.