Skip to content

Commit f986e24

Browse files
feat(netbird): add Gateway API support and reject ingressGrpc without TLS (#74) (#80)
* feat(netbird): add Gateway API support and reject ingressGrpc without TLS Adds HTTPRoute/GRPCRoute/TCPRoute as mutually-exclusive alternatives to each existing Ingress block (server.httpRoute, server.grpcRoute, server.relayHttpRoute, server.relayTcpRoute, dashboard.httpRoute). The chart renders routes only and attaches them via parentRefs to a user-managed Gateway. Omitted backendRefs auto-fill to the netbird Service on port 80. Fail-fast helm-template validation covers: * Ingress + Gateway route both enabled for the same traffic class * relayHttpRoute and relayTcpRoute both enabled * Route enabled with empty parentRefs * ingressGrpc enabled with empty tls — gRPC over nginx-ingress cannot negotiate h2c, and the default ssl-redirect annotation redirects plaintext gRPC to HTTPS, so this silently failed before Fixes #74 by giving users a plaintext-h2c path (grpcRoute) for gRPC and rejecting the silent-failure Ingress configuration. Includes 36 new helm-unittest cases and an Envoy-Gateway-based e2e test harness (ci/scripts/netbird/e2e-gateway.sh + CI job) that verifies routes reach Accepted=True on the gateway and that backendRefs auto-fill. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(netbird): dprint-format README and values.yaml Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(netbird): let Envoy Gateway install Gateway API CRDs Installing standard-install.yaml with kubectl then running the envoy-gateway Helm chart caused server-side-apply conflicts: EG owns the same CRDs via its packaged manifests but our prior kubectl-apply set "kubectl-client-side-apply" as the field manager. The EG chart bundles both standard and experimental channel CRDs (including TCPRoute), so a single install is enough. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(netbird): wait for Gateway Accepted, preserve state for debug on fail Gateway Programmed condition requires Envoy's data-plane pod to be Ready, which is too slow on kind within the 3m timeout. Route attachment only needs the Gateway to be Accepted (admission by the controller), so wait on that instead — routes progress independently of proxy readiness. Also skip the cleanup trap on non-zero exit so CI's "Show debug info on failure" step can actually see pod status / events / logs — previously the namespace was deleted before debug ran. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 93eda38 commit f986e24

20 files changed

Lines changed: 1263 additions & 37 deletions

.github/workflows/ci.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,44 @@ jobs:
210210
echo "=== Events ==="
211211
kubectl -n netbird-e2e get events --sort-by='.lastTimestamp' || true
212212
213+
e2e-gateway:
214+
name: "E2E — NetBird: Gateway API (Envoy Gateway)"
215+
runs-on: ubuntu-latest
216+
needs: [detect-changes, lint-and-unit-test]
217+
if: needs.detect-changes.outputs.netbird == 'true' || needs.detect-changes.outputs.ci == 'true'
218+
steps:
219+
- name: Checkout
220+
uses: actions/checkout@v4
221+
222+
- name: Set up Helm
223+
uses: azure/setup-helm@v4
224+
with:
225+
version: v4.0.2
226+
227+
- name: Create kind cluster
228+
uses: helm/kind-action@v1
229+
with:
230+
cluster_name: helms-e2e
231+
232+
- name: Run e2e test (gateway)
233+
run: ci/scripts/netbird/e2e-gateway.sh
234+
235+
- name: Show debug info on failure
236+
if: failure()
237+
run: |
238+
echo "=== Pod status ==="
239+
kubectl -n netbird-gateway-e2e get pods -o wide || true
240+
echo "=== Gateway status ==="
241+
kubectl -n netbird-gateway-e2e get gateway netbird-gateway -o yaml || true
242+
echo "=== Route statuses ==="
243+
kubectl -n netbird-gateway-e2e get httproute,grpcroute -o yaml || true
244+
echo "=== Envoy Gateway logs ==="
245+
kubectl -n envoy-gateway-system logs deployment/envoy-gateway --tail=100 || true
246+
echo "=== Server logs ==="
247+
kubectl -n netbird-gateway-e2e logs deployment/netbird-gateway-e2e-server --all-containers --tail=100 || true
248+
echo "=== Events ==="
249+
kubectl -n netbird-gateway-e2e get events --sort-by='.lastTimestamp' || true
250+
213251
e2e-oidc-embedded:
214252
name: "E2E — NetBird: OIDC (Embedded IdP)"
215253
runs-on: ubuntu-latest

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1616
`https://netbird.example.com`). NetBird clients require the port — without
1717
it the daemon fails with `missing port in address`. Use
1818
`https://netbird.example.com:443` instead. Fixes #75.
19+
- **netbird**: Gateway API support as a mutually-exclusive alternative to
20+
Kubernetes Ingress for every traffic class. New values:
21+
`server.httpRoute` (`HTTPRoute`), `server.grpcRoute` (`GRPCRoute`),
22+
`server.relayHttpRoute` (`HTTPRoute`), `server.relayTcpRoute`
23+
(`TCPRoute`, v1alpha2), and `dashboard.httpRoute` (`HTTPRoute`). The
24+
chart renders routes only; users provide `parentRefs` to a Gateway they
25+
already manage. Omitted `backendRefs` auto-fill to the netbird
26+
server / dashboard Service on port 80. Fixes #74 — controllers that
27+
support plaintext h2c (Envoy Gateway, Traefik Gateway, …) can now expose
28+
gRPC without TLS via `GRPCRoute`, sidestepping the nginx-ingress h2c
29+
limitation that made `server.ingressGrpc` fail silently without a cert.
30+
- **netbird**: Fail-fast validation that rejects enabling both an Ingress
31+
and its Gateway-API counterpart for the same traffic class (and between
32+
`server.relayHttpRoute` / `server.relayTcpRoute`), or enabling a route
33+
with an empty `parentRefs` list.
34+
- **netbird**: Fail-fast validation that rejects
35+
`server.ingressGrpc.enabled=true` with an empty `server.ingressGrpc.tls`
36+
list. gRPC over Kubernetes Ingress requires TLS (nginx-ingress cannot
37+
negotiate plaintext h2c, and the default `ssl-redirect: "true"`
38+
annotation redirects plaintext gRPC to HTTPS) — previously this
39+
misconfiguration failed silently. Fixes #74. Users who want plaintext
40+
gRPC should use `server.grpcRoute` with a Gateway API controller that
41+
supports h2c.
1942

