democratic-csi/docs/proxy-driver.md

6.7 KiB

Proxy driver

Proxy driver allow you to run several drivers in one instance of democratic-csi.

Usually democratic-csi requires you to run a separate instance for each storage class. This is heavily implied by the CSI protocol.

However, it is still possible to have several storage classes work via a single CSI driver. The proxy driver makes the best effort to allow dynamic storage classes.

This file has user documentation for proxy driver. Technical details that are relevant only for development can be found here.

Terminology

"Proxy" is the driver created via driver: proxy in the main config. Other drivers are referred to as "real driver" or "underlying driver".

"Connection" is equivalent to a democratic-csi deployment without a proxy. Each connection has a separate .yaml config file. Each real driver is associated with a single connection name.

Compatibility

Drivers that are tested and work without issues:

  • freenas-nfs
  • freenas-iscsi
  • freenas-api-nfs
  • freenas-api-iscsi
  • zfs-generic-nfs
  • zfs-generic-iscsi
  • zfs-generic-nvmeof
  • local-hostpath

Drivers that are not tested but should work fine:

  • freenas-smb
  • freenas-api-smb
  • zfs-generic-smb
  • synology-iscsi
  • nfs-client
  • smb-client
  • lustre-client
  • node-manual
  • zfs-local-dataset
  • zfs-local-zvol

Drivers that are known to be incompatible with proxy:

  • objectivefs
  • zfs-local-ephemeral-inline

All local drivers need proxy.nodeTopology.type == node to work properly.

Config layout

Like all other drivers, proxy driver needs the main config file. See proxy.yaml example. Additionally, proxy needs config files for other drivers to be in the container filesystem.

Initially proxy doesn't know what real drivers to use. In Kubernetes you configure real drivers via parameters.connection field in a Storage Class. In other Container Orchestrators look for equivalent settings.

In the example proxy.configFolder value is /mnt/connections/. This means that proxy will look for real driver config files in this folder.

Config file must have the following name: <connection-name>.yaml.

Connection names are arbitrary, you just need to make sure that name of the config file matches connection name from the storage class.

Connection configuration can be added and updated dynamically, as long as you make sure that files mounted into democratic-csi driver container are updated.

Limitations

Proxy driver has a few limitations.

Since it provides a common interface for several drivers, these drivers need to be similar enough. For example, you can't mix local-hostpath and freenas-nfs drivers, because they simply need different modes of deployment. Generally, you can mix drivers if it's possible to switch between them by just changing config file.

Another limitation is connection name length. Connection name SHOULD be short. It is added as a prefix into Volume Handle value. Volume handles have limited maximum length. If your volume handle is already very long, adding connection name to it may cause volume creation to fail. Whether or not this is relevant at all for you depends on your real driver config. For example, snapshot handles are usually very long. Volume handle length is usually fixed, unless you customized it.

You will probably be fine when using connection name under 20 symbols. You can probably use longer names, but the shorter the better.

Another limitation is that connection name is saved in volumes. Connection name MUST be immutable. If you create a volume, and then change connection name, you will get errors at different operations. You may still be able to mount this volume, but volume size expansion or volume deletion will not work anymore. It would be analogous to deleting the whole democratic-csi deployment when not using proxy driver.

If you want to change connection name, you need to add a new config file for new connection, and create a new storage class that will use this new connection. You can then delete all volumes that are using the old connection, and only then you can delete the old connection config.

Simple k8s example

Imagine that currently you have several deployments of democratic-csi with different configs that you want to merge into a single deployment.

First set democratic-csi config values for proxy (here is a minimalistic example):

driver: proxy
proxy:
  configFolder: /mnt/connections/

Then adjust your helm values for democratic-csi deployment:

  • (optional) delete all built-in storage classes
  • (required) add extra volumes to the controller deployment
csiDriver:
  name: org.democratic-csi.proxy
controller:
  extraVolumes:
  - name: connections
    secret:
      secretName: connections
  driver:
    extraVolumeMounts:
    - name: connections
      mountPath: /mnt/connections

Then create a secret for config files that will contain real driver config later:

# don't forget to adjust namespace
kubectl create secret generic connections

Then you can deploy democratic-csi with proxy driver. Now you should have an empty deployment that works but can't create any real drivers or connect to any real backend.

Let's add connections to proxy: you need to update the connections secret. Let's say that you need 2 storage classes: nfs and iscsi. You need to have 2 separate config files for them.

# don't forget to adjust namespace
kubectl create secret generic connections \
  --from-file example-nfs.yaml=./path/to/nfs/config.yaml \
  --from-file example-iscsi.yaml=./path/to/iscsi/config.yaml \
  -o yaml --dry-run=client | kl apply -f -

As you can see, you don't need to restart democratic-csi to add or update connections. If you change the connections secret too quickly, then you may need to wait a few seconds for files to get remounted info filesystem, but no restart is needed.

Then create corresponding storage classes:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
provisioner: org.democratic-csi.proxy
reclaimPolicy: Delete
allowVolumeExpansion: true
parameters:
  connection: example-nfs
  fsType: nfs
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: iscsi
provisioner: org.democratic-csi.proxy
reclaimPolicy: Delete
allowVolumeExpansion: true
parameters:
  connection: example-iscsi
  fsType: ext4

Now you should be able to create volumes using these 2 storage classes.

Notice that storage class name does not match connection name. Also, local file names don't match connection name. This is done to make example easier to understand.

In real deployment you'll probably want to keep local file names, connection names, and mounted file names synced for easier management.