KroderDev/kube-edge-router
Kubernetes Operator that exposes LoadBalancer services through remote Edge VPS nodes with public IPv4 addresses via WireGuard tunnels and nftables DNAT rules.
Kube Edge Router
A Kubernetes Operator that exposes LoadBalancer services through remote Edge VPS nodes with public IPv4 addresses.
Overview
kube-edge-router bridges internal Kubernetes services to the public internet through edge nodes connected via WireGuard tunnels. It automates the management of nftables forwarding rules on edge VPS nodes.
flowchart TB
subgraph Internet
User([User])
end
subgraph Edge["Edge VPS (edge-us-east-01)"]
PIP[Public IP<br/>203.0.113.10]
NFT[nftables<br/>DNAT]
WG1[WireGuard<br/>wg0]
end
subgraph Core["Core Cluster"]
Controller[kube-edge-router<br/>Controller]
EN[EdgeNode CRD]
SVC[Service<br/>type: LoadBalancer]
MLB[MetalLB<br/>172.16.10.200]
end
User -->|:25565| PIP
PIP --> NFT
NFT --> WG1
WG1 -->|WireGuard Tunnel| MLB
MLB --> SVC
Controller -->|SSH| NFT
Controller --> EN
Controller -->|Watch| SVCReconciliation Flow
sequenceDiagram
participant S as Service
participant C as Controller
participant EN as EdgeNode
participant E as Edge VPS
S->>C: Create Service (LoadBalancer)
C->>EN: Find available Public IP
EN-->>C: 203.0.113.10 available
C->>E: SSH: Apply nftables DNAT
E-->>C: Rules applied
C->>EN: Mark IP as allocated
C->>S: Patch status.loadBalancer.ingressFeatures
- ๐ Multi-Edge Support: Manage multiple edge VPS nodes with different public IP pools
- ๐ Zero-Trust Edge: Control plane pushes config; edge nodes are stateless gateways
- ๐ Automatic Reconciliation: Watches LoadBalancer services and syncs rules
- ๐ฆ CRD-Based:
EdgeNodecustom resource for declarative edge management
Prerequisites
The Edge Node VPS must be provisioned with the following:
- OS: Linux (Debian 12+ recommended)
- Networking:
nftables(enabled),WireGuard - Firewall: UFW MUST BE DISABLED. The controller manages
nftablesdirectly. - Kernel: Forwarding enabled (
net.ipv4.ip_forward=1) - SSH: Key-based access for the controller.
Installation
# Install CRDs
kubectl apply -f config/crd/bases/
# Deploy controller
kubectl apply -k config/default/Usage
1. Create an EdgeNode
apiVersion: networking.edge-router.io/v1alpha1
kind: EdgeNode
metadata:
name: edge-us-east-01
spec:
managementIP: "10.10.0.2" # WireGuard IP
sshSecretRef: "edge-ssh-key" # Secret with SSH private key
publicIPs:
- address: "203.0.113.10"
interface: "enp1s0"2. Annotate a Service
apiVersion: v1
kind: Service
metadata:
name: my-app
annotations:
edge-router.io/edge-routed: "true"
spec:
type: LoadBalancer
ports:
- port: 80803. Annotate a Namespace (Recommended for vClusters)
To expose ALL LoadBalancer services within a namespace automatically:
apiVersion: v1
kind: Namespace
metadata:
name: tenant-a
annotations:
edge-router.io/edge-routed: "true"The controller will:
- Detect the internal VIP assigned by MetalLB
- Allocate an available public IP from an EdgeNode
- SSH to the edge and apply nftables rules
- Update the Service status with the public IP
Configuration
| Environment Variable | Description | Default |
|---|---|---|
SSH_TIMEOUT |
SSH connection timeout | 10s |
RECONCILE_INTERVAL |
Forced reconcile interval | 5m |
Development
# Prerequisites
go 1.25+
kubebuilder 3.x
# Run locally
make run
# Run tests
make test
# Build image
make docker-build IMG=your-registry/kube-edge-router:tagBuild Process
Build-Time Versioning
The Makefile automatically injects the git version into the binary:
- Release: Uses the git tag (e.g.,
v0.3.2). - Development: Uses the tag + commit hash + dirty status (e.g.,
v0.3.2-4-g9c5a1b-dirty).
To override the version manually:
make build VERSION=custom-v1.0.0Architecture
This project follows Hexagonal Architecture. See AGENTS.md for details.
License
MIT License - see LICENSE for details.