mapfs-csi Kubernetes Deployment

This is the generic Kubernetes bundle — static access key/secret key credentials, any supported vendor (S3/AWS, GCS, Azure, Wasabi, Aliyun, Cloudflare, Oracle, S3-compatible), on any Kubernetes cluster.

On AWS EKS and you want an AWS Marketplace-compliant install (IRSA, no static AWS credentials) instead, see /docs/k8s/eks_deploy.html — that's a separate, independently released bundle, not a variant of this one.

Two separate concerns, don't confuse them:

  • Installing the driver (once per cluster, no cloud/bucket knowledge needed) —
    a Helm chart, plus a one-per-cluster ChannelServer deployment.
  • Configuring a storage backend (repeat for every bucket/cloud you want
    to use — a single driver install can serve many of these at once) —
    plain YAML templates, applied with kubectl apply -f.

Download the Bundle

$ wget https://mapfs.cloud/dist/mapfs-csi-manifests-kubernetes-1.1.3.tar.gz
$ tar xzf mapfs-csi-manifests-kubernetes-1.1.3.tar.gz && cd mapfs-csi-manifests-kubernetes-1.1.3

Directory Layout

mapfs-csi-manifests-kubernetes-1.1.3/
├── channel-server.yaml       # ChannelServer (channeld) Deployment+Service
├── mapfs-csi-chart/          # Helm chart (also published to Docker Hub)
├── storageclass.yaml         # Dynamic-provisioning StorageClass template
├── cloud-secret.yaml         # Cloud credentials Secret template
├── pv.yaml / pvc.yaml        # Static-provisioning templates (S3, etc.)
└── azure-pv.yaml / azure-storageclass.yaml  # Azure Blob Storage examples