2043
### Changed
2144

@@ -24,6 +47,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
2447
- **netbird**: README and `values.yaml` examples now show
2548
`exposedAddress` with an explicit `:443` port and document that the
2649
port is required even when it matches the scheme default.
50+
- **netbird**: README gains a "Gateway API as an alternative to Ingress"
51+
section with copy-pasteable examples, parameter tables for the new
52+
route blocks, and an updated architecture diagram.
2753

2854
## [0.4.1] — 2026-04-14
2955

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: lint unittest e2e e2e-netbird e2e-sqlite e2e-postgres e2e-mysql e2e-oidc-keycloak e2e-oidc-zitadel e2e-keycloak e2e-keycloak-dev e2e-keycloak-postgres e2e-keycloak-replicas e2e-setup e2e-teardown test compat-matrix
1+
.PHONY: lint unittest e2e e2e-netbird e2e-sqlite e2e-postgres e2e-mysql e2e-gateway e2e-oidc-keycloak e2e-oidc-zitadel e2e-keycloak e2e-keycloak-dev e2e-keycloak-postgres e2e-keycloak-replicas e2e-setup e2e-teardown test compat-matrix
22

33
CHARTS := $(wildcard charts/*)
44

@@ -36,6 +36,9 @@ e2e-postgres: e2e-setup
3636
e2e-mysql: e2e-setup
3737
ci/scripts/netbird/e2e.sh mysql
3838

39+
e2e-gateway: e2e-setup
40+
ci/scripts/netbird/e2e-gateway.sh
41+
3942
e2e-oidc-keycloak: e2e-setup
4043
ci/scripts/netbird/e2e-oidc.sh keycloak
4144

@@ -46,6 +49,7 @@ e2e-netbird: e2e-setup
4649
ci/scripts/netbird/e2e.sh sqlite
4750
ci/scripts/netbird/e2e.sh postgres
4851
ci/scripts/netbird/e2e.sh mysql
52+
ci/scripts/netbird/e2e-gateway.sh
4953
ci/scripts/netbird/e2e-oidc.sh keycloak
5054
ci/scripts/netbird/e2e-oidc.sh zitadel
5155

0 commit comments

Comments
 (0)