Repository: rook/rook
Pull request #5032 (2020-03-17 10:50:57)

Ceph: add CSI configurations to ConfigMap
<!-- Please take a look at our [Contributing](https://rook.io/docs/rook/master/development-flow.html)
documentation before submitting a Pull Request!
Thank you for contributing to Rook! -->

**Description of your changes:**
adds all the CSI configurations to ConfigMap.
This configMap can be used in combination with Env Vars
to configure Ceph CSI drivers in rook.

Signed-off-by: Umanga Chapagain <chapagainumanga@gmail.com>

**Which issue is resolved by this Pull Request:**
Resolves # remaining parts of #4817 

**Checklist:**

- [x] Reviewed the developer guide on [Submitting a Pull Request](https://rook.io/docs/rook/master/development-flow.html#submitting-a-pull-request)
- [ ] Documentation has been updated, if necessary.
- [ ] Unit tests have been added, if necessary.
- [x] Integration tests have been added, if necessary.
- [x] Pending release notes updated with breaking and/or notable changes, if necessary.
- [ ] Upgrade from previous release is tested and upgrade user guide is updated, if necessary.
- [ ] Code generation (`make codegen`) has been run to update object specifications, if necessary.
- [x] Comments have been added or updated based on the standards set in [CONTRIBUTING.md](https://github.com/rook/rook/blob/master/CONTRIBUTING.md#comments)
- [ ] Add the flag for skipping the CI if this PR does not require a build. See [here](https://github.com/rook/rook/blob/master/INSTALL.md#skip-ci) for more details.

[test ceph]

umangachapagain: @travisn @leseb Using ConfigMap to set operator cmd flags looks tricky.

Fetching the ConfigMap requires Kubernetes Client with correct context. This Context object is only created when the operator starts. Looks like a loop to me. 

What do you suggest? (we also need to make it generic enough for everyone else to consume)

Patch:
diff --git a/.mergify.yml b/.mergify.yml
index 857b1283e..13f082d25 100644
--- a/.mergify.yml
+++ b/.mergify.yml
@@ -28,20 +28,6 @@ pull_request_rules:
         strict: false
       dismiss_reviews: {}
       delete_head_branch: {}
-  # release-1.3 branch
-  - name: automerge backport release-1.3
-    conditions:
-      - author=mergify[bot]
-      - base=release-1.3
-      - label!=do-not-merge
-      - 'status-success=DCO'
-      - 'status-success=continuous-integration/jenkins/pr-head'
-    actions:
-      merge:
-        method: merge
-        strict: false
-      dismiss_reviews: {}
-      delete_head_branch: {}
   # Trigger backport PRs based on label
   # release-1.1 branch
   - actions:
@@ -58,12 +44,4 @@ pull_request_rules:
         - release-1.2
     conditions:
       - label=backport-release-1.2
-    name: backport release-1.2
-  # release-1.3 branch
-  - actions:
-      backport:
-        branches:
-        - release-1.3
-    conditions:
-      - label=backport-release-1.3
-    name: backport release-1.3
\ No newline at end of file
+    name: backport release-1.2
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
index eacb5df34..f7f28a6ac 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -62,6 +62,7 @@ pipeline {
                 }
             }
             steps {
+                sh 'build/run make -j\$(nproc) mod.check'
                 sh 'build/run make -j\$(nproc) build.all'
             }
         }
diff --git a/Makefile b/Makefile
index a83c6ce39..57dffa54c 100644
--- a/Makefile
+++ b/Makefile
@@ -95,7 +95,7 @@ build.version:
 	@mkdir -p $(OUTPUT_DIR)
 	@echo "$(VERSION)" > $(OUTPUT_DIR)/version
 
-build.common: build.version helm.build mod.check
+build.common: build.version helm.build
 	@$(MAKE) go.init
 	@$(MAKE) go.validate
 
@@ -188,6 +188,7 @@ Targets:
     test-integration   Runs integration tests.
     mod.check          Check / Tidy current modules.
     mod.update         Update all modules.
+    vendor.check       Checks if vendor dependencies changed.
     vet                Runs lint checks on go sources.
 
 Options:
diff --git a/PendingReleaseNotes.md b/PendingReleaseNotes.md
index 7b6ddf0f1..cc8e68fbd 100644
--- a/PendingReleaseNotes.md
+++ b/PendingReleaseNotes.md
@@ -16,6 +16,8 @@
 - Specific devices for OSDs can now be specified using the full udev path (e.g. /dev/disk/by-id/ata-ST4000DM004-XXXX) instead of the device name.
 - OSD on PVC CRUSH device storage class can now be changed by setting an annotation "crushDeviceClass" on the "data" volume template. See "cluster-on-pvc.yaml" for example.
 - Rook will now refuse to create pools with replica size 1 unless `requireSafeReplicaSize` is set to false.
+- CSI drivers can now be configured using ["rook-ceph-operator-config"](https://github.com/rook/rook/blob/master/cluster/examples/kubernetes/ceph/operator.yaml) ConfigMap.
+ConfigMap can be used in mix with the already existing Env Vars defined in operator deployment manifest. Precedence will be given to ConfigMap in case of conflicting configurations.
 
 ### EdgeFS
 
diff --git a/cluster/examples/kubernetes/ceph/operator-openshift.yaml b/cluster/examples/kubernetes/ceph/operator-openshift.yaml
index f4308d1c3..1d88ea76c 100644
--- a/cluster/examples/kubernetes/ceph/operator-openshift.yaml
+++ b/cluster/examples/kubernetes/ceph/operator-openshift.yaml
@@ -90,8 +90,7 @@ users:
 ---
 # Rook Ceph Operator Config
 # Use this ConfigMap to override operator configurations
-# Precedence will be given to this config in case
-# Env Var also exists for the same
+# Precedence will be given to this config in case Env Var also exists for the same
 #
 kind: ConfigMap
 apiVersion: v1
@@ -100,10 +99,50 @@ metadata:
   # should be in the namespace of the operator
   namespace: rook-ceph
 data:
-  # # (Optional) Ceph Provisioner NodeAffinity.
+  # Enable the CSI driver.
+  # To run the non-default version of the CSI driver, see the override-able image properties in operator.yaml
+  ROOK_CSI_ENABLE_CEPHFS: "true"
+  # Enable the default version of the CSI RBD driver. To start another version of the CSI driver, see image properties below.
+  ROOK_CSI_ENABLE_RBD: "true"
+  ROOK_CSI_ENABLE_GRPC_METRICS: "true"
+  # Enable deployment of csi-snapshotter sidecar container in ceph-csi provisioner pod.
+  CSI_ENABLE_SNAPSHOTTER: "true"
+
+  # Set logging level for csi containers.
+  # Supported values from 0 to 5. 0 for general useful logs, 5 for trace level verbosity.
+  # CSI_LOG_LEVEL: "0"
+  
+  # Enable Ceph Kernel clients on kernel < 4.17 which support quotas for Cephfs
+  # If you disable the kernel client, your application may be disrupted during upgrade.
+  # See the upgrade guide: https://rook.io/docs/rook/master/ceph-upgrade.html
+  CSI_FORCE_CEPHFS_KERNEL_CLIENT: "true"
+  
+  # (Optional) Allow starting unsupported ceph-csi image
+  ROOK_CSI_ALLOW_UNSUPPORTED_VERSION: "false"
+  # The default version of CSI supported by Rook will be started. To change the version
+  # of the CSI driver to something other than what is officially supported, change
+  # these images to the desired release of the CSI driver.
+  # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v2.0.0"
+  # ROOK_CSI_REGISTRAR_IMAGE: "quay.io/k8scsi/csi-node-driver-registrar:v1.2.0"
+  # ROOK_CSI_RESIZER_IMAGE: "quay.io/k8scsi/csi-resizer:v0.4.0"
+  # ROOK_CSI_PROVISIONER_IMAGE: "quay.io/k8scsi/csi-provisioner:v1.4.0"
+  # ROOK_CSI_SNAPSHOTTER_IMAGE: "quay.io/k8scsi/csi-snapshotter:v1.2.2"
+  # ROOK_CSI_ATTACHER_IMAGE: "quay.io/k8scsi/csi-attacher:v2.1.0"
+  
+  # CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
+  # Default value is RollingUpdate.
+  # CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY: "OnDelete"
+  # CSI RBD plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
+  # Default value is RollingUpdate.
+  # CSI_RBD_PLUGIN_UPDATE_STRATEGY: "OnDelete"
+  
+  # kubelet directory path, if kubelet configured to use other than /var/lib/kubelet path.
+  # ROOK_CSI_KUBELET_DIR_PATH: "/var/lib/kubelet"
+  
+  # (Optional) Ceph Provisioner NodeAffinity.
   # CSI_PROVISIONER_NODE_AFFINITY: "role=storage-node; storage=rook, ceph"
-  # # (Optional) CEPH CSI provisioner tolerations list. Put here list of taints you want to tolerate in YAML format.
-  # # CSI provisioner would be best to start on the same nodes as other ceph daemons.
+  # (Optional) CEPH CSI provisioner tolerations list. Put here list of taints you want to tolerate in YAML format.
+  # CSI provisioner would be best to start on the same nodes as other ceph daemons.
   # CSI_PROVISIONER_TOLERATIONS: |
   #   - effect: NoSchedule
   #     key: node-role.kubernetes.io/controlplane
@@ -111,10 +150,10 @@ data:
   #   - effect: NoExecute
   #     key: node-role.kubernetes.io/etcd
   #     operator: Exists
-  # # (Optional) Ceph CSI plugin NodeAffinity.
+  # (Optional) Ceph CSI plugin NodeAffinity.
   # CSI_PLUGIN_NODE_AFFINITY: "role=storage-node; storage=rook, ceph"
-  # # (Optional) CEPH CSI plugin tolerations list. Put here list of taints you want to tolerate in YAML format.
-  # # CSI plugins need to be started on all the nodes where the clients need to mount the storage.
+  # (Optional) CEPH CSI plugin tolerations list. Put here list of taints you want to tolerate in YAML format.
+  # CSI plugins need to be started on all the nodes where the clients need to mount the storage.
   # CSI_PLUGIN_TOLERATIONS: |
   #   - effect: NoSchedule
   #     key: node-role.kubernetes.io/controlplane
@@ -122,6 +161,13 @@ data:
   #   - effect: NoExecute
   #     key: node-role.kubernetes.io/etcd
   #     operator: Exists
+  
+  # Configure CSI Ceph FS grpc and liveness metrics port
+  # CSI_CEPHFS_GRPC_METRICS_PORT: "9091"
+  # CSI_CEPHFS_LIVENESS_METRICS_PORT: "9081"
+  # Configure CSI RBD grpc and liveness metrics port
+  # CSI_RBD_GRPC_METRICS_PORT: "9090"
+  # CSI_RBD_LIVENESS_METRICS_PORT: "9080"
 ---
 # The deployment for the rook operator
 # OLM: BEGIN OPERATOR DEPLOYMENT
@@ -259,91 +305,6 @@ spec:
         - name: ROOK_ENABLE_MACHINE_DISRUPTION_BUDGET
           value: "false"
 
-        # Enable the CSI driver.
-        # To run the non-default version of the CSI driver, see the override-able image properties in operator.yaml
-        - name: ROOK_CSI_ENABLE_CEPHFS
-          value: "true"
-        - name: ROOK_CSI_ENABLE_RBD
-          value: "true"
-        - name: ROOK_CSI_ENABLE_GRPC_METRICS
-          value: "true"
-        # Enable deployment of snapshotter container in ceph-csi provisioner
-        - name: CSI_ENABLE_SNAPSHOTTER
-          value: "true"
-        # Set logging level for csi containers.
-        # Supported values from 0 to 5. 0 for general useful logs, 5 for trace level verbosity.
-        #- name: CSI_LOG_LEVEL
-        #  value: "0"
-        # Enable Ceph Kernel clients on kernel < 4.17 which support quotas for Cephfs
-        # If you disable the kernel client, your application may be disrupted during upgrade.
-        # See the upgrade guide: https://rook.io/docs/rook/v1.2/ceph-upgrade.html
-        - name: CSI_FORCE_CEPHFS_KERNEL_CLIENT
-          value: "true"
-        # The default version of CSI supported by Rook will be started. To change the version
-        # of the CSI driver to something other than what is officially supported, change
-        # these images to the desired release of the CSI driver.
-        #- name: ROOK_CSI_CEPH_IMAGE
-        #  value: "quay.io/cephcsi/cephcsi:v2.0.0"
-        #- name: ROOK_CSI_REGISTRAR_IMAGE
-        #  value: "quay.io/k8scsi/csi-node-driver-registrar:v1.2.0"
-        #- name: ROOK_CSI_RESIZER_IMAGE
-        #  value: "quay.io/k8scsi/csi-resizer:v0.4.0"
-        #- name: ROOK_CSI_PROVISIONER_IMAGE
-        #  value: "quay.io/k8scsi/csi-provisioner:v1.4.0"
-        #- name: ROOK_CSI_SNAPSHOTTER_IMAGE
-        #  value: "quay.io/k8scsi/csi-snapshotter:v1.2.2"
-        #- name: ROOK_CSI_ATTACHER_IMAGE
-        #  value: "quay.io/k8scsi/csi-attacher:v2.1.0"
-        # CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
-        # Default value is RollingUpdate.
-        #- name: CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY
-        #  value: "OnDelete"
-        # CSI Rbd plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
-        # Default value is RollingUpdate.
-        #- name: CSI_RBD_PLUGIN_UPDATE_STRATEGY
-        #  value: "OnDelete"
-        # kubelet directory path, if kubelet configured to use other than /var/lib/kubelet path.
-        #- name: ROOK_CSI_KUBELET_DIR_PATH
-        #  value: "/var/lib/kubelet"
-        # (Optional) Ceph Provisioner NodeAffinity.
-        # - name: CSI_PROVISIONER_NODE_AFFINITY
-        #   value: "role=storage-node; storage=rook, ceph"
-        # (Optional) Allow starting unsupported ceph-csi image
-        - name: ROOK_CSI_ALLOW_UNSUPPORTED_VERSION
-          value: "false"
-        # (Optional) CEPH CSI provisioner tolerations list. Put here list of taints you want to tolerate in YAML format.
-        # CSI provisioner would be best to start on the same nodes as other ceph daemons.
-        # - name: CSI_PROVISIONER_TOLERATIONS
-        #   value: |
-        #     - effect: NoSchedule
-        #       key: node-role.kubernetes.io/controlplane
-        #       operator: Exists
-        #     - effect: NoExecute
-        #       key: node-role.kubernetes.io/etcd
-        #       operator: Exists
-        # (Optional) Ceph CSI plugin NodeAffinity.
-        # - name: CSI_PLUGIN_NODE_AFFINITY
-        #   value: "role=storage-node; storage=rook, ceph"
-        # (Optional) CEPH CSI plugin tolerations list. Put here list of taints you want to tolerate in YAML format.
-        # CSI plugins need to be started on all the nodes where the clients need to mount the storage.
-        # - name: CSI_PLUGIN_TOLERATIONS
-        #   value: |
-        #     - effect: NoSchedule
-        #       key: node-role.kubernetes.io/controlplane
-        #       operator: Exists
-        #     - effect: NoExecute
-        #       key: node-role.kubernetes.io/etcd
-        #       operator: Exists
-        # Configure CSI cephfs grpc and liveness metrics port
-        #- name: CSI_CEPHFS_GRPC_METRICS_PORT
-        #  value: "9091"
-        #- name: CSI_CEPHFS_LIVENESS_METRICS_PORT
-        #  value: "9081"
-        # Configure CSI rbd grpc and liveness metrics port
-        #- name: CSI_RBD_GRPC_METRICS_PORT
-        #  value: "9090"
-        #- name: CSI_RBD_LIVENESS_METRICS_PORT
-        #  value: "9080"
         - name: ROOK_HOSTPATH_REQUIRES_PRIVILEGED
           value: "true"
 
diff --git a/cluster/examples/kubernetes/ceph/operator.yaml b/cluster/examples/kubernetes/ceph/operator.yaml
index 34db3b717..669d92c25 100644
--- a/cluster/examples/kubernetes/ceph/operator.yaml
+++ b/cluster/examples/kubernetes/ceph/operator.yaml
@@ -21,10 +21,50 @@ metadata:
   # should be in the namespace of the operator
   namespace: rook-ceph
 data:
-  # # (Optional) Ceph Provisioner NodeAffinity.
+  # Enable the CSI driver.
+  # To run the non-default version of the CSI driver, see the override-able image properties in operator.yaml
+  ROOK_CSI_ENABLE_CEPHFS: "true"
+  # Enable the default version of the CSI RBD driver. To start another version of the CSI driver, see image properties below.
+  ROOK_CSI_ENABLE_RBD: "true"
+  ROOK_CSI_ENABLE_GRPC_METRICS: "true"
+  # Enable deployment of csi-snapshotter sidecar container in ceph-csi provisioner pod.
+  CSI_ENABLE_SNAPSHOTTER: "true"
+
+  # Set logging level for csi containers.
+  # Supported values from 0 to 5. 0 for general useful logs, 5 for trace level verbosity.
+  # CSI_LOG_LEVEL: "0"
+  
+  # Enable Ceph Kernel clients on kernel < 4.17 which support quotas for Cephfs
+  # If you disable the kernel client, your application may be disrupted during upgrade.
+  # See the upgrade guide: https://rook.io/docs/rook/master/ceph-upgrade.html
+  CSI_FORCE_CEPHFS_KERNEL_CLIENT: "true"
+  
+  # (Optional) Allow starting unsupported ceph-csi image
+  ROOK_CSI_ALLOW_UNSUPPORTED_VERSION: "false"
+  # The default version of CSI supported by Rook will be started. To change the version
+  # of the CSI driver to something other than what is officially supported, change
+  # these images to the desired release of the CSI driver.
+  # ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v2.0.0"
+  # ROOK_CSI_REGISTRAR_IMAGE: "quay.io/k8scsi/csi-node-driver-registrar:v1.2.0"
+  # ROOK_CSI_RESIZER_IMAGE: "quay.io/k8scsi/csi-resizer:v0.4.0"
+  # ROOK_CSI_PROVISIONER_IMAGE: "quay.io/k8scsi/csi-provisioner:v1.4.0"
+  # ROOK_CSI_SNAPSHOTTER_IMAGE: "quay.io/k8scsi/csi-snapshotter:v1.2.2"
+  # ROOK_CSI_ATTACHER_IMAGE: "quay.io/k8scsi/csi-attacher:v2.1.0"
+  
+  # CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
+  # Default value is RollingUpdate.
+  # CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY: "OnDelete"
+  # CSI RBD plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
+  # Default value is RollingUpdate.
+  # CSI_RBD_PLUGIN_UPDATE_STRATEGY: "OnDelete"
+  
+  # kubelet directory path, if kubelet configured to use other than /var/lib/kubelet path.
+  # ROOK_CSI_KUBELET_DIR_PATH: "/var/lib/kubelet"
+  
+  # (Optional) Ceph Provisioner NodeAffinity.
   # CSI_PROVISIONER_NODE_AFFINITY: "role=storage-node; storage=rook, ceph"
-  # # (Optional) CEPH CSI provisioner tolerations list. Put here list of taints you want to tolerate in YAML format.
-  # # CSI provisioner would be best to start on the same nodes as other ceph daemons.
+  # (Optional) CEPH CSI provisioner tolerations list. Put here list of taints you want to tolerate in YAML format.
+  # CSI provisioner would be best to start on the same nodes as other ceph daemons.
   # CSI_PROVISIONER_TOLERATIONS: |
   #   - effect: NoSchedule
   #     key: node-role.kubernetes.io/controlplane
@@ -32,10 +72,10 @@ data:
   #   - effect: NoExecute
   #     key: node-role.kubernetes.io/etcd
   #     operator: Exists
-  # # (Optional) Ceph CSI plugin NodeAffinity.
+  # (Optional) Ceph CSI plugin NodeAffinity.
   # CSI_PLUGIN_NODE_AFFINITY: "role=storage-node; storage=rook, ceph"
-  # # (Optional) CEPH CSI plugin tolerations list. Put here list of taints you want to tolerate in YAML format.
-  # # CSI plugins need to be started on all the nodes where the clients need to mount the storage.
+  # (Optional) CEPH CSI plugin tolerations list. Put here list of taints you want to tolerate in YAML format.
+  # CSI plugins need to be started on all the nodes where the clients need to mount the storage.
   # CSI_PLUGIN_TOLERATIONS: |
   #   - effect: NoSchedule
   #     key: node-role.kubernetes.io/controlplane
@@ -43,6 +83,13 @@ data:
   #   - effect: NoExecute
   #     key: node-role.kubernetes.io/etcd
   #     operator: Exists
+  
+  # Configure CSI CSI Ceph FS grpc and liveness metrics port
+  # CSI_CEPHFS_GRPC_METRICS_PORT: "9091"
+  # CSI_CEPHFS_LIVENESS_METRICS_PORT: "9081"
+  # Configure CSI RBD grpc and liveness metrics port
+  # CSI_RBD_GRPC_METRICS_PORT: "9090"
+  # CSI_RBD_LIVENESS_METRICS_PORT: "9080"
 ---
 # OLM: BEGIN OPERATOR DEPLOYMENT
 apiVersion: apps/v1
@@ -208,93 +255,6 @@ spec:
         - name: ROOK_ENABLE_DISCOVERY_DAEMON
           value: "true"
 
-        # Enable the default version of the CSI CephFS driver. To start another version of the CSI driver, see image properties below.
-        - name: ROOK_CSI_ENABLE_CEPHFS
-          value: "true"
-
-        # Enable the default version of the CSI RBD driver. To start another version of the CSI driver, see image properties below.
-        - name: ROOK_CSI_ENABLE_RBD
-          value: "true"
-        - name: ROOK_CSI_ENABLE_GRPC_METRICS
-          value: "true"
-        # Enable deployment of snapshotter container in ceph-csi provisioner.
-        - name: CSI_ENABLE_SNAPSHOTTER
-          value: "true"
-        # Set logging level for csi containers.
-        # Supported values from 0 to 5. 0 for general useful logs, 5 for trace level verbosity.
-        #- name: CSI_LOG_LEVEL
-        #  value: "0"
-        # Enable Ceph Kernel clients on kernel < 4.17 which support quotas for Cephfs
-        # If you disable the kernel client, your application may be disrupted during upgrade.
-        # See the upgrade guide: https://rook.io/docs/rook/v1.2/ceph-upgrade.html
-        - name: CSI_FORCE_CEPHFS_KERNEL_CLIENT
-          value: "true"
-        # CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
-        # Default value is RollingUpdate.
-        #- name: CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY
-        #  value: "OnDelete"
-        # CSI Rbd plugin daemonset update strategy, supported values are OnDelete and RollingUpdate.
-        # Default value is RollingUpdate.
-        #- name: CSI_RBD_PLUGIN_UPDATE_STRATEGY
-        #  value: "OnDelete"
-        # The default version of CSI supported by Rook will be started. To change the version
-        # of the CSI driver to something other than what is officially supported, change
-        # these images to the desired release of the CSI driver.
-        #- name: ROOK_CSI_CEPH_IMAGE
-        #  value: "quay.io/cephcsi/cephcsi:v2.0.0"
-        #- name: ROOK_CSI_REGISTRAR_IMAGE
-        #  value: "quay.io/k8scsi/csi-node-driver-registrar:v1.2.0"
-        #- name: ROOK_CSI_RESIZER_IMAGE
-        #  value: "quay.io/k8scsi/csi-resizer:v0.4.0"
-        #- name: ROOK_CSI_PROVISIONER_IMAGE
-        #  value: "quay.io/k8scsi/csi-provisioner:v1.4.0"
-        #- name: ROOK_CSI_SNAPSHOTTER_IMAGE
-        #  value: "quay.io/k8scsi/csi-snapshotter:v1.2.2"
-        #- name: ROOK_CSI_ATTACHER_IMAGE
-        #  value: "quay.io/k8scsi/csi-attacher:v2.1.0"
-        # kubelet directory path, if kubelet configured to use other than /var/lib/kubelet path.
-        #- name: ROOK_CSI_KUBELET_DIR_PATH
-        #  value: "/var/lib/kubelet"
-        # (Optional) Ceph Provisioner NodeAffinity.
-        # - name: CSI_PROVISIONER_NODE_AFFINITY
-        #   value: "role=storage-node; storage=rook, ceph"
-        # (Optional) Allow starting unsupported ceph-csi image
-        - name: ROOK_CSI_ALLOW_UNSUPPORTED_VERSION
-          value: "false"
-        # (Optional) CEPH CSI provisioner tolerations list. Put here list of taints you want to tolerate in YAML format.
-        #  CSI provisioner would be best to start on the same nodes as other ceph daemons.
-        # - name: CSI_PROVISIONER_TOLERATIONS
-        #   value: |
-        #     - effect: NoSchedule
-        #       key: node-role.kubernetes.io/controlplane
-        #       operator: Exists
-        #     - effect: NoExecute
-        #       key: node-role.kubernetes.io/etcd
-        #       operator: Exists
-        # (Optional) Ceph CSI plugin NodeAffinity.
-        # - name: CSI_PLUGIN_NODE_AFFINITY
-        #   value: "role=storage-node; storage=rook, ceph"
-        # (Optional) CEPH CSI plugin tolerations list. Put here list of taints you want to tolerate in YAML format.
-        # CSI plugins need to be started on all the nodes where the clients need to mount the storage.
-        # - name: CSI_PLUGIN_TOLERATIONS
-        #   value: |
-        #     - effect: NoSchedule
-        #       key: node-role.kubernetes.io/controlplane
-        #       operator: Exists
-        #     - effect: NoExecute
-        #       key: node-role.kubernetes.io/etcd
-        #       operator: Exists
-        # Configure CSI cephfs grpc and liveness metrics port
-        #- name: CSI_CEPHFS_GRPC_METRICS_PORT
-        #  value: "9091"
-        #- name: CSI_CEPHFS_LIVENESS_METRICS_PORT
-        #  value: "9081"
-        # Configure CSI rbd grpc and liveness metrics port
-        #- name: CSI_RBD_GRPC_METRICS_PORT
-        #  value: "9090"
-        #- name: CSI_RBD_LIVENESS_METRICS_PORT
-        #  value: "9080"
-
         # Time to wait until the node controller will move Rook pods to other
         # nodes after detecting an unreachable node.
         # Pods affected by this setting are:
diff --git a/cmd/rook/ceph/operator.go b/cmd/rook/ceph/operator.go
index dea74a6eb..6cda5734d 100644
--- a/cmd/rook/ceph/operator.go
+++ b/cmd/rook/ceph/operator.go
@@ -46,18 +46,6 @@ func init() {
 	operatorCmd.Flags().BoolVar(&operator.EnableFlexDriver, "enable-flex-driver", true, "enable the rook flex driver")
 	operatorCmd.Flags().BoolVar(&operator.EnableDiscoveryDaemon, "enable-discovery-daemon", true, "enable the rook discovery daemon")
 
-	operatorCmd.Flags().BoolVar(&csi.EnableRBD, "csi-enable-rbd", true, "enable ceph-csi rbd support")
-	operatorCmd.Flags().BoolVar(&csi.EnableCephFS, "csi-enable-cephfs", true, "enable ceph-csi cephfs support")
-	operatorCmd.Flags().StringVar(&csi.CSIParam.DriverNamePrefix, "csi-driver-name-prefix", "", "custom csi driver name prefix")
-
-	// csi images
-	operatorCmd.Flags().StringVar(&csi.CSIParam.CSIPluginImage, "csi-ceph-image", csi.DefaultCSIPluginImage, "ceph-csi plugin image")
-	operatorCmd.Flags().StringVar(&csi.CSIParam.RegistrarImage, "csi-registrar-image", csi.DefaultRegistrarImage, "csi registrar image")
-	operatorCmd.Flags().StringVar(&csi.CSIParam.ProvisionerImage, "csi-provisioner-image", csi.DefaultProvisionerImage, "csi provisioner image")
-	operatorCmd.Flags().StringVar(&csi.CSIParam.AttacherImage, "csi-attacher-image", csi.DefaultAttacherImage, "csi attacher image")
-	operatorCmd.Flags().StringVar(&csi.CSIParam.SnapshotterImage, "csi-snapshotter-image", csi.DefaultSnapshotterImage, "csi snapshotter image")
-	operatorCmd.Flags().BoolVar(&csi.AllowUnsupported, "csi-allow-unsupported-version", false, "csi allow unsupported image version")
-
 	// csi deployment templates
 	operatorCmd.Flags().StringVar(&csi.RBDPluginTemplatePath, "csi-rbd-plugin-template-path", csi.DefaultRBDPluginTemplatePath, "path to ceph-csi rbd plugin template")
 	operatorCmd.Flags().StringVar(&csi.RBDProvisionerSTSTemplatePath, "csi-rbd-provisioner-sts-template-path", csi.DefaultRBDProvisionerSTSTemplatePath, "path to ceph-csi rbd provisioner statefulset template")
@@ -66,9 +54,6 @@ func init() {
 	operatorCmd.Flags().StringVar(&csi.CephFSPluginTemplatePath, "csi-cephfs-plugin-template-path", csi.DefaultCephFSPluginTemplatePath, "path to ceph-csi cephfs plugin template")
 	operatorCmd.Flags().StringVar(&csi.CephFSProvisionerSTSTemplatePath, "csi-cephfs-provisioner-sts-template-path", csi.DefaultCephFSProvisionerSTSTemplatePath, "path to ceph-csi cephfs provisioner statefulset template")
 	operatorCmd.Flags().StringVar(&csi.CephFSProvisionerDepTemplatePath, "csi-cephfs-provisioner-dep-template-path", csi.DefaultCephFSProvisionerDepTemplatePath, "path to ceph-csi cephfs provisioner deployment template")
-	operatorCmd.Flags().BoolVar(&csi.EnableCSIGRPCMetrics, "csi-enable-grpc-metrics", true, "enable grpc metrics in ceph-csi")
-
-	operatorCmd.Flags().StringVar(&csi.CSIParam.KubeletDirPath, "csi-kubelet-dir-path", csi.DefaultKubeletDirPath, "kubelet directory path for mounting volumes")
 
 	operatorCmd.Flags().BoolVar(&disruption.EnableMachineDisruptionBudget, "enable-machine-disruption-budget", false, "enable fencing controllers")
 
diff --git a/go.mod b/go.mod
index ad9bccce9..9b3ef66d4 100644
--- a/go.mod
+++ b/go.mod
@@ -23,6 +23,7 @@ require (
 	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.4.0
 	github.com/yanniszark/go-nodetool v0.0.0-20191206125106-cd8f91fa16be
+	golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458 // indirect
 	gopkg.in/ini.v1 v1.51.1 // indirect
 	k8s.io/api v0.17.2
 	k8s.io/apiextensions-apiserver v0.17.2
diff --git a/go.sum b/go.sum
index b0370a6bd..2209d7d42 100644
--- a/go.sum
+++ b/go.sum
@@ -55,6 +55,12 @@ github.com/aws/aws-sdk-go v1.16.26 h1:GWkl3rkRO/JGRTWoLLIqwf7AWC4/W/1hMOUZqmX0js
 github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/banzaicloud/k8s-objectmatcher v1.1.0 h1:KHWn9Oxh21xsaGKBHWElkaRrr4ypCDyrh15OB1zHtAw=
 github.com/banzaicloud/k8s-objectmatcher v1.1.0/go.mod h1:gGaElvgkqa0Lk1khRr+jel/nsCLfzhLnD3CEWozpk9k=
+github.com/banzaicloud/k8s-objectmatcher v1.1.1 h1:OWS/mUIb7HWI27pOYdxix4xu3nekNOvmS+Y3r9L5mFE=
+github.com/banzaicloud/k8s-objectmatcher v1.1.1/go.mod h1:NTk6nNix5oP7/lE/5/YxFO87+241sDmTOKvoZ9E+Muw=
+github.com/banzaicloud/k8s-objectmatcher v1.2.0 h1:ogya2/veg371s8jxWV2/NAtraMLnRqX+RELWJ8275JM=
+github.com/banzaicloud/k8s-objectmatcher v1.2.0/go.mod h1:+kRcvF2kyA0u8k9AvTYgtt8zhv30Gi8ITKdMWqh7j+A=
+github.com/banzaicloud/k8s-objectmatcher v1.2.2 h1:WekhVqrRa/wUCPuESExwRjy5R+BDTf/s7DKP99y8MvY=
+github.com/banzaicloud/k8s-objectmatcher v1.2.2/go.mod h1:+kRcvF2kyA0u8k9AvTYgtt8zhv30Gi8ITKdMWqh7j+A=
 github.com/bazelbuild/bazel-gazelle v0.18.2/go.mod h1:D0ehMSbS+vesFsLGiD6JXu3mVEzOlfUl8wNnq+x/9p0=
 github.com/bazelbuild/bazel-gazelle v0.19.1-0.20191105222053-70208cbdc798/go.mod h1:rPwzNHUqEzngx1iVBfO/2X2npKaT3tqPqqHW6rVsn/A=
 github.com/bazelbuild/buildtools v0.0.0-20190731111112-f720930ceb60/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU=
@@ -112,6 +118,7 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
 github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea h1:n2Ltr3SrfQlf/9nOna1DoGKxLx3qTSI8Ttl6Xrqp6mw=
 github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
 github.com/coreos/prometheus-operator v0.34.0 h1:TF9qaydNeUamLKs0hniaapa4FBz8U8TIlRRtJX987A4=
 github.com/coreos/prometheus-operator v0.34.0/go.mod h1:Li6rMllG/hYIyXfMuvUwhyC+hqwJVHdsDdP21hypT1M=
 github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U=
@@ -277,6 +284,7 @@ github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
@@ -383,6 +391,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
 github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
 github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -495,6 +504,7 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
@@ -502,6 +512,7 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
 github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
 github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -537,6 +548,8 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY
 github.com/pquerna/ffjson v0.0.0-20180717144149-af8b230fcd20/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
 github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
+github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8=
 github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
@@ -547,6 +560,7 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.1.0 h1:IxU7wGikQPAcoOd3/f4Ol7+vIKS1Sgu08tzjktR4nJE=
 github.com/prometheus/common v0.1.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -554,6 +568,7 @@ github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkp
 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
 github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -652,6 +667,7 @@ github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSf
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/yanniszark/go-nodetool v0.0.0-20191206125106-cd8f91fa16be h1:e8XjnroTyruokenelQLRje3D3nbti3ol45daXg5iWUA=
 github.com/yanniszark/go-nodetool v0.0.0-20191206125106-cd8f91fa16be/go.mod h1:8e/E6xP+Hyo+dJy51hlGEbJkiYl0fEzvlQdqAEcg1oQ=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0=
@@ -705,8 +721,10 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
 golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -714,6 +732,7 @@ golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -735,6 +754,8 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ym
 golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 h1:MlY3mEfbnWGmUi4rtHOtNnnnN4UJRGSyLPx+DXA5Sq4=
 golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -750,6 +771,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180117170059-2c42eef0765b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -783,6 +805,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -822,8 +845,14 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw
 golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws=
 golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458 h1:DgonIcqC7u+gVZX7lpuReBil5B/i8fvW/hAQdhT6/ao=
+golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=
 gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw=
@@ -876,6 +905,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.1.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -945,6 +975,7 @@ k8s.io/repo-infra v0.0.1-alpha.1/go.mod h1:wO1t9WaB99V80ljbeENTnayuEEwNZt7gECYh/
 k8s.io/sample-apiserver v0.17.2/go.mod h1:JLhi1DSBMlKAckfVdV1YNuz49EKNlfSflW+6LVDf1Mo=
 k8s.io/system-validators v1.0.4/go.mod h1:HgSgTg4NAGNoYYjKsUyk52gdNi2PVDswQ9Iyn66R7NI=
 k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a h1:uy5HAgt4Ha5rEMbhZA+aM1j2cq5LmR6LQ71EYC2sVH4=
 k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20190923111123-69764acb6e8e/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
@@ -960,6 +991,8 @@ mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIa
 mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
 mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY=
 sigs.k8s.io/controller-runtime v0.2.0-beta.2/go.mod h1:TSH2R0nSz4WAlUUlNnOFcOR/VUhfwBLlmtq2X6AiQCA=
+sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
+sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
 sigs.k8s.io/controller-runtime v0.5.1 h1:TNidCfVoU/cs2i+9xoTcL/l7yhl0bDhYXU0NCG6wmiE=
 sigs.k8s.io/controller-runtime v0.5.1/go.mod h1:Uojny7gvg55YLQnEGnPzRE3dC4ik2tRlZJgOUCWXAV4=
 sigs.k8s.io/controller-tools v0.2.2-0.20190919191502-76a25b63325a/go.mod h1:8SNGuj163x/sMwydREj7ld5mIMJu1cDanIfnx6xsU70=
@@ -972,6 +1005,8 @@ sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2Iem
 sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
 sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs=
 sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
+sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM=
+sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
 sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
diff --git a/pkg/operator/ceph/cluster/crash/reconcile.go b/pkg/operator/ceph/cluster/crash/reconcile.go
index b5aabcdcb..b1f265b20 100644
--- a/pkg/operator/ceph/cluster/crash/reconcile.go
+++ b/pkg/operator/ceph/cluster/crash/reconcile.go
@@ -86,22 +86,6 @@ func (r *ReconcileNode) reconcile(request reconcile.Request) (reconcile.Result,
 	node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: request.Name}}
 	err := r.client.Get(context.TODO(), request.NamespacedName, node)
 	if err != nil {
-		//if a node is not present, check if there are any crashcollector deployment for that node and delete it.
-		deploymentList := &appsv1.DeploymentList{}
-		namespaceListOpts := client.InNamespace(request.Namespace)
-		err := r.client.List(context.TODO(), deploymentList, client.MatchingLabels{k8sutil.AppAttr: AppName, NodeNameLabel: request.Name}, namespaceListOpts)
-		if err != nil {
-			logger.Errorf("failed to list crash collector deployments, delete it/them manually. %v", err)
-		}
-		for _, d := range deploymentList.Items {
-			logger.Infof("deleting deployment %q for deleted node %q", d.ObjectMeta.Name, request.Name)
-			err := r.deleteCrashCollector(d)
-			if err != nil {
-				logger.Errorf("failed to delete crash collector deployment %q, delete it manually. %v", d.Name, err)
-				continue
-			}
-			logger.Infof("crash collector deployment %q successfully removed", d.Name)
-		}
 		return reconcile.Result{}, errors.Errorf("could not get node %q", request.NamespacedName)
 	}
 
diff --git a/pkg/operator/ceph/csi/spec.go b/pkg/operator/ceph/csi/spec.go
index 1b0deedfd..844e075e4 100644
--- a/pkg/operator/ceph/csi/spec.go
+++ b/pkg/operator/ceph/csi/spec.go
@@ -23,6 +23,8 @@ import (
 	"strings"
 	"time"
 
+	controllerutil "github.com/rook/rook/pkg/operator/ceph/controller"
+
 	"github.com/pkg/errors"
 
 	"github.com/rook/rook/pkg/operator/k8sutil"
@@ -141,6 +143,10 @@ const (
 	operatorDeploymentName = "rook-ceph-operator"
 	// default log level for csi containers
 	defaultLogLevel uint8 = 0
+
+	// update strategy
+	rollingUpdate = "RollingUpdate"
+	onDelete      = "OnDelete"
 )
 
 func CSIEnabled() bool {
@@ -224,43 +230,70 @@ func StartCSIDrivers(namespace string, clientset kubernetes.Interface, ver *vers
 	tp.EnableCSIGRPCMetrics = fmt.Sprintf("%t", EnableCSIGRPCMetrics)
 
 	// If not set or set to anything but "false", the kernel client will be enabled
-	kClinet := os.Getenv("CSI_FORCE_CEPHFS_KERNEL_CLIENT")
-	if strings.EqualFold(kClinet, "false") {
+	kClient, err := k8sutil.GetOperatorSetting(clientset, controllerutil.OperatorSettingConfigMapName, "CSI_FORCE_CEPHFS_KERNEL_CLIENT", "true")
+	if err != nil {
+		return errors.Wrap(err, "failed to load CSI_FORCE_CEPHFS_KERNEL_CLIENT setting")
+	}
+	if strings.EqualFold(kClient, "false") {
 		tp.ForceCephFSKernelClient = "false"
 	} else {
 		tp.ForceCephFSKernelClient = "true"
 	}
 	// parse GRPC and Liveness ports
-	tp.CephFSGRPCMetricsPort = getPortFromENV("CSI_CEPHFS_GRPC_METRICS_PORT", DefaultCephFSGRPCMerticsPort)
-	tp.CephFSLivenessMetricsPort = getPortFromENV("CSI_CEPHFS_LIVENESS_METRICS_PORT", DefaultCephFSLivenessMerticsPort)
+	tp.CephFSGRPCMetricsPort, err = getPortFromConfig(clientset, "CSI_CEPHFS_GRPC_METRICS_PORT", DefaultCephFSGRPCMerticsPort)
+	if err != nil {
+		return errors.Wrap(err, "error getting CSI CephFS GRPC metrics port.")
+	}
+	tp.CephFSLivenessMetricsPort, err = getPortFromConfig(clientset, "CSI_CEPHFS_LIVENESS_METRICS_PORT", DefaultCephFSLivenessMerticsPort)
+	if err != nil {
+		return errors.Wrap(err, "error getting CSI CephFS liveness metrics port.")
+	}
 
-	tp.RBDGRPCMetricsPort = getPortFromENV("CSI_RBD_GRPC_METRICS_PORT", DefaultRBDGRPCMerticsPort)
-	tp.RBDLivenessMetricsPort = getPortFromENV("CSI_RBD_LIVENESS_METRICS_PORT", DefaultRBDLivenessMerticsPort)
+	tp.RBDGRPCMetricsPort, err = getPortFromConfig(clientset, "CSI_RBD_GRPC_METRICS_PORT", DefaultRBDGRPCMerticsPort)
+	if err != nil {
+		return errors.Wrap(err, "error getting CSI RBD GRPC metrics port.")
+	}
+	tp.RBDLivenessMetricsPort, err = getPortFromConfig(clientset, "CSI_RBD_LIVENESS_METRICS_PORT", DefaultRBDLivenessMerticsPort)
+	if err != nil {
+		return errors.Wrap(err, "error getting CSI RBD liveness metrics port.")
+	}
 
-	enableSnap := os.Getenv("CSI_ENABLE_SNAPSHOTTER")
+	enableSnap, err := k8sutil.GetOperatorSetting(clientset, controllerutil.OperatorSettingConfigMapName, "CSI_ENABLE_SNAPSHOTTER", "true")
+	if err != nil {
+		return errors.Wrap(err, "failed to load CSI_ENABLE_SNAPSHOTTER setting")
+	}
 	if !strings.EqualFold(enableSnap, "false") {
 		tp.EnableSnapshotter = "true"
 	}
 
-	updateStrategy := os.Getenv("CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY")
-	if strings.EqualFold(updateStrategy, "ondelete") {
-		tp.CephFSPluginUpdateStrategy = "OnDelete"
+	updateStrategy, err := k8sutil.GetOperatorSetting(clientset, controllerutil.OperatorSettingConfigMapName, "CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY", rollingUpdate)
+	if err != nil {
+		return errors.Wrap(err, "failed to load CSI_CEPHFS_PLUGIN_UPDATE_STRATEGY setting")
+	}
+	if strings.EqualFold(updateStrategy, onDelete) {
+		tp.CephFSPluginUpdateStrategy = onDelete
 	} else {
-		tp.CephFSPluginUpdateStrategy = "RollingUpdate"
+		tp.CephFSPluginUpdateStrategy = rollingUpdate
 	}
 
-	updateStrategy = os.Getenv("CSI_RBD_PLUGIN_UPDATE_STRATEGY")
-	if strings.EqualFold(updateStrategy, "ondelete") {
-		tp.RBDPluginUpdateStrategy = "OnDelete"
+	updateStrategy, err = k8sutil.GetOperatorSetting(clientset, controllerutil.OperatorSettingConfigMapName, "CSI_RBD_PLUGIN_UPDATE_STRATEGY", rollingUpdate)
+	if err != nil {
+		return errors.Wrap(err, "failed to load CSI_RBD_PLUGIN_UPDATE_STRATEGY setting")
+	}
+	if strings.EqualFold(updateStrategy, onDelete) {
+		tp.RBDPluginUpdateStrategy = onDelete
 	} else {
-		tp.RBDPluginUpdateStrategy = "RollingUpdate"
+		tp.RBDPluginUpdateStrategy = rollingUpdate
 	}
 
 	if ver.Major > KubeMinMajor || (ver.Major == KubeMinMajor && ver.Minor < provDeploymentSuppVersion) {
 		deployProvSTS = true
 	}
 
-	tp.ResizerImage = os.Getenv("ROOK_CSI_RESIZER_IMAGE")
+	tp.ResizerImage, err = k8sutil.GetOperatorSetting(clientset, controllerutil.OperatorSettingConfigMapName, "ROOK_CSI_RESIZER_IMAGE", defaultResizerImage)
+	if err != nil {
+		return errors.Wrap(err, "failed to load ROOK_CSI_RESIZER_IMAGE setting")
+	}
 	if tp.ResizerImage == "" {
 		tp.ResizerImage = defaultResizerImage
 	}
@@ -272,7 +305,11 @@ func StartCSIDrivers(namespace string, clientset kubernetes.Interface, ver *vers
 		logger.Warning("CSI Block volume expansion requires Kubernetes version >=1.16.0")
 	}
 
-	logLevel := os.Getenv("CSI_LOG_LEVEL")
+	logLevel, err := k8sutil.GetOperatorSetting(clientset, controllerutil.OperatorSettingConfigMapName, "CSI_LOG_LEVEL", "")
+	if err != nil {
+		// logging a warning and intentionally continuing with the default log level
+		logger.Warningf("failed to load CSI_LOG_LEVEL. Defaulting to %d. %v", defaultLogLevel, err)
+	}
 	tp.LogLevel = defaultLogLevel
 	if logLevel != "" {
 		l, err := strconv.ParseUint(logLevel, 10, 8)
diff --git a/pkg/operator/ceph/csi/util.go b/pkg/operator/ceph/csi/util.go
index 31bd271da..0fd0be746 100644
--- a/pkg/operator/ceph/csi/util.go
+++ b/pkg/operator/ceph/csi/util.go
@@ -19,7 +19,6 @@ package csi
 import (
 	"bytes"
 	"io/ioutil"
-	"os"
 	"path/filepath"
 	"strconv"
 	"strings"
@@ -169,19 +168,20 @@ func applyToPodSpec(pod *corev1.PodSpec, n *corev1.NodeAffinity, t []corev1.Tole
 	}
 }
 
-func getPortFromENV(env string, defaultPort uint16) uint16 {
-	port := os.Getenv(env)
+func getPortFromConfig(clientset kubernetes.Interface, env string, defaultPort uint16) (uint16, error) {
+	port, err := k8sutil.GetOperatorSetting(clientset, controller.OperatorSettingConfigMapName, env, strconv.Itoa(int(defaultPort)))
+	if err != nil {
+		return defaultPort, errors.Wrapf(err, "failed to load value for %q.", env)
+	}
 	if strings.TrimSpace(port) == "" {
-		return defaultPort
+		return defaultPort, nil
 	}
 	p, err := strconv.ParseUint(port, 10, 64)
 	if err != nil {
-		logger.Debugf("failed to parse port value for env %q. using default port %d. %v", env, defaultPort, err)
-		return defaultPort
+		return defaultPort, errors.Wrapf(err, "failed to parse port value for %q.", env)
 	}
 	if p > 65535 {
-		logger.Debugf("%s port value is greater than 65535. using default port %d for %s", port, defaultPort, env)
-		return defaultPort
+		return defaultPort, errors.Errorf("%s port value is greater than 65535 for %s.", port, env)
 	}
-	return uint16(p)
+	return uint16(p), nil
 }
diff --git a/pkg/operator/ceph/file/mds/mds.go b/pkg/operator/ceph/file/mds/mds.go
index 2737827b8..1bb6f1c5d 100644
--- a/pkg/operator/ceph/file/mds/mds.go
+++ b/pkg/operator/ceph/file/mds/mds.go
@@ -187,7 +187,7 @@ func (c *Cluster) Start() error {
 
 		if createErr != nil && kerrors.IsAlreadyExists(createErr) {
 			daemon := string(config.MdsType)
-			if err = UpdateDeploymentAndWait(c.context, d, c.fs.Namespace, daemon, daemonLetterID, c.clusterSpec.SkipUpgradeChecks, c.clusterSpec.ContinueUpgradeAfterChecksEvenIfNotHealthy); err != nil {
+			if err = UpdateDeploymentAndWait(c.context, d, c.fs.Namespace, daemon, daemonLetterID, c.clusterSpec.SkipUpgradeChecks, false); err != nil {
 				return errors.Wrapf(err, "failed to update mds deployment %s", d.Name)
 			}
 		}
diff --git a/pkg/operator/ceph/file/mds/spec.go b/pkg/operator/ceph/file/mds/spec.go
index 243a35170..6ab8c7fb5 100644
--- a/pkg/operator/ceph/file/mds/spec.go
+++ b/pkg/operator/ceph/file/mds/spec.go
@@ -86,7 +86,7 @@ func (c *Cluster) makeDeployment(mdsConfig *mdsConfig) *apps.Deployment {
 	k8sutil.AddRookVersionLabelToDeployment(d)
 	c.fs.Spec.MetadataServer.Annotations.ApplyToObjectMeta(&d.ObjectMeta)
 	controller.AddCephVersionLabelToDeployment(c.clusterInfo.CephVersion, d)
-
+	k8sutil.SetOwnerRef(&d.ObjectMeta, &c.ownerRef)
 	return d
 }
 
diff --git a/pkg/operator/ceph/object/rgw.go b/pkg/operator/ceph/object/rgw.go
index 2b3622a43..0e2b5fd1a 100644
--- a/pkg/operator/ceph/object/rgw.go
+++ b/pkg/operator/ceph/object/rgw.go
@@ -165,7 +165,7 @@ func (c *clusterConfig) startRGWPods() error {
 		// Generate the mime.types file after the rep. controller as well for the same reason as keyring
 		if createErr != nil && kerrors.IsAlreadyExists(createErr) {
 			daemon := string(config.RgwType)
-			if err := updateDeploymentAndWait(c.context, deployment, c.store.Namespace, daemon, daemonLetterID, c.skipUpgradeChecks, c.clusterSpec.ContinueUpgradeAfterChecksEvenIfNotHealthy); err != nil {
+			if err := updateDeploymentAndWait(c.context, deployment, c.store.Namespace, daemon, daemonLetterID, c.skipUpgradeChecks, false); err != nil {
 				return errors.Wrapf(err, "failed to update object store %q deployment %q", c.store.Name, deployment.Name)
 			}
 		}
diff --git a/pkg/operator/ceph/operator.go b/pkg/operator/ceph/operator.go
index 89d48a7a9..7258d7f8c 100644
--- a/pkg/operator/ceph/operator.go
+++ b/pkg/operator/ceph/operator.go
@@ -20,6 +20,7 @@ package operator
 import (
 	"os"
 	"os/signal"
+	"strconv"
 	"syscall"
 	"time"
 
@@ -30,6 +31,7 @@ import (
 	"github.com/rook/rook/pkg/daemon/ceph/agent/flexvolume/attachment"
 	"github.com/rook/rook/pkg/operator/ceph/agent"
 	"github.com/rook/rook/pkg/operator/ceph/cluster"
+	cephController "github.com/rook/rook/pkg/operator/ceph/controller"
 	"github.com/rook/rook/pkg/operator/ceph/csi"
 	"github.com/rook/rook/pkg/operator/ceph/provisioner"
 	"github.com/rook/rook/pkg/operator/discover"
@@ -179,6 +181,8 @@ func (o *Operator) startDrivers() error {
 }
 
 func (o *Operator) updateDrivers() error {
+	var err error
+
 	// Skipping CSI driver update since the first cluster hasn't been started yet
 	if !o.delayedDaemonsStarted {
 		return nil
@@ -200,6 +204,10 @@ func (o *Operator) updateDrivers() error {
 		return errors.Wrapf(err, "error getting server version")
 	}
 
+	if err = o.setCSIParams(); err != nil {
+		return errors.Wrap(err, "failed to configure CSI parameters")
+	}
+
 	if !csi.CSIEnabled() {
 		logger.Infof("CSI driver is not enabled")
 		return nil
@@ -227,3 +235,65 @@ func (o *Operator) updateDrivers() error {
 	logger.Infof("successfully started Ceph CSI driver(s)")
 	return nil
 }
+
+func (o *Operator) setCSIParams() error {
+	var err error
+
+	csiEnableRBD, err := k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_ENABLE_RBD", "true")
+	if err != nil {
+		return errors.Wrap(err, "unable to determine if CSI driver for RBD is enabled")
+	}
+	if csi.EnableRBD, err = strconv.ParseBool(csiEnableRBD); err != nil {
+		return errors.Wrap(err, "unable to parse value for 'ROOK_CSI_ENABLE_RBD'")
+	}
+
+	csiEnableCephFS, err := k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_ENABLE_CEPHFS", "true")
+	if err != nil {
+		return errors.Wrap(err, "unable to determine if CSI driver for CephFS is enabled")
+	}
+	if csi.EnableCephFS, err = strconv.ParseBool(csiEnableCephFS); err != nil {
+		return errors.Wrap(err, "unable to parse value for 'ROOK_CSI_ENABLE_CEPHFS'")
+	}
+
+	csiAllowUnsupported, err := k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_ALLOW_UNSUPPORTED_VERSION", "false")
+	if err != nil {
+		return errors.Wrap(err, "unable to determine if unsupported version is allowed")
+	}
+	if csi.AllowUnsupported, err = strconv.ParseBool(csiAllowUnsupported); err != nil {
+		return errors.Wrap(err, "unable to parse value for 'ROOK_CSI_ALLOW_UNSUPPORTED_VERSION'")
+	}
+
+	csiEnableCSIGRPCMetrics, err := k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_ENABLE_GRPC_METRICS", "true")
+	if err != nil {
+		return errors.Wrap(err, "unable to determine if CSI GRPC metrics is enabled")
+	}
+	if csi.EnableCSIGRPCMetrics, err = strconv.ParseBool(csiEnableCSIGRPCMetrics); err != nil {
+		return errors.Wrap(err, "unable to parse value for 'ROOK_CSI_ENABLE_GRPC_METRICS'")
+	}
+
+	csi.CSIParam.CSIPluginImage, err = k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_CEPH_IMAGE", csi.DefaultCSIPluginImage)
+	if err != nil {
+		return errors.Wrap(err, "unable to configure CSI plugin image")
+	}
+	csi.CSIParam.RegistrarImage, err = k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_REGISTRAR_IMAGE", csi.DefaultRegistrarImage)
+	if err != nil {
+		return errors.Wrap(err, "unable to configure CSI registrar image")
+	}
+	csi.CSIParam.ProvisionerImage, err = k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_PROVISIONER_IMAGE", csi.DefaultProvisionerImage)
+	if err != nil {
+		return errors.Wrap(err, "unable to configure CSI provisioner image")
+	}
+	csi.CSIParam.AttacherImage, err = k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_ATTACHER_IMAGE", csi.DefaultAttacherImage)
+	if err != nil {
+		return errors.Wrap(err, "unable to configure CSI attacher image")
+	}
+	csi.CSIParam.SnapshotterImage, err = k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_SNAPSHOTTER_IMAGE", csi.DefaultSnapshotterImage)
+	if err != nil {
+		return errors.Wrap(err, "unable to configure CSI snapshotter image")
+	}
+	csi.CSIParam.KubeletDirPath, err = k8sutil.GetOperatorSetting(o.context.Clientset, cephController.OperatorSettingConfigMapName, "ROOK_CSI_KUBELET_DIR_PATH", csi.DefaultKubeletDirPath)
+	if err != nil {
+		return errors.Wrap(err, "unable to configure CSI kubelet directory path")
+	}
+	return nil
+}
diff --git a/pkg/operator/k8sutil/configmap.go b/pkg/operator/k8sutil/configmap.go
index 015e1872c..fff25d3f6 100644
--- a/pkg/operator/k8sutil/configmap.go
+++ b/pkg/operator/k8sutil/configmap.go
@@ -43,7 +43,7 @@ func DeleteConfigMap(clientset kubernetes.Interface, cmName, namespace string, o
 // returns defaultValue if setting is not found
 func GetOperatorSetting(clientset kubernetes.Interface, configMapName, settingName, defaultValue string) (string, error) {
 	// config must be in operator pod namespace
-	namespace := os.Getenv("POD_NAMESPACE")
+	namespace := os.Getenv(PodNamespaceEnvVar)
 	cm, err := clientset.CoreV1().ConfigMaps(namespace).Get(configMapName, metav1.GetOptions{})
 	if err != nil {
 		if apierrors.IsNotFound(err) {
diff --git a/pkg/operator/k8sutil/deployment.go b/pkg/operator/k8sutil/deployment.go
index dc9e95f97..01897c8b5 100644
--- a/pkg/operator/k8sutil/deployment.go
+++ b/pkg/operator/k8sutil/deployment.go
@@ -118,15 +118,6 @@ func UpdateDeploymentAndWait(context *clusterd.Context, modifiedDeployment *apps
 
 				return d, nil
 			}
-
-			// If ProgressDeadlineExceeded is reached let's fail earlier
-			// This can happen if one of the deployment cannot be scheduled on a node and stays in "pending" state
-			for _, condition := range d.Status.Conditions {
-				if condition.Type == v1.DeploymentProgressing && condition.Reason == "ProgressDeadlineExceeded" {
-					return nil, fmt.Errorf("gave up waiting for deployment %q to update because %q", modifiedDeployment.Name, condition.Reason)
-				}
-			}
-
 			logger.Debugf("deployment %q status=%+v", d.Name, d.Status)
 			time.Sleep(time.Duration(sleepTime) * time.Second)
 		}


Test patch:
diff --git a/pkg/operator/ceph/csi/util_test.go b/pkg/operator/ceph/csi/util_test.go
index 670aab7d7..47080d7c8 100644
--- a/pkg/operator/ceph/csi/util_test.go
+++ b/pkg/operator/ceph/csi/util_test.go
@@ -22,6 +22,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"k8s.io/client-go/kubernetes/fake"
 )
 
 var (
@@ -115,31 +116,42 @@ func TestStatefulSetTemplate(t *testing.T) {
 	assert.Nil(t, err)
 }
 
-func Test_getPortFromENV(t *testing.T) {
+func Test_getPortFromConfig(t *testing.T) {
+	k8s := fake.NewSimpleClientset()
+
 	var key = "TEST_CSI_PORT_ENV"
 	var defaultPort uint16 = 8000
-	// emtpty env variable
-	port := getPortFromENV(key, defaultPort)
+
+	// empty env variable
+	port, err := getPortFromConfig(k8s, key, defaultPort)
+	assert.Nil(t, err)
 	assert.Equal(t, port, defaultPort)
+
 	// valid port is set in env
-	err := os.Setenv(key, "9000")
+	err = os.Setenv(key, "9000")
+	assert.Nil(t, err)
+	port, err = getPortFromConfig(k8s, key, defaultPort)
 	assert.Nil(t, err)
-	port = getPortFromENV(key, defaultPort)
 	assert.Equal(t, port, uint16(9000))
+
 	err = os.Unsetenv(key)
 	assert.Nil(t, err)
 	// higher port value is set in env
 	err = os.Setenv(key, "65536")
 	assert.Nil(t, err)
-	port = getPortFromENV(key, defaultPort)
+	port, err = getPortFromConfig(k8s, key, defaultPort)
+	assert.Error(t, err)
 	assert.Equal(t, port, defaultPort)
+
 	err = os.Unsetenv(key)
 	assert.Nil(t, err)
 	// negative port is set in env
 	err = os.Setenv(key, "-1")
 	assert.Nil(t, err)
-	port = getPortFromENV(key, defaultPort)
+	port, err = getPortFromConfig(k8s, key, defaultPort)
+	assert.Error(t, err)
 	assert.Equal(t, port, defaultPort)
+
 	err = os.Unsetenv(key)
 	assert.Nil(t, err)
 }
diff --git a/tests/framework/installer/ceph_manifests.go b/tests/framework/installer/ceph_manifests.go
index d40da1e16..f6176e3f7 100644
--- a/tests/framework/installer/ceph_manifests.go
+++ b/tests/framework/installer/ceph_manifests.go
@@ -1498,15 +1498,19 @@ spec:
             fieldRef:
               fieldPath: metadata.namespace
         - name: ROOK_ENABLE_FLEX_DRIVER
-          value: "true"
-        - name: ROOK_CSI_ENABLE_CEPHFS
-          value: "true"
-        - name: ROOK_CSI_ENABLE_RBD
-          value: "true"
-        - name: ROOK_CSI_ENABLE_GRPC_METRICS
-          value: "true"
+          value: "false"
         - name: ROOK_CURRENT_NAMESPACE_ONLY
           value: "false"
+---
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: rook-ceph-operator-config
+  namespace: ` + namespace + `
+data:
+  ROOK_CSI_ENABLE_CEPHFS: "true"
+  ROOK_CSI_ENABLE_RBD: "true"
+  ROOK_CSI_ENABLE_GRPC_METRICS: "true"
 `
 }
 
diff --git a/tests/framework/installer/ceph_manifests_v1.1.go b/tests/framework/installer/ceph_manifests_v1.1.go
index 2fc9d289f..c855c50f4 100644
--- a/tests/framework/installer/ceph_manifests_v1.1.go
+++ b/tests/framework/installer/ceph_manifests_v1.1.go
@@ -1322,13 +1322,7 @@ spec:
             fieldRef:
               fieldPath: metadata.namespace
         - name: ROOK_ENABLE_FLEX_DRIVER
-          value: "true"
-        - name: ROOK_CSI_ENABLE_CEPHFS
-          value: "true"
-        - name: ROOK_CSI_ENABLE_RBD
-          value: "true"
-        - name: ROOK_CSI_ENABLE_GRPC_METRICS
-          value: "true"
+          value: "false"
 ---
 kind: ClusterRoleBinding
 apiVersion: rbac.authorization.k8s.io/v1beta1
@@ -1373,6 +1367,16 @@ rules:
   - "*"
   resources:
   - "*"
+---
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: rook-ceph-operator-config
+  namespace: ` + namespace + `
+data:
+  ROOK_CSI_ENABLE_CEPHFS: "true"
+  ROOK_CSI_ENABLE_RBD: "true"
+  ROOK_CSI_ENABLE_GRPC_METRICS: "true"
 `
 }