Make runtime namespace configurable (#145)

Making the runtime namespace configurable makes it possible to run
locally outside of the cluster. This is useful for quick development
testing.

Signed-off-by: Philip Laine <philip.laine@gmail.com>
This commit is contained in:
Philip Laine
2026-03-18 12:00:31 +01:00
committed by GitHub
parent 8267cc406a
commit ccf819d2ff
3 changed files with 39 additions and 34 deletions
+24 -26
View File
@@ -18,6 +18,7 @@ package main
import ( import (
"crypto/tls" "crypto/tls"
"errors"
"flag" "flag"
"fmt" "fmt"
"os" "os"
@@ -46,10 +47,6 @@ import (
// +kubebuilder:scaffold:imports // +kubebuilder:scaffold:imports
) )
const (
inClusterNamespacePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
)
var ( var (
scheme = runtime.NewScheme() scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup") setupLog = ctrl.Log.WithName("setup")
@@ -67,6 +64,7 @@ func init() {
func main() { func main() {
// NB Specific flags // NB Specific flags
var ( var (
runtimeNamespace string
managementURL string managementURL string
clientImage string clientImage string
clusterName string clusterName string
@@ -76,6 +74,7 @@ func main() {
allowAutomaticPolicyCreation bool allowAutomaticPolicyCreation bool
defaultLabels string defaultLabels string
) )
flag.StringVar(&runtimeNamespace, "runtime-namespace", "", "Namespace the controller is running in")
flag.StringVar(&managementURL, "netbird-management-url", "https://api.netbird.io", "Management service URL") flag.StringVar(&managementURL, "netbird-management-url", "https://api.netbird.io", "Management service URL")
flag.StringVar(&clientImage, "netbird-client-image", "netbirdio/netbird:latest", "Image for netbird client container") flag.StringVar(&clientImage, "netbird-client-image", "netbirdio/netbird:latest", "Image for netbird client container")
flag.StringVar( flag.StringVar(
@@ -133,6 +132,12 @@ func main() {
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
runtimeNamespace, err := getRuntimeNamespace(runtimeNamespace)
if err != nil {
setupLog.Error(err, "unable to get runtime namespace")
os.Exit(1)
}
defaultLabelsMap := make(map[string]string) defaultLabelsMap := make(map[string]string)
if defaultLabels != "" { if defaultLabels != "" {
for s := range strings.SplitSeq(defaultLabels, ",") { for s := range strings.SplitSeq(defaultLabels, ",") {
@@ -177,10 +182,11 @@ func main() {
Metrics: metricsserver.Options{ Metrics: metricsserver.Options{
BindAddress: metricsAddr, BindAddress: metricsAddr,
}, },
WebhookServer: webhookServer, WebhookServer: webhookServer,
HealthProbeBindAddress: probeAddr, HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection, LeaderElectionNamespace: runtimeNamespace,
LeaderElectionID: "operator.netbird.io", LeaderElection: enableLeaderElection,
LeaderElectionID: "operator.netbird.io",
}) })
if err != nil { if err != nil {
setupLog.Error(err, "unable to start manager") setupLog.Error(err, "unable to start manager")
@@ -223,18 +229,12 @@ func main() {
os.Exit(1) os.Exit(1)
} }
controllerNamespace, err := getInClusterNamespace()
if err != nil {
setupLog.Error(err, "unable to get main namespace", "controller", "Service")
os.Exit(1)
}
if err = (&controller.ServiceReconciler{ if err = (&controller.ServiceReconciler{
Client: mgr.GetClient(), Client: mgr.GetClient(),
ClusterName: clusterName, ClusterName: clusterName,
ClusterDNS: clusterDNS, ClusterDNS: clusterDNS,
NamespacedNetworks: namespacedNetworks, NamespacedNetworks: namespacedNetworks,
ControllerNamespace: controllerNamespace, ControllerNamespace: runtimeNamespace,
DefaultLabels: defaultLabelsMap, DefaultLabels: defaultLabelsMap,
}).SetupWithManager(mgr); err != nil { }).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Service") setupLog.Error(err, "unable to create controller", "controller", "Service")
@@ -307,19 +307,17 @@ func main() {
} }
} }
func getInClusterNamespace() (string, error) { func getRuntimeNamespace(runtimeNamespace string) (string, error) {
// Check whether the namespace file exists. if runtimeNamespace != "" {
// If not, we are not running in cluster so can't guess the namespace. return runtimeNamespace, nil
if _, err := os.Stat(inClusterNamespacePath); os.IsNotExist(err) { }
return "", fmt.Errorf("not running in-cluster, please specify LeaderElectionNamespace") inClusterNamespacePath := "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
} else if err != nil { b, err := os.ReadFile(inClusterNamespacePath)
return "", fmt.Errorf("error checking namespace file: %w", err) if errors.Is(err, os.ErrNotExist) {
return "", fmt.Errorf("not running in-cluster, runtime namespace needs to be set")
} }
// Load the namespace file and return its content
namespace, err := os.ReadFile(inClusterNamespacePath)
if err != nil { if err != nil {
return "", fmt.Errorf("error reading namespace file: %w", err) return "", fmt.Errorf("error reading namespace file: %w", err)
} }
return string(namespace), nil return string(b), nil
} }
@@ -45,6 +45,7 @@ spec:
- --leader-elect - --leader-elect
- --health-probe-bind-address=:{{ .Values.operator.livenessProbe.port }} - --health-probe-bind-address=:{{ .Values.operator.livenessProbe.port }}
- --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs - --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs
- --runtime-namespace=$(POD_NAMESPACE)
{{- if .Values.managementURL }} {{- if .Values.managementURL }}
- --netbird-management-url={{.Values.managementURL}} - --netbird-management-url={{.Values.managementURL}}
{{- end }} {{- end }}
@@ -87,8 +88,12 @@ spec:
periodSeconds: {{ .Values.operator.livenessProbe.periodSeconds }} periodSeconds: {{ .Values.operator.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.operator.livenessProbe.successThreshold }} successThreshold: {{ .Values.operator.livenessProbe.successThreshold }}
timeoutSeconds: {{ .Values.operator.livenessProbe.timeoutSeconds }} timeoutSeconds: {{ .Values.operator.livenessProbe.timeoutSeconds }}
{{- if or .Values.netbirdAPI.key .Values.netbirdAPI.keyFromSecret }}
env: env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- if or .Values.netbirdAPI.key .Values.netbirdAPI.keyFromSecret }}
- name: NB_API_KEY - name: NB_API_KEY
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
+9 -7
View File
@@ -192,11 +192,12 @@ var _ = Describe("Manager", Ordered, func() {
Eventually(verifyMetricsServerStarted).Should(Succeed()) Eventually(verifyMetricsServerStarted).Should(Succeed())
By("creating the curl-metrics pod to access the metrics endpoint") By("creating the curl-metrics pod to access the metrics endpoint")
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never", Eventually(func(g Gomega) {
"--namespace", namespace, cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
"--image=curlimages/curl:latest", "--namespace", namespace,
"--overrides", "--image=curlimages/curl:latest",
fmt.Sprintf(`{ "--overrides",
fmt.Sprintf(`{
"spec": { "spec": {
"containers": [{ "containers": [{
"name": "curl", "name": "curl",
@@ -217,8 +218,9 @@ var _ = Describe("Manager", Ordered, func() {
}] }]
} }
}`, metricsServiceName, namespace)) }`, metricsServiceName, namespace))
_, err = utils.Run(cmd) _, err = utils.Run(cmd)
Expect(err).NotTo(HaveOccurred(), "Failed to create curl-metrics pod") g.Expect(err).NotTo(HaveOccurred(), "Failed to create curl-metrics pod")
}).Should(Succeed())
By("waiting for the curl-metrics pod to complete.") By("waiting for the curl-metrics pod to complete.")
verifyCurlUp := func(g Gomega) { verifyCurlUp := func(g Gomega) {