A Kubernetes operator that seamlessly integrates Netmaker WireGuard networks with Kubernetes clusters, enabling secure bidirectional connectivity between Kubernetes workloads and Netmaker networks.
The Netmaker K8s Operator provides multiple features to bridge Kubernetes clusters with Netmaker WireGuard networks:
- Egress Proxy: Expose Netmaker services to Kubernetes cluster workloads
- Ingress Proxy: Expose Kubernetes services to Netmaker network devices
- API Proxy: Secure access to Kubernetes API through WireGuard tunnels
Expose services that are external to your Kubernetes cluster but available in your Netmaker network, making them accessible to your Kubernetes workloads.
Use Case: Allow Kubernetes applications to access Netmaker services (APIs, databases, etc.) using standard Kubernetes Service names.
Example:
apiVersion: v1
kind: Service
metadata:
name: netmaker-api-egress
annotations:
netmaker.io/egress: "enabled"
netmaker.io/egress-target-ip: "100.93.135.2"
spec:
ports:
- port: 80
targetPort: 8080 # Port on Netmaker deviceHow it works:
- Creates a proxy pod with netclient sidecar
- Proxy listens on Kubernetes Service port
- Forwards traffic to Netmaker device via WireGuard
- Kubernetes workloads access via Service name
Documentation: Egress Proxy Guide
Expose Kubernetes services to devices on your Netmaker network, allowing Netmaker devices to access Kubernetes workloads.
Use Case: Enable Netmaker network devices to access Kubernetes services (APIs, databases, web apps) using Netmaker IPs or DNS names.
Example:
apiVersion: v1
kind: Service
metadata:
name: my-api-ingress
annotations:
netmaker.io/ingress: "enabled"
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: my-apiHow it works:
- Creates a proxy pod with netclient sidecar
- Proxy listens on Netmaker network IP (WireGuard interface)
- Forwards traffic to Kubernetes Service
- Netmaker devices access via Netmaker IP or DNS
Documentation: Ingress Proxy Guide
Secure reverse proxy for accessing Kubernetes API servers through WireGuard tunnels with user impersonation and RBAC support.
Use Case: Remote access to Kubernetes clusters via WireGuard with authentication and authorization.
Documentation: Proxy Usage Guide
| Feature | Ingress Proxy | Egress Proxy |
|---|---|---|
| Direction | Netmaker → Kubernetes | Kubernetes → Netmaker |
| Use Case | Expose K8s services to Netmaker network | Access Netmaker services from K8s |
| Proxy Listens On | Netmaker network IP (WireGuard interface) | Kubernetes Service port |
| Proxy Forwards To | Kubernetes Service (ClusterIP) | Netmaker device (IP/DNS) |
| Access Method | Netmaker devices use Netmaker IP/DNS | K8s workloads use Service name |
| Annotation | netmaker.io/ingress: "enabled" |
netmaker.io/egress: "enabled" |
| Target Config | netmaker.io/ingress-dns-name (optional) |
netmaker.io/egress-target-ip or netmaker.io/egress-target-dns |
| Port Config | Uses Service port and targetPort |
Uses Service targetPort (port on Netmaker device) |
Egress Proxy Flow (K8s → Netmaker):
K8s Pod → K8s Service → Egress Proxy Pod → WireGuard → Netmaker Device
Ingress Proxy Flow (Netmaker → K8s):
Netmaker Device → WireGuard → Ingress Proxy Pod → K8s Service → K8s Pod
- Go v1.22.0+
- Docker v17.03+
- kubectl v1.11.3+
- Kubernetes cluster v1.11.3+
- Netmaker server with network configured
- Netmaker token for joining the network
Install from Helm repository (recommended):
# Add the Helm repository (replace with your DigitalOcean Spaces endpoint)
helm repo add netmaker-k8s-ops https://downloads.netmaker.io/charts/
helm repo update
# Install the chart
helm install netmaker-k8s-ops netmaker-k8s-ops/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--create-namespace \
--version 1.0.0 \
--set image.repository=gravitl/netmaker-k8s-ops \
--set image.tag=latest \
--set netclient.token="YOUR_NETMAKER_TOKEN_HERE"Or install from local chart:
# Basic installation with default values
# Note: If namespace already exists, either omit --create-namespace or set namespace.create=false
helm install netmaker-k8s-ops netmaker-k8s-ops/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--create-namespace \
--set image.repository=gravitl/netmaker-k8s-ops \
--set image.tag=latest \
--set netclient.token="YOUR_NETMAKER_TOKEN_HERE"If namespace already exists, use:
helm install netmaker-k8s-ops netmaker-k8s-ops/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--set namespace.create=false \
--set image.repository=gravitl/netmaker-k8s-ops \
--set image.tag=latest \
--set netclient.token="YOUR_NETMAKER_TOKEN_HERE"With K8s Proxy configuration (PRO netmaker server needed) (need netmaker API integration in auth mode for users sync):
Auth MODE
helm install netmaker-k8s-ops netmaker-k8s-ops/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--create-namespace \
--set image.repository=gravitl/netmaker-k8s-ops \
--set image.tag=latest \
--set netclient.token="YOUR_NETMAKER_TOKEN_HERE" \
--set manager.configMap.proxyMode="auth" \
--set service.proxy.enabled=true \
--set api.enabled=true \
--set api.serverDomain="api.example.com" \
--set api.token="your-api-token-here" \
--set api.syncInterval="10"NOAUTH MODE
helm install netmaker-k8s-ops netmaker-k8s-ops/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--create-namespace \
--set image.repository=gravitl/netmaker-k8s-ops \
--set image.tag=latest \
--set netclient.token="YOUR_NETMAKER_TOKEN_HERE" \
--set manager.configMap.proxyMode="noauth" \
--set service.proxy.enabled=true
Or using a values file (for better organization):
# Create a values file (values-custom.yaml)
cat > values-custom.yaml <<EOF
image:
repository: <your-registry>/netmaker-k8s-ops
tag: <tag>
netclient:
token: "YOUR_NETMAKER_TOKEN_HERE"
manager:
env:
- name: IN_CLUSTER
value: "true"
- name: ENABLE_LEADER_ELECTION
value: "true"
- name: PROXY_SKIP_TLS_VERIFY
value: "true"
- name: PROXY_MODE
value: "auth"
- name: API_SERVER_DOMAIN
value: "api.example.com"
- name: API_TOKEN
value: "your-api-token-here"
- name: API_SYNC_INTERVAL
value: "300"
EOF
helm install netmaker-k8s-ops ./deploy/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--create-namespace \
--values values-custom.yaml- Using Kubernetes Secret for token (recommended for production):
# Create secret
kubectl create secret generic netclient-token \
--from-literal=token="YOUR_NETMAKER_TOKEN_HERE" \
--namespace netmaker-k8s-ops-system
# Install with secret reference (requires modifying values.yaml or using --set-file)
helm install netmaker-k8s-ops ./deploy/netmaker-k8s-ops \
--namespace netmaker-k8s-ops-system \
--create-namespace \
--set image.repository=<your-registry>/netmaker-k8s-ops \
--set image.tag=<tag>Then update the deployment to use the secret (see Token Configuration Guide).
- Verify deployment:
kubectl get pods -n netmaker-k8s-ops-system
helm status netmaker-k8s-ops -n netmaker-k8s-ops-systemUninstall with Helm:
helm uninstall netmaker-k8s-ops -n netmaker-k8s-ops-systemNote: CRDs are NOT automatically removed by Helm uninstall (this is Helm's default behavior to prevent data loss). To remove CRDs manually:
kubectl delete crd netmakerops.network.netmaker.io- Build and push the operator image:
make docker-build docker-push IMG=<your-registry>/netmaker-k8s-ops:tag- Install CRDs:
make install- Deploy the operator:
make deploy IMG=<your-registry>/netmaker-k8s-ops:tag-
Configure Netmaker token:
Option A: Direct environment variable (quick start, not recommended for production):
# In config/manager/manager.yaml, netclient container section env: - name: TOKEN value: "YOUR_NETMAKER_TOKEN_HERE"
Option B: Kubernetes Secret (recommended for production):
# Create secret kubectl create secret generic netclient-token \ --from-literal=token="YOUR_NETMAKER_TOKEN_HERE" \ --namespace=netmaker-k8s-ops-system # Update config/manager/manager.yaml to use secret: env: - name: TOKEN valueFrom: secretKeyRef: name: netclient-token key: token
See Token Configuration Guide for all methods and best practices.
-
Verify deployment:
kubectl get pods -n netmaker-k8s-ops-systemCreate a Service to access a Netmaker API:
apiVersion: v1
kind: Service
metadata:
name: netmaker-api-egress
annotations:
netmaker.io/egress: "enabled"
netmaker.io/egress-target-dns: "api.netmaker.internal"
spec:
ports:
- port: 80
targetPort: 8080Access from Kubernetes pods:
curl http://netmaker-api-egress:80Expose a Kubernetes service to Netmaker network:
apiVersion: v1
kind: Service
metadata:
name: my-api-ingress
annotations:
netmaker.io/ingress: "enabled"
netmaker.io/ingress-dns-name: "api.k8s.netmaker.internal"
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: my-apiAccess from Netmaker devices:
curl http://api.k8s.netmaker.internal:80- User Guide - Start here! Introduction and getting started guide for new users
- Token Configuration Guide - How to pass Netmaker tokens (secrets, env vars, etc.)
- Proxy Usage Guide - Kubernetes API proxy configuration and usage
- Proxy Authentication Modes - Detailed authentication mode configuration
- Egress Proxy Guide - Expose Netmaker services to K8s
- Ingress Proxy Guide - Expose K8s services to Netmaker
- Contributing Guide - Guidelines for contributing to the project
┌─────────────────────────────────────────────────────────────┐
│ Netmaker Network │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Netmaker │ │ Netmaker │ │
│ │ Device 1 │ │ Device 2 │ │
│ └──────┬───────┘ └──────┬───────┘ │
└─────────┼────────────────────────┼───────────────────────────┘
│ │ WireGuard Tunnel
│ │
┌─────────┼────────────────────────┼───────────────────────────┐
│ │ │ │
│ ┌──────▼────────────────────────▼───────┐ │
│ │ Kubernetes Cluster │ │
│ │ │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ Ingress Proxy Pod │ │ │
│ │ │ (netclient + socat) │ │ │
│ │ └──────────┬───────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────▼───────────────────────┐ │ │
│ │ │ Kubernetes Service │ │ │
│ │ └──────────┬───────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────▼───────────────────────┐ │ │
│ │ │ Application Pods │ │ │
│ │ │ (with optional netclient) │ │ │
│ │ └──────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────┐ │ │
│ │ │ Egress Proxy Pod │ │ │
│ │ │ (netclient + socat) │ │ │
│ │ └──────────────────────────────────┘ │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- ✅ Egress Proxy: Access Netmaker services from Kubernetes
- ✅ Ingress Proxy: Expose Kubernetes services to Netmaker
- ✅ RBAC Integration: Full Kubernetes RBAC support
Uninstall using Helm:
helm uninstall netmaker-k8s-ops -n netmaker-k8s-ops-systemDelete CRDs (optional, CRDs are NOT automatically removed by Helm uninstall to prevent data loss):
kubectl delete crd netmakerops.network.netmaker.ioDelete CR instances:
kubectl delete -k config/samples/Delete CRDs:
make uninstallUndeploy the operator:
make undeploy- go version v1.22.0+
- docker version 17.03+.
- kubectl version v1.11.3+.
- Access to a Kubernetes v1.11.3+ cluster.
Build and push your image to the location specified by IMG:
make docker-build docker-push IMG=<some-registry>/netmaker-k8s-ops:tagNOTE: This image ought to be published in the personal registry you specified. And it is required to have access to pull the image from the working environment. Make sure you have the proper permission to the registry if the above commands don’t work.
Install the CRDs into the cluster:
make installDeploy the Manager to the cluster with the image specified by IMG:
make deploy IMG=<some-registry>/netmaker-k8s-ops:tagNOTE: If you encounter RBAC errors, you may need to grant yourself cluster-admin privileges or be logged in as admin.
Create instances of your solution You can apply the samples (examples) from the config/sample:
kubectl apply -k config/samples/NOTE: Ensure that the samples has default values to test it out.
Delete the instances (CRs) from the cluster:
kubectl delete -k config/samples/Delete the APIs(CRDs) from the cluster:
make uninstallUnDeploy the controller from the cluster:
make undeployFollowing are the steps to build the installer and distribute this project.
- Build the installer for the image built and published in the registry:
make build-installer IMG=<some-registry>/netmaker-k8s-ops:tagNOTE: The makefile target mentioned above generates an 'install.yaml' file in the dist directory. This file contains all the resources built with Kustomize, which are necessary to install this project without its dependencies.
- Using the installer
Users can just run kubectl apply -f to install the project, i.e.:
kubectl apply -f https://raw.githubusercontent.com/<org>/netmaker-k8s-ops/<tag or branch>/dist/install.yamlNOTE: Run make help for more information on all potential make targets
More information can be found via the Kubebuilder Documentation
We welcome contributions! Please see our Contributing Guide for details on:
- How to get started with development
- Code style and conventions
- Testing requirements
- Pull request process
- And more!
Contributions of all kinds are appreciated - code, documentation, bug reports, feature requests, and feedback.
Copyright 2025 Netmaker, Inc.
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.
See the LICENSE file for the full license text.