Prerequisites

  • A Kubernetes cluster with kubectl and helm (v3+) configured against it
  • A valid mapfs license (email + token, from https://mapfs.cloud/)
  • Access credentials for your target cloud storage (access_key/secret_key,
    or an Azure connectionString)
  • An existing bucket / container

Install the Driver

This is a one-time, per-cluster step. It doesn't need any cloud/bucket information — just your mapfs license.

  1. Deploy the ChannelServer (channeld). Every mount-daemon pod the node plugin creates connects to this for cache-invalidation fan-out; one per cluster, not per-volume:

    kubectl apply -f channel-server.yaml
    
  2. Install the chart, pointing channelServer.address at the Service from step 1 (<svc-name>.<namespace>.svc.cluster.local:<port>):

    helm install mapfs-csi oci://registry-1.docker.io/wyflow/mapfs-csi-chart --version 1.1.3 \
      --set license.email=you@example.com \
      --set license.token=<token-from-mapfs-portal> \
      --set channelServer.address=mapfs-channel.kube-system.svc.cluster.local:7777
    

    channelServer.address is required — without it, mount-daemon pods fail to start. On Graviton (arm64) nodes, also add:

      --set nodeSelector."kubernetes\.io/arch"=arm64
    

    — though this only matters for a cluster with a mix of amd64 and arm64 nodes; a homogeneous arm64 cluster works fine without it.

  3. Check status:

    kubectl -n kube-system get pod -l app=mapfs-csi-controller
    kubectl -n kube-system get pod -l app=mapfs-csi-node
    kubectl -n kube-system get pod -l app=mapfs-channel
    

To upgrade to a newer version later:

helm upgrade mapfs-csi oci://registry-1.docker.io/wyflow/mapfs-csi-chart --version <new-version>

Configure a Storage Backend

Repeat this for every bucket/cloud you want to expose to the cluster — it's independent of installing the driver, and doesn't require reinstalling or upgrading it. Every template below ships in the bundle unedited; the diffs show the minimum edits for a working example, not every available field — see each file's own comments for the rest (cache sizing, s3compatible/cloudflare/oracle-specific fields, etc).

Dynamic provisioning: storageclass.yaml + cloud-secret.yaml

Create the credentials Secret first (the StorageClass below references it by name):

kubectl create secret generic mapfs-cloud-creds -n kube-system \
  --from-literal=access_key=<AccessKeyID> \
  --from-literal=secret_key=<SecretAccessKey>

Edit storageclass.yaml:

--- storageclass.yaml
+++ storageclass.yaml
@@
   cloud: "s3"                # s3/aws | azure | gcs/google | wasabi | aliyun |
                              # cloudflare | oracle | s3compatible
-  bucket: "my-bucket-name"
+  bucket: "my-mapfs-bucket"

   # --- Required for specific clouds ---
-  # region: "us-east-1"     # required: s3/aws, gcs, wasabi, aliyun, oracle
+  region: "us-east-1"
kubectl apply -f storageclass.yaml

A PVC with storageClassName: mapfs-s3 then gets its PV created automatically — see /docs/k8s/k8s_quickstart.html for that part.

Static provisioning: pv.yaml + pvc.yaml

Edit pv.yaml:

--- pv.yaml
+++ pv.yaml
@@
-  name: __PV_NAME__                   # e.g. mapfs-prod-bucket-pv
+  name: mapfs-prod-bucket-pv
@@
     # used as the mapfs volume name passed to "mapfs mount"
     # lowercase letters, digits, hyphen and dot only, max 253 chars
-    volumeHandle: __VOLUME_NAME__
+    volumeHandle: prod-bucket-vol
@@
       # --- Cloud backend (required) ---
-      cloud: "__CLOUD__"              # s3|aws|azure|gcs|google|wasabi|aliyun|cloudflare|oracle|s3compatible
-      bucket: "__BUCKET_NAME__"
+      cloud: "s3"
+      bucket: "my-mapfs-bucket"

       # --- Cloud-specific (required for certain vendors) ---
-      # region: "__REGION__"          # s3/aws, gcs, wasabi, aliyun, oracle  e.g. us-east-1
+      region: "us-east-1"

Edit pvc.yaml (a matching Pod ships in the same file):

--- pvc.yaml
+++ pvc.yaml
@@
-  name: __PVC_NAME__                  # e.g. prod-bucket-pvc
-  namespace: __NAMESPACE__            # e.g. default | team-a
+  name: prod-bucket-pvc
+  namespace: default
@@
   storageClassName: ""                # empty = static binding to an existing PV
-  volumeName: __PV_NAME__             # must match metadata.name in pv.yaml
+  volumeName: mapfs-prod-bucket-pv
@@
-  name: __POD_NAME__                  # e.g. my-app
-  namespace: __NAMESPACE__
+  name: my-app
+  namespace: default
 spec:
   containers:
-    - name: __CONTAINER_NAME__        # e.g. app
-      image: __IMAGE__                # e.g. ubuntu:22.04
-      command: __COMMAND__            # e.g. ["sleep", "infinity"]
+    - name: app
+      image: ubuntu:22.04
+      command: ["sleep", "infinity"]
       volumeMounts:
         - name: cloud-data
-          mountPath: __MOUNT_PATH__   # path inside the container, e.g. /data
+          mountPath: /data
@@
-        claimName: __PVC_NAME__
+        claimName: prod-bucket-pvc
kubectl apply -f pv.yaml -f pvc.yaml

Azure Blob Storage: azure-storageclass.yaml / azure-pv.yaml

Credentials use connectionString, not access_key/secret_key:

kubectl create secret generic mapfs-cloud-creds -n kube-system \
  --from-literal=connectionString="DefaultEndpointsProtocol=https;AccountName=<name>;AccountKey=<key>;EndpointSuffix=core.windows.net"

Dynamic — edit azure-storageclass.yaml:

--- azure-storageclass.yaml
+++ azure-storageclass.yaml
@@
   cloud: "azure"
-  container_name: "my-container-name"   # Azure Blob Storage container name
+  container_name: "my-mapfs-container"

Static — edit azure-pv.yaml the same way pv.yaml was edited above, plus:

--- azure-pv.yaml
+++ azure-pv.yaml
@@
       cloud: "azure"
-      container_name: "__CONTAINER_NAME__"    # Azure Blob Storage container name
+      container_name: "my-mapfs-container"

Self-hosted MinIO / other S3-compatible storage

No separate template — reuse storageclass.yaml or pv.yaml with cloud: s3compatible and an endpoint:

--- storageclass.yaml (or pv.yaml's volumeAttributes)
+++
-  cloud: "s3"
-  bucket: "my-bucket-name"
+  cloud: "s3compatible"
+  bucket: "my-mapfs-bucket"
+  endpoint: "https://minio.example.com:9000"

Uninstalling

Removing a storage backend

kubectl delete -f storageclass.yaml
kubectl -n kube-system delete secret mapfs-cloud-creds

A StorageClass/PV with reclaimPolicy: Retain never deletes data in the cloud bucket — deleting the PV only removes the Kubernetes record.

Uninstalling the driver

Only do this once no storage backend depends on it anymore.

helm uninstall mapfs-csi
kubectl delete -f channel-server.yaml