Repository: rook/rook
Pull request #10409 (2022-06-07 16:17:10)

ceph: Add holder pod if csi host networking is disabled (backport #10342)
This is an automatic backport of pull request #10342 done by [Mergify](https://mergify.com).


---


<details>
<summary>Mergify commands and options</summary>

<br />

More conditions and actions can be found in the [documentation](https://docs.mergify.com/).

You can also trigger Mergify actions by commenting on this pull request:

- `@Mergifyio refresh` will re-evaluate the rules
- `@Mergifyio rebase` will rebase this PR on its base branch
- `@Mergifyio update` will merge the base branch into this PR
- `@Mergifyio backport <destination>` will backport this PR on `<destination>` branch

Additionally, on Mergify [dashboard](https://dashboard.mergify.com/) you can:

- look at your merge queues
- generate the Mergify configuration with the config editor.

Finally, you can contact us on https://mergify.com
</details>



Patch:
diff --git a/pkg/operator/ceph/csi/controller.go b/pkg/operator/ceph/csi/controller.go
index 48eb2ba86..e7d26aa3a 100644
--- a/pkg/operator/ceph/csi/controller.go
+++ b/pkg/operator/ceph/csi/controller.go
@@ -19,6 +19,7 @@ package csi
 import (
 	"context"
 	"os"
+	"strconv"
 
 	cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
 	cephclient "github.com/rook/rook/pkg/daemon/ceph/client"
@@ -46,11 +47,11 @@ const (
 
 // ReconcileCSI reconciles a ceph-csi driver
 type ReconcileCSI struct {
-	client           client.Client
-	context          *clusterd.Context
-	opManagerContext context.Context
-	opConfig         opcontroller.OperatorConfig
-	multusClusters   []ClusterDetail
+	client             client.Client
+	context            *clusterd.Context
+	opManagerContext   context.Context
+	opConfig           opcontroller.OperatorConfig
+	clustersWithHolder []ClusterDetail
 }
 
 // ClusterDetail is a struct that holds the information of a cluster, it knows its internals (like
@@ -69,11 +70,11 @@ func Add(mgr manager.Manager, context *clusterd.Context, opManagerContext contex
 // newReconciler returns a new reconcile.Reconciler
 func newReconciler(mgr manager.Manager, context *clusterd.Context, opManagerContext context.Context, opConfig opcontroller.OperatorConfig) reconcile.Reconciler {
 	return &ReconcileCSI{
-		client:           mgr.GetClient(),
-		context:          context,
-		opConfig:         opConfig,
-		opManagerContext: opManagerContext,
-		multusClusters:   []ClusterDetail{},
+		client:             mgr.GetClient(),
+		context:            context,
+		opConfig:           opConfig,
+		opManagerContext:   opManagerContext,
+		clustersWithHolder: []ClusterDetail{},
 	}
 }
 
@@ -153,6 +154,29 @@ func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, e
 
 		return reconcile.Result{}, nil
 	}
+	// Fetch the operator's configmap. We force the NamespaceName to the operator since the request
+	// could be a CephCluster. If so the NamespaceName will be the one from the cluster and thus the
+	// CM won't be found
+	opNamespaceName := types.NamespacedName{Name: opcontroller.OperatorSettingConfigMapName, Namespace: r.opConfig.OperatorNamespace}
+	opConfig := &v1.ConfigMap{}
+	err = r.client.Get(r.opManagerContext, opNamespaceName, opConfig)
+	if err != nil {
+		if kerrors.IsNotFound(err) {
+			logger.Debug("operator's configmap resource not found. will use default value or env var.")
+			r.opConfig.Parameters = make(map[string]string)
+		} else {
+			// Error reading the object - requeue the request.
+			return opcontroller.ImmediateRetryResult, errors.Wrap(err, "failed to get operator's configmap")
+		}
+	} else {
+		// Populate the operator's config
+		r.opConfig.Parameters = opConfig.Data
+	}
+
+	csiHostNetworkEnabled, err := strconv.ParseBool(k8sutil.GetValue(r.opConfig.Parameters, "CSI_ENABLE_HOST_NETWORK", "true"))
+	if err != nil {
+		return reconcile.Result{}, errors.Wrap(err, "failed to parse value for 'CSI_ENABLE_HOST_NETWORK'")
+	}
 
 	for i, cluster := range cephClusters.Items {
 		if !cluster.DeletionTimestamp.IsZero() {
@@ -164,10 +188,10 @@ func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, e
 			logger.Debugf("ceph cluster %q has cleanup policy, the cluster will soon go away, no need to reconcile the csi driver", cluster.Name)
 			return reconcile.Result{}, nil
 		}
-
-		// Do we have a multus cluster?
+		holderEnabled := !csiHostNetworkEnabled || cluster.Spec.Network.IsMultus()
+		// Do we have a multus cluster or csi host network disabled?
 		// If so deploy the plugin holder with the fsid attached
-		if cluster.Spec.Network.IsMultus() {
+		if holderEnabled {
 			// Load cluster info for later use in updating the ceph-csi configmap
 			clusterInfo, _, _, err := opcontroller.LoadClusterInfo(r.context, r.opManagerContext, cluster.Namespace)
 			if err != nil {
@@ -181,30 +205,13 @@ func (r *ReconcileCSI) reconcile(request reconcile.Request) (reconcile.Result, e
 				return opcontroller.ImmediateRetryResult, errors.Wrapf(err, "failed to load cluster info for cluster %q", cluster.Name)
 			}
 
-			logger.Debugf("cluster %q is running on multus, deploying the ceph-csi plugin holder", cluster.Name)
-			r.multusClusters = append(r.multusClusters, ClusterDetail{cluster: &cephClusters.Items[i], clusterInfo: clusterInfo})
-		} else {
-			logger.Debugf("not a multus cluster %q, not deploying the ceph-csi plugin holder", request.NamespacedName)
-		}
-	}
+			logger.Debugf("cluster %q is running on multus or CSI_ENABLE_HOST_NETWORK is false, deploying the ceph-csi plugin holder", cluster.Name)
+
+			r.clustersWithHolder = append(r.clustersWithHolder, ClusterDetail{cluster: &cephClusters.Items[i], clusterInfo: clusterInfo})
 
-	// Fetch the operator's configmap. We force the NamespaceName to the operator since the request
-	// could be a CephCluster. If so the NamespaceName will be the one from the cluster and thus the
-	// CM won't be found
-	opNamespaceName := types.NamespacedName{Name: opcontroller.OperatorSettingConfigMapName, Namespace: r.opConfig.OperatorNamespace}
-	opConfig := &v1.ConfigMap{}
-	err = r.client.Get(r.opManagerContext, opNamespaceName, opConfig)
-	if err != nil {
-		if kerrors.IsNotFound(err) {
-			logger.Debug("operator's configmap resource not found. will use default value or env var.")
-			r.opConfig.Parameters = make(map[string]string)
 		} else {
-			// Error reading the object - requeue the request.
-			return opcontroller.ImmediateRetryResult, errors.Wrap(err, "failed to get operator's configmap")
+			logger.Debugf("not a multus cluster %q or CSI_ENABLE_HOST_NETWORK is true, not deploying the ceph-csi plugin holder", request.NamespacedName)
 		}
-	} else {
-		// Populate the operator's config
-		r.opConfig.Parameters = opConfig.Data
 	}
 
 	ownerRef, err := k8sutil.GetDeploymentOwnerReference(r.opManagerContext, r.context.Clientset, os.Getenv(k8sutil.PodNameEnvVar), r.opConfig.OperatorNamespace)
diff --git a/pkg/operator/ceph/csi/spec.go b/pkg/operator/ceph/csi/spec.go
index 059fddfc5..6d57a61dd 100644
--- a/pkg/operator/ceph/csi/spec.go
+++ b/pkg/operator/ceph/csi/spec.go
@@ -370,8 +370,15 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 			return errors.Wrap(err, "failed to load nfs provisioner deployment template")
 		}
 	}
-	multusApplied := len(r.multusClusters) > 0
 
+	holderEnabled := !CSIParam.EnableCSIHostNetwork
+
+	for i := range r.clustersWithHolder {
+		if r.clustersWithHolder[i].cluster.Spec.Network.IsMultus() {
+			holderEnabled = true
+			break
+		}
+	}
 	// get common provisioner tolerations and node affinity
 	provisionerTolerations := getToleration(r.opConfig.Parameters, provisionerTolerationsEnv, []corev1.Toleration{})
 	provisionerNodeAffinity := getNodeAffinity(r.opConfig.Parameters, provisionerNodeAffinityEnv, &corev1.NodeAffinity{})
@@ -380,11 +387,12 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 	pluginTolerations := getToleration(r.opConfig.Parameters, pluginTolerationsEnv, []corev1.Toleration{})
 	pluginNodeAffinity := getNodeAffinity(r.opConfig.Parameters, pluginNodeAffinityEnv, &corev1.NodeAffinity{})
 
-	if multusApplied && !v.SupportsMultus() {
-		return errors.Errorf("multus is applied but the csi version %q does not support it, need at least %q", v.String(), multusSupportedVersion.String())
+	if holderEnabled && !v.SupportsNsenter() {
+		return errors.Errorf("multus/csi pod networking is applied but the csi version %q does not support it, need at least %q", v.String(), nsenterSupportedVersion.String())
 	}
 
-	// Deploy the CSI Holder DaemonSet if Multus is enabled
+	// Deploy the CSI Holder DaemonSet if Multus is enabled or
+	// EnableCSIHostNetwork is disabled.
 	err = r.configureHolders(enabledDrivers, tp, pluginTolerations, pluginNodeAffinity)
 	if err != nil {
 		return errors.Wrap(err, "failed to configure holder")
@@ -402,11 +410,11 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 		if err != nil {
 			return errors.Wrapf(err, "failed to set owner reference to rbd plugin daemonset %q", rbdPlugin.Name)
 		}
-		_, err := r.applyCephClusterNetworkConfig(r.opManagerContext, &rbdPlugin.Spec.Template.ObjectMeta)
+		err = r.applyCephClusterNetworkConfig(r.opManagerContext, &rbdPlugin.Spec.Template.ObjectMeta)
 		if err != nil {
 			return errors.Wrapf(err, "failed to apply network config to rbd plugin daemonset %q", rbdPlugin.Name)
 		}
-		if multusApplied {
+		if holderEnabled {
 			rbdPlugin.Spec.Template.Spec.HostNetwork = false
 		}
 		err = k8sutil.CreateDaemonSet(r.opManagerContext, r.opConfig.OperatorNamespace, r.context.Clientset, rbdPlugin)
@@ -434,7 +442,7 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 			Type: apps.RecreateDeploymentStrategyType,
 		}
 
-		_, err = r.applyCephClusterNetworkConfig(r.opManagerContext, &rbdProvisionerDeployment.Spec.Template.ObjectMeta)
+		err = r.applyCephClusterNetworkConfig(r.opManagerContext, &rbdProvisionerDeployment.Spec.Template.ObjectMeta)
 		if err != nil {
 			return errors.Wrapf(err, "failed to apply network config to rbd plugin provisioner deployment %q", rbdProvisionerDeployment.Name)
 		}
@@ -470,11 +478,11 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 		if err != nil {
 			return errors.Wrapf(err, "failed to set owner reference to cephfs plugin daemonset %q", cephfsPlugin.Name)
 		}
-		multusApplied, err := r.applyCephClusterNetworkConfig(r.opManagerContext, &cephfsPlugin.Spec.Template.ObjectMeta)
+		err = r.applyCephClusterNetworkConfig(r.opManagerContext, &cephfsPlugin.Spec.Template.ObjectMeta)
 		if err != nil {
 			return errors.Wrapf(err, "failed to apply network config to cephfs plugin daemonset %q", cephfsPlugin.Name)
 		}
-		if multusApplied {
+		if holderEnabled {
 			cephfsPlugin.Spec.Template.Spec.HostNetwork = false
 			// HostPID is used to communicate with the network namespace
 			cephfsPlugin.Spec.Template.Spec.HostPID = true
@@ -506,7 +514,7 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 			Type: apps.RecreateDeploymentStrategyType,
 		}
 
-		_, err = r.applyCephClusterNetworkConfig(r.opManagerContext, &cephfsProvisionerDeployment.Spec.Template.ObjectMeta)
+		err = r.applyCephClusterNetworkConfig(r.opManagerContext, &cephfsProvisionerDeployment.Spec.Template.ObjectMeta)
 		if err != nil {
 			return errors.Wrapf(err, "failed to apply network config to cephfs plugin provisioner deployment %q", cephfsProvisionerDeployment.Name)
 		}
@@ -541,11 +549,11 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 		if err != nil {
 			return errors.Wrapf(err, "failed to set owner reference to nfs plugin daemonset %q", nfsPlugin.Name)
 		}
-		multusApplied, err := r.applyCephClusterNetworkConfig(r.opManagerContext, &nfsPlugin.Spec.Template.ObjectMeta)
+		err = r.applyCephClusterNetworkConfig(r.opManagerContext, &nfsPlugin.Spec.Template.ObjectMeta)
 		if err != nil {
 			return errors.Wrapf(err, "failed to apply network config to nfs plugin daemonset %q", nfsPlugin.Name)
 		}
-		if multusApplied {
+		if holderEnabled {
 			nfsPlugin.Spec.Template.Spec.HostNetwork = false
 		}
 		err = k8sutil.CreateDaemonSet(r.opManagerContext, r.opConfig.OperatorNamespace, r.context.Clientset, nfsPlugin)
@@ -574,7 +582,7 @@ func (r *ReconcileCSI) startDrivers(ver *version.Info, ownerInfo *k8sutil.OwnerI
 			Type: apps.RecreateDeploymentStrategyType,
 		}
 
-		_, err = r.applyCephClusterNetworkConfig(r.opManagerContext, &nfsProvisionerDeployment.Spec.Template.ObjectMeta)
+		err = r.applyCephClusterNetworkConfig(r.opManagerContext, &nfsProvisionerDeployment.Spec.Template.ObjectMeta)
 		if err != nil {
 			return errors.Wrapf(err, "failed to apply network config to nfs provisioner deployment %q", nfsProvisionerDeployment.Name)
 		}
@@ -670,23 +678,21 @@ func (r *ReconcileCSI) deleteCSIDriverResources(ver *version.Info, daemonset, de
 	return nil
 }
 
-func (r *ReconcileCSI) applyCephClusterNetworkConfig(ctx context.Context, objectMeta *metav1.ObjectMeta) (bool, error) {
-	var isMultusApplied bool
+func (r *ReconcileCSI) applyCephClusterNetworkConfig(ctx context.Context, objectMeta *metav1.ObjectMeta) error {
 	cephClusters, err := r.context.RookClientset.CephV1().CephClusters(objectMeta.Namespace).List(ctx, metav1.ListOptions{})
 	if err != nil {
-		return false, errors.Wrap(err, "failed to find CephClusters")
+		return errors.Wrap(err, "failed to find CephClusters")
 	}
 	for _, cephCluster := range cephClusters.Items {
 		if cephCluster.Spec.Network.IsMultus() {
 			err = k8sutil.ApplyMultus(cephCluster.Spec.Network, objectMeta)
 			if err != nil {
-				return false, errors.Wrapf(err, "failed to apply multus configuration to CephCluster %q", cephCluster.Name)
+				return errors.Wrapf(err, "failed to apply multus configuration to CephCluster %q", cephCluster.Name)
 			}
-			isMultusApplied = true
 		}
 	}
 
-	return isMultusApplied, nil
+	return nil
 }
 
 // ValidateCSIVersion checks if the configured ceph-csi image is supported
@@ -741,11 +747,11 @@ func (r *ReconcileCSI) validateCSIVersion(ownerInfo *k8sutil.OwnerInfo) (*CephCS
 }
 
 func (r *ReconcileCSI) configureHolders(enabledDrivers []driverDetails, tp templateParam, pluginTolerations []corev1.Toleration, pluginNodeAffinity *corev1.NodeAffinity) error {
-	for _, multusCluster := range r.multusClusters {
+	for _, cluster := range r.clustersWithHolder {
 		for _, driver := range enabledDrivers {
-			err := r.configureHolder(driver, multusCluster, tp, pluginTolerations, pluginNodeAffinity)
+			err := r.configureHolder(driver, cluster, tp, pluginTolerations, pluginNodeAffinity)
 			if err != nil {
-				return errors.Wrapf(err, "failed to configure holder %q for %q/%q", driver.name, multusCluster.cluster.Name, multusCluster.cluster.Namespace)
+				return errors.Wrapf(err, "failed to configure holder %q for %q/%q", driver.name, cluster.cluster.Name, cluster.cluster.Namespace)
 			}
 		}
 	}
@@ -753,7 +759,7 @@ func (r *ReconcileCSI) configureHolders(enabledDrivers []driverDetails, tp templ
 	return nil
 }
 
-func (r *ReconcileCSI) configureHolder(driver driverDetails, multusCluster ClusterDetail, tp templateParam, pluginTolerations []corev1.Toleration, pluginNodeAffinity *corev1.NodeAffinity) error {
+func (r *ReconcileCSI) configureHolder(driver driverDetails, c ClusterDetail, tp templateParam, pluginTolerations []corev1.Toleration, pluginNodeAffinity *corev1.NodeAffinity) error {
 	cephPluginHolder, err := templateToDaemonSet("cephpluginholder", driver.holderTemplate, tp)
 	if err != nil {
 		return errors.Wrapf(err, "failed to load ceph %q plugin holder template", driver.fullName)
@@ -775,7 +781,7 @@ func (r *ReconcileCSI) configureHolder(driver driverDetails, multusCluster Clust
 		cephPluginHolder.Spec.Template.Spec.Containers[0].Env,
 		corev1.EnvVar{
 			Name:  "CEPH_CLUSTER_NAMESPACE",
-			Value: multusCluster.cluster.Namespace,
+			Value: c.cluster.Namespace,
 		},
 	)
 
@@ -790,35 +796,37 @@ func (r *ReconcileCSI) configureHolder(driver driverDetails, multusCluster Clust
 	)
 
 	// Make the DS name unique per Ceph cluster
-	cephPluginHolder.Name = fmt.Sprintf("%s-%s", cephPluginHolder.Name, multusCluster.cluster.Name)
-	cephPluginHolder.Spec.Template.Name = fmt.Sprintf("%s-%s", cephPluginHolder.Spec.Template.Name, multusCluster.cluster.Name)
-	cephPluginHolder.Spec.Template.Spec.Containers[0].Name = fmt.Sprintf("%s-%s", cephPluginHolder.Spec.Template.Spec.Containers[0].Name, multusCluster.cluster.Name)
+	cephPluginHolder.Name = fmt.Sprintf("%s-%s", cephPluginHolder.Name, c.cluster.Name)
+	cephPluginHolder.Spec.Template.Name = fmt.Sprintf("%s-%s", cephPluginHolder.Spec.Template.Name, c.cluster.Name)
+	cephPluginHolder.Spec.Template.Spec.Containers[0].Name = fmt.Sprintf("%s-%s", cephPluginHolder.Spec.Template.Spec.Containers[0].Name, c.cluster.Name)
 
 	// Add default labels
 	k8sutil.AddRookVersionLabelToDaemonSet(cephPluginHolder)
 
-	// Apply Multus annotations to daemonset spec
-	err = k8sutil.ApplyMultus(multusCluster.cluster.Spec.Network, &cephPluginHolder.Spec.Template.ObjectMeta)
-	if err != nil {
-		return errors.Wrapf(err, "failed to apply multus configuration for holder %q in cluster %q", cephPluginHolder.Name, multusCluster.cluster.Namespace)
+	// If multus is enabled, add the multus plugin label
+	if c.cluster.Spec.Network.IsMultus() {
+		// Apply Multus annotations to daemonset spec
+		err = k8sutil.ApplyMultus(c.cluster.Spec.Network, &cephPluginHolder.Spec.Template.ObjectMeta)
+		if err != nil {
+			return errors.Wrapf(err, "failed to apply multus configuration for holder %q in cluster %q", cephPluginHolder.Name, c.cluster.Namespace)
+		}
 	}
-
 	// Finally create the DaemonSet
 	_, err = r.context.Clientset.AppsV1().DaemonSets(r.opConfig.OperatorNamespace).Create(r.opManagerContext, cephPluginHolder, metav1.CreateOptions{})
 	if err != nil {
 		if kerrors.IsAlreadyExists(err) {
-			logger.Debugf("holder %q already exists for cluster %q, it should never be updated", cephPluginHolder.Name, multusCluster.cluster.Namespace)
+			logger.Debugf("holder %q already exists for cluster %q, it should never be updated", cephPluginHolder.Name, c.cluster.Namespace)
 		} else {
 			return errors.Wrapf(err, "failed to start ceph plugin holder daemonset %q", cephPluginHolder.Name)
 		}
 	}
 
 	clusterConfigEntry := &CsiClusterConfigEntry{
-		Monitors: MonEndpoints(multusCluster.clusterInfo.Monitors),
+		Monitors: MonEndpoints(c.clusterInfo.Monitors),
 		RBD:      &CsiRBDSpec{},
 		CephFS:   &CsiCephFSSpec{},
 	}
-	netNamespaceFilePath := generateNetNamespaceFilePath(CSIParam.KubeletDirPath, driver.fullName, multusCluster.cluster.Namespace)
+	netNamespaceFilePath := generateNetNamespaceFilePath(CSIParam.KubeletDirPath, driver.fullName, c.cluster.Namespace)
 	if driver.name == RBDDriverShortName {
 		clusterConfigEntry.RBD.NetNamespaceFilePath = netNamespaceFilePath
 	}
@@ -826,7 +834,7 @@ func (r *ReconcileCSI) configureHolder(driver driverDetails, multusCluster Clust
 		clusterConfigEntry.CephFS.NetNamespaceFilePath = netNamespaceFilePath
 	}
 	// Save the path of the network namespace file for ceph-csi to use
-	err = SaveClusterConfig(r.context.Clientset, multusCluster.cluster.Namespace, multusCluster.clusterInfo, clusterConfigEntry)
+	err = SaveClusterConfig(r.context.Clientset, c.cluster.Namespace, c.clusterInfo, clusterConfigEntry)
 	if err != nil {
 		return errors.Wrapf(err, "failed to save cluster config for csi holder %q", driver.fullName)
 	}
diff --git a/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml b/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml
index 686f6d1e5..e7d447ee9 100644
--- a/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml
+++ b/pkg/operator/ceph/csi/template/cephfs/csi-cephfsplugin-holder.yaml
@@ -1,9 +1,9 @@
-# This DaemonSet is only active when the cluster is deployed with Multus enabled. Hopefully in the
-# future it will be part of every Ceph-CSI deployment. Its role is to "hold" the Ceph Filesystem
-# mounts that are created by the CSI driver. Essentially, it exposes its network namespace into the
-# Kubelet plugin directly and Ceph-CSI picks it up. When mounting, the Ceph-CSI driver will use the
-# network namespace of the DaemonSet instead of its own (the plugin pod). This pod is not expected
-# to be updated nor restarted unless the node reboots.
+# This DaemonSet is only active when the cluster is deployed with Multus enabled or EnableCSIHostNetwork
+# is set to false. Hopefully in the future it will be part of every Ceph-CSI deployment. Its role is to
+# "hold" the Ceph Filesystem mounts that are created by the CSI driver. Essentially, it exposes its
+# network namespace into the Kubelet plugin directly and Ceph-CSI picks it up. When mounting, the Ceph-CSI
+# driver will use the network namespace of the DaemonSet instead of its own (the plugin pod). This pod
+# is not expected to be updated nor restarted unless the node reboots.
 kind: DaemonSet
 apiVersion: apps/v1
 metadata:
diff --git a/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml b/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml
index 6bf9b080f..c64250673 100644
--- a/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml
+++ b/pkg/operator/ceph/csi/template/rbd/csi-rbdplugin-holder.yaml
@@ -1,9 +1,9 @@
-# This DaemonSet is only active when the cluster is deployed with Multus enabled. Hopefully in the
-# future it will be part of every Ceph-CSI deployment. Its role is to "hold" the network RBD block
-# mapping that are created by the CSI driver. Essentially, it exposes its network namespace into the
-# Kubelet plugin directly and Ceph-CSI picks it up. When mapping an RBD image, the Ceph-CSI driver
-# will use the network namespace of the DaemonSet instead of its own (the plugin pod). This pod is
-# not expected to be updated nor restarted unless the node reboots.
+# This DaemonSet is only active when the cluster is deployed with Multus enabled or EnableCSIHostNetwork
+# is set to false. Hopefully in the future it will be part of every Ceph-CSI deployment. Its role is
+# to "hold" the network RBD block mapping that are created by the CSI driver. Essentially, it exposes
+# its network namespace into the Kubelet plugin directly and Ceph-CSI picks it up. When mapping an RBD
+# image, the Ceph-CSI driver will use the network namespace of the DaemonSet instead of its own (the plugin pod).
+# This pod is not expected to be updated nor restarted unless the node reboots.
 kind: DaemonSet
 apiVersion: apps/v1
 metadata:
diff --git a/pkg/operator/ceph/csi/version.go b/pkg/operator/ceph/csi/version.go
index 1a7f21b9e..5c27fbf5f 100644
--- a/pkg/operator/ceph/csi/version.go
+++ b/pkg/operator/ceph/csi/version.go
@@ -40,8 +40,8 @@ var (
 	// custom ceph.conf is supported in v3.5.0+
 	cephConfSupportedVersion = CephCSIVersion{3, 5, 0}
 
-	// multus fix with the extra holder pod is supported with at least v3.6.1
-	multusSupportedVersion = CephCSIVersion{3, 6, 1}
+	// pod networking fix with the extra holder pod is supported with at least v3.6.1
+	nsenterSupportedVersion = CephCSIVersion{3, 6, 1}
 
 	// for parsing the output of `cephcsi`
 	versionCSIPattern = regexp.MustCompile(`v(\d+)\.(\d+)\.(\d+)`)
@@ -131,13 +131,13 @@ func (v *CephCSIVersion) SupportsCustomCephConf() bool {
 	return v.isAtLeast(&cephConfSupportedVersion)
 }
 
-// SupportsMultus checks if the csi image has support for calling "nsenter" while executing
+// SupportsNsenter checks if the csi image has support for calling "nsenter" while executing
 // mount/map commands. This is needed for Multus scenarios.
-func (v *CephCSIVersion) SupportsMultus() bool {
+func (v *CephCSIVersion) SupportsNsenter() bool {
 	// if AllowUnsupported is set also a csi-image greater than the supported ones are allowed
 	if AllowUnsupported {
 		return true
 	}
 
-	return v.isAtLeast(&multusSupportedVersion)
+	return v.isAtLeast(&nsenterSupportedVersion)
 }


Test patch:
diff --git a/.github/workflows/canary-integration-test.yml b/.github/workflows/canary-integration-test.yml
index 558d55d7e..5f7aab2e0 100644
--- a/.github/workflows/canary-integration-test.yml
+++ b/.github/workflows/canary-integration-test.yml
@@ -1179,7 +1179,7 @@ jobs:
       run: tests/scripts/github-action-helper.sh wait_for_prepare_pod
 
     - name: wait for ceph to be ready
-      run: IS_MULTUS=true tests/scripts/github-action-helper.sh wait_for_ceph_to_be_ready osd_multus 2
+      run: IS_POD_NETWORK=true IS_MULTUS=true tests/scripts/github-action-helper.sh wait_for_ceph_to_be_ready osd_multus 2
 
     - name: wait for ceph-csi configmap to be updated with network namespace
       run: tests/scripts/github-action-helper.sh wait_for_ceph_csi_configmap_to_be_updated
@@ -1200,3 +1200,52 @@ jobs:
       if: failure() && github.event_name == 'pull_request'
       uses: mxschmitt/action-tmate@v3
       timeout-minutes: 60
+
+  csi-hostnetwork-disabled:
+    runs-on: ubuntu-18.04
+    if: "!contains(github.event.pull_request.labels.*.name, 'skip-ci')"
+    steps:
+    - name: checkout
+      uses: actions/checkout@v2
+      with:
+        fetch-depth: 0
+
+    - name: setup cluster resources
+      uses: ./.github/workflows/canary-test-config
+      with:
+        github-token: ${{ secrets.GITHUB_TOKEN }}
+
+
+    - name: use local disk and create partitions for osds
+      run: |
+        tests/scripts/github-action-helper.sh use_local_disk
+        tests/scripts/github-action-helper.sh create_partitions_for_osds
+
+    - name: deploy CSI hostNetworking disabled cluster
+      run: tests/scripts/github-action-helper.sh deploy_csi_hostnetwork_disabled_cluster
+
+    - name: wait for prepare pod
+      run: tests/scripts/github-action-helper.sh wait_for_prepare_pod
+
+    - name: wait for ceph to be ready
+      run: IS_POD_NETWORK=true tests/scripts/github-action-helper.sh wait_for_ceph_to_be_ready osd 2
+
+    - name: wait for ceph-csi configmap to be updated with network namespace
+      run: tests/scripts/github-action-helper.sh wait_for_ceph_csi_configmap_to_be_updated
+
+    - name: test ceph-csi-rbd plugin restart
+      run: tests/scripts/github-action-helper.sh test_csi_rbd_workload
+
+    - name: test ceph-csi-cephfs plugin restart
+      run: tests/scripts/github-action-helper.sh test_csi_cephfs_workload
+
+    - name: collect common logs
+      if: always()
+      uses: ./.github/workflows/collect-logs
+      with:
+        name: csi-hostnetwork-disabled
+
+    - name: setup tmate session for debugging when event is PR
+      if: failure() && github.event_name == 'pull_request'
+      uses: mxschmitt/action-tmate@v3
+      timeout-minutes: 60
diff --git a/pkg/operator/ceph/csi/spec_test.go b/pkg/operator/ceph/csi/spec_test.go
index d530e25e1..bc8c74534 100644
--- a/pkg/operator/ceph/csi/spec_test.go
+++ b/pkg/operator/ceph/csi/spec_test.go
@@ -42,9 +42,9 @@ func TestReconcileCSI_configureHolders(t *testing.T) {
 			Clientset:     testop.New(t, 1),
 			RookClientset: rookclient.NewSimpleClientset(),
 		},
-		opManagerContext: context.TODO(),
-		opConfig:         opcontroller.OperatorConfig{},
-		multusClusters:   []ClusterDetail{},
+		opManagerContext:   context.TODO(),
+		opConfig:           opcontroller.OperatorConfig{},
+		clustersWithHolder: []ClusterDetail{},
 	}
 
 	t.Run("no clusters, noop", func(t *testing.T) {
@@ -68,7 +68,7 @@ func TestReconcileCSI_configureHolders(t *testing.T) {
 			Namespace: r.opConfig.OperatorNamespace,
 		}
 
-		r.multusClusters = []ClusterDetail{
+		r.clustersWithHolder = []ClusterDetail{
 			{
 				cluster: &cephv1.CephCluster{
 					ObjectMeta: metav1.ObjectMeta{Namespace: "rook-ceph", Name: "my-cluster"},
diff --git a/pkg/operator/ceph/csi/version_test.go b/pkg/operator/ceph/csi/version_test.go
index c1ef2bbcd..6ee5b8455 100644
--- a/pkg/operator/ceph/csi/version_test.go
+++ b/pkg/operator/ceph/csi/version_test.go
@@ -114,22 +114,22 @@ func TestSupportsCustomCephConf(t *testing.T) {
 	assert.True(t, ret)
 }
 
-func TestSupportsMultus(t *testing.T) {
+func TestSupportsNsenter(t *testing.T) {
 	t.Run("AllowUnsupported=true regardless of the version", func(t *testing.T) {
 		AllowUnsupported = true
-		ret := testMinVersion.SupportsMultus()
+		ret := testMinVersion.SupportsNsenter()
 		assert.True(t, ret)
 	})
 
 	t.Run("AllowUnsupported=false and version 3.5 is too old", func(t *testing.T) {
 		AllowUnsupported = false
-		ret := testMinVersion.SupportsMultus()
+		ret := testMinVersion.SupportsNsenter()
 		assert.False(t, ret)
 	})
 
 	t.Run("AllowUnsupported=false and version 3.6.1 is fine", func(t *testing.T) {
 		AllowUnsupported = false
-		ret := testReleaseV361.SupportsMultus()
+		ret := testReleaseV361.SupportsNsenter()
 		assert.True(t, ret)
 	})
 }
diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh
index 8962e2409..7800de032 100755
--- a/tests/scripts/github-action-helper.sh
+++ b/tests/scripts/github-action-helper.sh
@@ -228,6 +228,23 @@ function deploy_cluster() {
   deploy_manifest_with_local_build toolbox.yaml
 }
 
+function deploy_csi_hostnetwork_disabled_cluster() {
+  create_cluster_prerequisites
+  cd deploy/examples
+  sed -i 's/.*CSI_ENABLE_HOST_NETWORK:.*/  CSI_ENABLE_HOST_NETWORK: \"false\"/g' operator.yaml
+  deploy_manifest_with_local_build operator.yaml
+  if [ $# == 0 ]; then
+    sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\/}|g" cluster-test.yaml
+  elif [ "$1" = "two_osds_in_device" ] ; then
+    sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\/}\n    config:\n      osdsPerDevice: \"2\"|g" cluster-test.yaml
+  elif [ "$1" = "osd_with_metadata_device" ] ; then
+    sed -i "s|#deviceFilter:|deviceFilter: ${BLOCK/\/dev\/}\n    config:\n      metadataDevice: /dev/test-rook-vg/test-rook-lv|g" cluster-test.yaml
+  fi
+  kubectl create -f cluster-test.yaml
+  kubectl create -f filesystem-test.yaml
+  deploy_manifest_with_local_build toolbox.yaml
+}
+
 function wait_for_prepare_pod() {
   get_pod_cmd=(kubectl --namespace rook-ceph get pod --no-headers)
   timeout=450
diff --git a/tests/scripts/validate_cluster.sh b/tests/scripts/validate_cluster.sh
index ac170130d..6ff47c635 100755
--- a/tests/scripts/validate_cluster.sh
+++ b/tests/scripts/validate_cluster.sh
@@ -89,17 +89,20 @@ function test_demo_pool {
 
 function test_csi {
   timeout 360 bash -x <<-'EOF'
+    echo $IS_POD_NETWORK
     echo $IS_MULTUS
-    if [ -z $IS_MULTUS ]; then
+    if [ -z "$IS_POD_NETWORK" ]; then
       until [[ "$(kubectl -n rook-ceph get pods --field-selector=status.phase=Running|grep -c ^csi-)" -eq 4 ]]; do
         echo "waiting for csi pods to be ready"
         sleep 5
       done
     else
       until [[ "$(kubectl -n rook-ceph get pods --field-selector=status.phase=Running|grep -c ^csi-)" -eq 6 ]]; do
-        echo "waiting for csi pods to be ready with multus"
+        echo "waiting for csi pods to be ready with multus or pod networking"
         sleep 5
       done
+    fi
+    if [ -n "$IS_MULTUS" ]; then
       echo "verifying csi holder interfaces (multus ones must be present)"
       kubectl -n rook-ceph exec -t ds/csi-rbdplugin-holder-my-cluster -- grep net /proc/net/dev
       kubectl -n rook-ceph exec -t ds/csi-cephfsplugin-holder-my-cluster -- grep net /proc/net/dev