Build a custom Dell CSI Driver

By on ・ Compiler un pilote Dell CSI modifié ・

With all the Dell CSI drivers and dependencies being open-source, anyone can tweak them to fit a specific use case.

This article demonstrates creating a patched version of a Dell CSI Driver for PowerScale.

The premise

As a practical example, the following steps indicate how to create a patched version of Dell CSI Driver for PowerScale that supports a longer mounted path.

The CSI Specification defines that a driver must accept a max path 128 bytes minimal :

  // SP SHOULD support the maximum path length allowed by the operating
  // system/filesystem, but, at a minimum, SP MUST accept a max path
  // length of at least 128 bytes.

Dell drivers use the library gocsi as a common boilerplate for CSI development.

That library enforces the 128 bytes maximum path length.

The PowerScale hardware supports path length up to 1023 characters as described in the File system guidelines chapter of the PowerScale spec.

Therefore, we will build a csi-powerscale driver that supports that maximum length path value.

Steps to patch a driver

Dependencies

The Dell CSI drivers are all built with golang and, obviously, run as a container. As a consequence, the pre-requisites are relatively simple, you need :

  • Golang (v1.16 minimal at the time of the publication of that post)
  • Podman or Docker
  • And optionally make to run our Makefile

Clone, Branch & Patch

The first thing to do is to clone the official csi-powerscale repository in your GOPATH source directory.

cd $GOPATH/src/github.com/
git clone [email protected]:dell/csi-powerscale.git dell/csi-powerscale
cd dell/csi-powerscale

You can then pick the version of the driver you want to patch ; git tag gives the list of versions.

This example will pick the v2.1.0 with git checkout v2.1.0 -b v2.1.0-longer-path.

The next step is to obtain the library we want to patch.

gocsi and every other open-source component maintained for Dell CSI are available on https://github.com/dell.

Picture below shows how to fork the repository on your private github. Image

Now we can get the library with:

cd $GOPATH/src/github.com/
git clone [email protected]:coulof/gocsi.git coulof/gocsi
cd coulof/gocsi

To ease the maintenance and merge of future commits, it is wise to add the original repo as an upstream branch with :

git remote add upstream [email protected]:dell/gocsi.git

The next important step is to pick and choose the correct library version used by our version of the driver.

We can check the csi-powerscale dependency file with : grep gocsi $GOPATH/src/github.com/dell/csi-powerscale/go.mod and create a branch of that version. In this case, the version is v1.5.0, and we can branch it with : git checkout v1.5.0 -b v1.5.0-longer-path.

It is now time to hack our patch ! Which is… just a oneliner :

--- a/middleware/specvalidator/spec_validator.go
+++ b/middleware/specvalidator/spec_validator.go
@@ -770,7 +770,7 @@ func validateVolumeCapabilitiesArg(
 }
 
 const (
-       maxFieldString = 128
+       maxFieldString = 1023
        maxFieldMap    = 4096
        maxFieldNodeId = 256
 )
git push --set-upstream origin v1.5.0-longer-path
git tag -a v1.5.0-longer-path
git push --tags

Build

With the patch committed and pushed, it is time to build the CSI driver binary and its container image.

Let’s go back to the csi-powerscale main repo : cd $GOPATH/src/github.com/dell/csi-powerscale

As mentioned in the introduction we can take advantage replace directive in the go.mod file to point to the patched lib.

In this case we will add the following :

iff --git a/go.mod b/go.mod
index 5c274b4..c4c8556 100644
--- a/go.mod
+++ b/go.mod
@@ -26,6 +26,7 @@ require (
 )
 
 replace (
+       github.com/dell/gocsi => github.com/coulof/gocsi v1.5.0-longer-path
        k8s.io/api => k8s.io/api v0.20.2
        k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.2
        k8s.io/apimachinery => k8s.io/apimachinery v0.20.2

Once done, we will obtain the new module from the online repo with go mod download.

Note that if you want to test the changes locally only, we can use the replace directive to point to the local directoy with :

replace github.com/dell/gocsi => ../../coulof/gocsi

We can then build our new driver binary locally with : make build

After a successful compilation, we can create the image. The shortest path to do that is to replace the csi-isilon binary from dellemc/csi-isilon docker image with :

cat << EOF > Dockerfile.patch
FROM dellemc/csi-isilon:v2.1.0
COPY "csi-isilon" .
EOF

docker build -t coulof/csi-isilon:v2.1.0-long-path -f Dockerfile.patch .          

Alternatively, you can rebuild an entire docker image using provided Makefile.

By default, the driver uses a Red Hat Universal Base Image minimal. That base image sometimes misses dependencies, so you can use another flavor like :

BASEIMAGE=registry.fedoraproject.org/fedora-minimal:latest REGISTRY=docker.io IMAGENAME=coulof/csi-powerscale IMAGETAG=v2.1.0-long-path make podman-build

The image is ready to be pushed in whatever image registry you prefer ; in this case, this is hub.docker.com : docker push coulof/csi-isilon:v2.1.0-long-path

Update CSI Kubernetes deployment

The final step is to replace the driver image used in your Kubernetes with your custom one.

Again, multiple solutions are possible, and the one to choose depends on how you deployed the driver.

If you used helm installer, you can add on top the myvalues.yaml the following block:

images:
  driver: docker.io/coulof/csi-powerscale:v2.1.0-long-path

Then update or uninstall/reinstall the driver as described in the documentation.

If you decided to use the Dell CSI Operator, you can simply point to the new image:

apiVersion: storage.dell.com/v1
kind: CSIIsilon
metadata:
  name: isilon
spec:
  driver:
    common:
      image: "docker.io/coulof/csi-powerscale:v2.1.0-long-path"
...

Or, if you want to do a quick & dirty test, you can create a patch file (here named path_csi-isilon_controller_image.yaml) with the following content:

spec:
  template:
    spec:
      containers:
      - name: driver 
        image: docker.io/coulof/csi-powerscale:v2.1.0-long-path

And apply it to your existing install with: kubectl patch deployment -n powerscale isilon-controller --patch-file path_csi-isilon_controller_image.yaml

In all cases, you can check that everything works by first making sure the Pod is started kubectl get pods -n powerscale & logs are clean : kubectl logs -n powerscale -l app=isilon-controller -c driver.

Wrap-up & disclamer

As demonstrate, thanks to the open-source it is easy to fix and improve Dell CSI drivers or Dell Container Storage Modules.

Keep in mind that Dell officially support (ticket, Service Requests, etc.) the image and binary ; not the custom build.