From 5ea7a177b7aa12decbe1685cd25e47567894eb30 Mon Sep 17 00:00:00 2001 From: Muhammad Adil Ghaffar Date: Wed, 18 Jun 2025 15:09:19 +0300 Subject: [PATCH] exporter: add hostnetwork bool to cephexporter Signed-off-by: Muhammad Adil Ghaffar --- Documentation/CRDs/specification.md | 12 ++ .../charts/rook-ceph/templates/resources.yaml | 4 + deploy/examples/crds.yaml | 4 + pkg/apis/ceph.rook.io/v1/types.go | 5 + .../ceph.rook.io/v1/zz_generated.deepcopy.go | 7 +- .../ceph/cluster/nodedaemon/exporter.go | 12 +- .../ceph/cluster/nodedaemon/exporter_test.go | 167 +++++++++++++++++- 7 files changed, 205 insertions(+), 6 deletions(-) diff --git a/Documentation/CRDs/specification.md b/Documentation/CRDs/specification.md index 54f0810d5..df92d6c26 100644 --- a/Documentation/CRDs/specification.md +++ b/Documentation/CRDs/specification.md @@ -3867,6 +3867,18 @@ int64

Time to wait before sending requests again to exporter server (seconds)

+ + +hostNetwork
+ +bool + + + +(Optional) +

Whether host networking is enabled for CephExporter. If not set, the network settings from CephCluster.spec.networking will be applied.

+ +

