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)
})