Kubernetes Gateway API Integration Beta
The NetBird Kubernetes operator supports the Gateway API as an alternative to annotation-based service exposure. Using standard Gateway API resources, you can:
- Expose services publicly via reverse proxy using
HTTPRouteresources with the public gateway class - Expose services privately to your NetBird network using
TCPRouteresources with the private gateway class
The operator watches for these Gateway API resources and automatically creates the corresponding Networks and Resources in your NetBird account.
Prerequisites
Before you begin, ensure you have the following:
- Helm version 3+ (recommended)
- kubectl version v1.11.3+
- Access to a Kubernetes v1.11.3+ cluster
- Cert Manager (recommended) — for secure communication between the k8s API and the operator
- A NetBird API token — you can create a PAT by following the steps here
Installation
Step 1: Add the Helm repository
helm repo add netbirdio https://netbirdio.github.io/helms
Step 2: Install Cert Manager
This is recommended for the k8s API to communicate securely with the NetBird operator.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.0/cert-manager.yaml
Step 3: Install the Gateway API CRDs
The operator requires the experimental Gateway API CRDs to be installed in your cluster.
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/experimental-install.yaml
Step 4: Create the NetBird API secret
Create a namespace for the operator and store your API token as a Kubernetes secret.
kubectl create namespace netbird
kubectl -n netbird create secret generic netbird-mgmt-api-key --from-literal=NB_API_KEY=$(cat ~/nb-pat.secret)
Replace ~/nb-pat.secret with the path to your NetBird API key.
Step 5: Install the operator
The operator version 0.3.0-rc.2 is subject to breaking changes. Values and behavior may change in future releases.
helm upgrade --install kubernetes-operator netbirdio/kubernetes-operator \
--namespace netbird \
--create-namespace \
--version 0.3.0-rc.2 \
-f - <<EOF
gatewayAPI:
enabled: true
webhook:
enableCertManager: false
netbirdAPI:
keyFromSecret:
name: "netbird-mgmt-api-key"
key: "NB_API_KEY"
EOF
Step 6: Verify the installation
kubectl -n netbird get pods
# Expected: netbird-operator-kubernetes-operator-xxxxx 1/1 Running
Configure Routing Peers and Gateways
Once the operator is running, deploy the routing peers and gateway resources. The operator supports two gateway classes:
netbird-public— exposes services through a reverse proxy, making them accessible via a public hostname usingHTTPRouteresourcesnetbird-private— exposes services as private network resources, accessible only to peers within your NetBird network usingTCPRouteresources
cat <<EOF | kubectl apply -f -
apiVersion: netbird.io/v1
kind: NBRoutingPeer
metadata:
name: netbird
namespace: netbird
spec: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: private
namespace: netbird
spec:
gatewayClassName: netbird-private
listeners:
- protocol: gateway.netbird.io/NBRoutingPeer
name: netbird
port: 1
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public
namespace: netbird
spec:
gatewayClassName: netbird-public
listeners:
- protocol: gateway.netbird.io/NBRoutingPeer
name: netbird
port: 1
EOF
Expose Services via Reverse Proxy (Public Gateway)
Use HTTPRoute resources with the public gateway to expose Kubernetes services through a reverse proxy. You can optionally add the hostnames field to make the service accessible via a specific domain.
If using a custom hostname, make sure that the domain name is properly configured in your DNS settings.
The following example deploys a demo application and creates an HTTPRoute with a custom hostname pointing to the public gateway:
export DEPLOYMENT_NAME=demo-nb-k8s; export DEPLOYMENT_IMAGE=ghcr.io/netbirdio/kubernetes-demo; cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: $DEPLOYMENT_NAME
namespace: default
labels:
app: $DEPLOYMENT_NAME
spec:
hostnames:
# Optional: omit this field if you don't want to expose this through the reverse proxy
- demo-nb-k8s.eu1.netbird.services
parentRefs:
- name: public
namespace: netbird
rules:
- backendRefs:
- name: $DEPLOYMENT_NAME
port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: $DEPLOYMENT_NAME
namespace: default
labels:
app: $DEPLOYMENT_NAME
spec:
replicas: 1
selector:
matchLabels:
app: $DEPLOYMENT_NAME
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: $DEPLOYMENT_NAME
spec:
containers:
- image: $DEPLOYMENT_IMAGE
imagePullPolicy: Always
name: demo
---
apiVersion: v1
kind: Service
metadata:
name: $DEPLOYMENT_NAME
namespace: default
labels:
app: $DEPLOYMENT_NAME
spec:
type: ClusterIP
selector:
app: $DEPLOYMENT_NAME
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
EOF
Expose Private Resources (Private Gateway)
Use TCPRoute resources with the private gateway to expose services as private network resources, accessible only to peers within your NetBird network.
The following example exposes the Kubernetes API server to your NetBird peers:
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: kubernetes
namespace: default
spec:
parentRefs:
- name: private
namespace: netbird
rules:
- backendRefs:
- name: kubernetes
port: 443
EOF
Work in progress features
We know the operator is not yet feature complete, but we thought you would like to hear that we're working on:
- ACL policy attachment
- Reverse Proxy authentication configuration
- Multi-cluster support
- Kubernetes API RBAC support
Get started
- Make sure to star us on GitHub
- Follow us on X
- Join our Slack Channel
- NetBird latest release on GitHub