CephFilesystemStatus diff --git a/deploy/charts/rook-ceph/templates/resources.yaml b/deploy/charts/rook-ceph/templates/resources.yaml index 99a367d62..6dd4e5ea9 100644 --- a/deploy/charts/rook-ceph/templates/resources.yaml +++ b/deploy/charts/rook-ceph/templates/resources.yaml @@ -2646,6 +2646,10 @@ spec: exporter: description: Ceph exporter configuration properties: + hostNetwork: + description: Whether host networking is enabled for CephExporter. If not set, the network settings from CephCluster.spec.networking will be applied. + nullable: true + type: boolean perfCountersPrioLimit: default: 5 description: Only performance counters greater than or equal to this option are fetched diff --git a/deploy/examples/crds.yaml b/deploy/examples/crds.yaml index be7bc6ef0..7b72bc3c3 100644 --- a/deploy/examples/crds.yaml +++ b/deploy/examples/crds.yaml @@ -2644,6 +2644,10 @@ spec: exporter: description: Ceph exporter configuration properties: + hostNetwork: + description: Whether host networking is enabled for CephExporter. If not set, the network settings from CephCluster.spec.networking will be applied. + nullable: true + type: boolean perfCountersPrioLimit: default: 5 description: Only performance counters greater than or equal to this option are fetched diff --git a/pkg/apis/ceph.rook.io/v1/types.go b/pkg/apis/ceph.rook.io/v1/types.go index a707926a9..f3812a447 100755 --- a/pkg/apis/ceph.rook.io/v1/types.go +++ b/pkg/apis/ceph.rook.io/v1/types.go @@ -427,6 +427,11 @@ type CephExporterSpec struct { // Time to wait before sending requests again to exporter server (seconds) // +kubebuilder:default=5 StatsPeriodSeconds int64 `json:"statsPeriodSeconds,omitempty"` + + // Whether host networking is enabled for CephExporter. If not set, the network settings from CephCluster.spec.networking will be applied. + // +nullable + // +optional + HostNetwork *bool `json:"hostNetwork,omitempty"` } // ClusterStatus represents the status of a Ceph cluster diff --git a/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go b/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go index 987aa341b..9b9a1e556 100644 --- a/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go +++ b/pkg/apis/ceph.rook.io/v1/zz_generated.deepcopy.go @@ -1046,6 +1046,11 @@ func (in *CephDaemonsVersions) DeepCopy() *CephDaemonsVersions { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CephExporterSpec) DeepCopyInto(out *CephExporterSpec) { *out = *in + if in.HostNetwork != nil { + in, out := &in.HostNetwork, &out.HostNetwork + *out = new(bool) + **out = **in + } return } @@ -3454,7 +3459,7 @@ func (in *MonitoringSpec) DeepCopyInto(out *MonitoringSpec) { if in.Exporter != nil { in, out := &in.Exporter, &out.Exporter *out = new(CephExporterSpec) - **out = **in + (*in).DeepCopyInto(*out) } return } diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter.go b/pkg/operator/ceph/cluster/nodedaemon/exporter.go index 987a49d43..cc72c34d8 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/exporter.go +++ b/pkg/operator/ceph/cluster/nodedaemon/exporter.go @@ -121,7 +121,7 @@ func (r *ReconcileNode) createOrUpdateCephExporter(node corev1.Node, tolerations // wait for previous exporter pod to be deleted, before creating a new one // to avoid fighting for the same socket file deploy.Spec.Strategy.Type = appsv1.RecreateDeploymentStrategyType - + hostNetwork := exporterIsHost(cephCluster) var terminationGracePeriodSeconds int64 = 2 deploy.Spec.Template = corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ @@ -137,7 +137,7 @@ func (r *ReconcileNode) createOrUpdateCephExporter(node corev1.Node, tolerations }, Tolerations: tolerations, RestartPolicy: corev1.RestartPolicyAlways, - HostNetwork: cephCluster.Spec.Network.IsHost(), + HostNetwork: hostNetwork, Volumes: volumes, PriorityClassName: cephv1.GetCephExporterPriorityClassName(cephCluster.Spec.PriorityClassNames), TerminationGracePeriodSeconds: &terminationGracePeriodSeconds, @@ -308,3 +308,11 @@ func generateExporterEnvVar() corev1.EnvVar { return env } + +func exporterIsHost(cephCluster cephv1.CephCluster) bool { + hostNetwork := cephCluster.Spec.Network.IsHost() + if cephCluster.Spec.Monitoring.Exporter != nil && cephCluster.Spec.Monitoring.Exporter.HostNetwork != nil { + hostNetwork = *cephCluster.Spec.Monitoring.Exporter.HostNetwork + } + return hostNetwork +} diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go b/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go index 4579f2cdd..3109345a2 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go +++ b/pkg/operator/ceph/cluster/nodedaemon/exporter_test.go @@ -19,6 +19,7 @@ package nodedaemon import ( "context" "fmt" + "strconv" "testing" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" @@ -34,6 +35,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) @@ -45,6 +47,7 @@ func assertCephExporterArgs(t *testing.T, args []string, ipv6 bool) { } else { expectedArgsLen = 8 } + argsLen := len(args) assert.Equal(t, expectedArgsLen, argsLen) assert.Equal(t, "--sock-dir", args[0]) @@ -144,34 +147,192 @@ func TestCreateOrUpdateCephExporter(t *testing.T) { } func TestCephExporterBindAddress(t *testing.T) { - t.Run("IPv4", func(t *testing.T) { + prioLimit, statsPeriod := defaultPrioLimit, defaultStatsPeriod + prioLimitString, err := strconv.ParseInt(prioLimit, 10, 64) + assert.NoError(t, err, "failed to parse prioLimit") + statsPeriodString, err := strconv.ParseInt(statsPeriod, 10, 64) + assert.NoError(t, err, "failed to parse statsPeriod") + + // Test cases for exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=true + t.Run("IPv4 and exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} cephCluster.Spec.Labels = cephv1.LabelsSpec{} cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + cephCluster.Spec.Network.HostNetwork = true + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) assertCephExporterArgs(t, exporterContainer.Args, false) }) - t.Run("IPv6 via DualStack", func(t *testing.T) { + t.Run("IPv6 via DualStack and exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} cephCluster.Spec.Labels = cephv1.LabelsSpec{} cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} cephCluster.Spec.Network.DualStack = true cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + cephCluster.Spec.Network.HostNetwork = true + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) assertCephExporterArgs(t, exporterContainer.Args, true) }) - t.Run("IPv6 via IPFamily", func(t *testing.T) { + t.Run("IPv6 via IPFamily and exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} cephCluster.Spec.Labels = cephv1.LabelsSpec{} cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} cephCluster.Spec.Network.IPFamily = "IPv6" cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + cephCluster.Spec.Network.HostNetwork = true + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, true) + }) + + // Test cases for exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=false + t.Run("IPv4 and exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Network.HostNetwork = false + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, false) + }) + + t.Run("IPv6 via DualStack and exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=false", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephCluster.Spec.Network.DualStack = true + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Network.HostNetwork = false + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, true) + }) + + t.Run("IPv6 via IPFamily and exporterHostNetwork is not set and cephCluster.Spec.Network.HostNetwork=false", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephCluster.Spec.Network.IPFamily = "IPv6" + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Network.HostNetwork = false + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, true) + }) + + // Test cases for exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=true + t.Run("IPv4 and exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{} + cephCluster.Spec.Monitoring.Exporter.HostNetwork = ptr.To(false) + cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit = prioLimitString + cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds = statsPeriodString + + cephCluster.Spec.Network.HostNetwork = true + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, false) + }) + + t.Run("IPv6 via DualStack and exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephCluster.Spec.Network.DualStack = true + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{} + cephCluster.Spec.Monitoring.Exporter.HostNetwork = ptr.To(false) + cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit = prioLimitString + cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds = statsPeriodString + + cephCluster.Spec.Network.HostNetwork = true + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, true) + }) + t.Run("IPv6 via IPFamily and exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=true", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephCluster.Spec.Network.IPFamily = "IPv6" + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{} + cephCluster.Spec.Monitoring.Exporter.HostNetwork = ptr.To(false) + cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit = prioLimitString + cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds = statsPeriodString + + cephCluster.Spec.Network.HostNetwork = true + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, true) + }) + + // Test cases for exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=false + t.Run("IPv4 and exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=false", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{} + cephCluster.Spec.Monitoring.Exporter.HostNetwork = ptr.To(false) + cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit = prioLimitString + cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds = statsPeriodString + + cephCluster.Spec.Network.HostNetwork = false + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, false) + }) + + t.Run("IPv6 via DualStack and exporterHostNetwork=false and cephCluster.Spec.Network.HostNetwork=false", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephCluster.Spec.Network.DualStack = true + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{} + cephCluster.Spec.Monitoring.Exporter.HostNetwork = ptr.To(false) + cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit = prioLimitString + cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds = statsPeriodString + + cephCluster.Spec.Network.HostNetwork = false + + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) + assertCephExporterArgs(t, exporterContainer.Args, true) + }) + t.Run("IPv6 via IPFamily and HostNetwork=false and cephCluster.Spec.Network.HostNetwork=false", func(t *testing.T) { + cephCluster := cephv1.CephCluster{ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph"}} + cephCluster.Spec.Labels = cephv1.LabelsSpec{} + cephCluster.Spec.PriorityClassNames = cephv1.PriorityClassNamesSpec{} + cephCluster.Spec.Network.IPFamily = "IPv6" + cephVersion := cephver.CephVersion{Major: 18, Minor: 0, Extra: 0} + + cephCluster.Spec.Monitoring.Exporter = &cephv1.CephExporterSpec{} + cephCluster.Spec.Monitoring.Exporter.HostNetwork = ptr.To(false) + cephCluster.Spec.Monitoring.Exporter.PerfCountersPrioLimit = prioLimitString + cephCluster.Spec.Monitoring.Exporter.StatsPeriodSeconds = statsPeriodString + + cephCluster.Spec.Network.HostNetwork = false + exporterContainer := getCephExporterDaemonContainer(cephCluster, cephVersion) assertCephExporterArgs(t, exporterContainer.Args, true) })