README
¶
HTTPRoute Controller
Kubernetes controller that automatically generates Gateway API HTTPRoutes from Service annotations.
Overview
Convenience controller for creating HTTPRoutes. Watches Services with specific annotations and auto-generates HTTPRoute + ReferenceGrant resources, eliminating manual YAML creation for each exposed service.
Built with:
- Kubebuilder v4.5.1
- Gateway API v1.2.1
- Controller-runtime v0.20.2
Architecture
Controller Name: homelab.local/httproute-controller
Reconciliation:
- Level-based triggers (reconciles full state)
- Idempotent operations
- OwnerReferences for same-namespace resources
- Finalizers for cross-namespace cleanup
Constraints:
- HTTPRoute must be in gateway namespace (Kubernetes blocks cross-namespace OwnerReferences)
- ReferenceGrant must be in service namespace
- HTTPS only (targets gateway
httpssection) - Single service per HTTPRoute (no aggregation)
Features
Annotation-driven automation:
- Watches Services with
gateway.homelab.local/expose: "true" - Auto-generates HTTPRoute + ReferenceGrant from annotations
- No manual resource creation required
Cross-namespace security:
- HTTPRoute deployed in gateway namespace (e.g.,
envoy-gateway-system) - Service remains in application namespace (e.g.,
default) - ReferenceGrant enables secure cross-namespace backend references
- Prevents unauthorized Service access from other namespaces
Lifecycle management:
- Finalizers ensure HTTPRoute cleanup when Service is deleted
- OwnerReferences auto-delete ReferenceGrant with Service
- Removing
expose: "true"triggers resource cleanup - Idempotent reconciliation (safe to run multiple times)
Configuration:
- Gateway name/namespace configurable per Service
- Defaults:
homelab-gatewayinenvoy-gateway-system - Port selection: explicit annotation or first Service port
- HTTPS-only (targets gateway's
httpssection)
Controller Lifecycle
sequenceDiagram
participant User
participant Service
participant Controller
participant GatewayNS as Gateway Namespace
participant ServiceNS as Service Namespace
User->>Service: Add annotations<br/>(expose=true, hostname)
Service->>Controller: Reconcile triggered
Controller->>Controller: Validate annotations
Controller->>GatewayNS: Create/Update HTTPRoute
Note over GatewayNS: HTTPRoute: myapp.homelab.local<br/>Backend: Service in app namespace
Controller->>ServiceNS: Create/Update ReferenceGrant
Note over ServiceNS: Allows HTTPRoute to reference Service
Controller->>Service: Add finalizer
Note over Service: Ensures cleanup on deletion
rect rgba(255, 100, 100, 0.1)
Note over User,ServiceNS: Service Deletion
User->>Service: Delete Service
Service->>Controller: Finalizer triggers cleanup
Controller->>GatewayNS: Delete HTTPRoute
Controller->>ServiceNS: Delete ReferenceGrant<br/>(via OwnerReference)
Controller->>Service: Remove finalizer
Service->>Service: Deletion completes
end
Usage
Annotations
| Annotation | Required | Default | Description |
|---|---|---|---|
gateway.homelab.local/expose |
Yes | - | Set to "true" to enable |
gateway.homelab.local/hostname |
Yes | - | DNS hostname (e.g., myapp.homelab.local) |
gateway.homelab.local/gateway |
No | homelab-gateway |
Gateway name |
gateway.homelab.local/gateway-namespace |
No | envoy-gateway-system |
Gateway namespace |
gateway.homelab.local/port |
No | First port | Service port |
Example
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
annotations:
gateway.homelab.local/expose: "true"
gateway.homelab.local/hostname: "myapp.homelab.local"
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
Controller automatically creates:
-
HTTPRoute (in gateway namespace):
- Name:
default-myapp - Hostname:
myapp.homelab.local - Backend: Service
myappin namespacedefault - Cleanup via Service finalizer (cross-namespace OwnerRefs not supported)
- Name:
-
ReferenceGrant (in service namespace):
- Name:
myapp-backend - Allows HTTPRoute from gateway namespace to reference Service
- OwnerReference to Service (automatic garbage collection)
- Name:
Installation
Using Helm (Recommended)
From Helm repository:
helm repo add httproute-controller https://piotr1215.github.io/httproute-controller
helm repo update
helm install httproute-controller httproute-controller/httproute-controller \
--namespace httproute-system \
--create-namespace
From GitHub release:
# Replace v0.3.5 with the desired version
helm install httproute-controller \
https://github.com/Piotr1215/httproute-controller/releases/download/v0.3.5/httproute-controller-0.3.5.tgz \
--namespace httproute-system \
--create-namespace
From source:
helm install httproute-controller ./helm/httproute-controller \
--namespace httproute-system \
--create-namespace
Using kubectl
kubectl apply -f https://raw.githubusercontent.com/Piotr1215/httproute-controller/main/dist/install.yaml
Development
Prerequisites
- go v1.23.0+
- kubectl v1.11.3+
- Access to a Kubernetes cluster
- Gateway API CRDs installed
Local Development
Install Gateway API CRDs:
make install
Run controller locally:
make run
Run tests:
make test
Build and test in cluster:
# Create KIND cluster
kind create cluster --name httproute-test
# Install Gateway API CRDs
kubectl apply -f config/crd/gateway-api/gateway-api-crds.yaml
# Build image
make docker-build IMG=httproute-controller:local
# Load image to KIND
kind load docker-image httproute-controller:local --name httproute-test
# Deploy controller
make deploy IMG=httproute-controller:local
# Run integration tests
make test-e2e
# Cleanup
kind delete cluster --name httproute-test
Uninstall:
make undeploy
make uninstall
Release
Releases are automated via GitHub Actions. To create a new release:
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
The release pipeline automatically:
- Builds and pushes multi-platform Docker images to
piotrzan/httproute-controller - Packages the Helm chart with correct version metadata
- Generates
install.yamlbundle - Creates GitHub release with artifacts
- Updates Helm repository index on GitHub Pages
Release artifacts:
- Docker image:
piotrzan/httproute-controller:<version> - Helm chart: Available from GitHub releases and Helm repository
- Install bundle:
dist/install.yaml
License
MIT License - see LICENSE file for details.