linode / linode-blockstorage-csi-driver

Container Storage Interface (CSI) Driver for Linode Block Storage
Apache License 2.0
66 stars 55 forks source link

ref: Respect idempotency in CreateVolume(...) #142

Closed lgarber-akamai closed 11 months ago

lgarber-akamai commented 11 months ago

General:

This change updates the LinodeControllerServer.CreateVolume(...) logic to respect the idempotency requirements described in the CSI spec. This change should hopefully make volume creation more reliable, especially for long-running and error-prone operations like large volume cloning.

Testing:

E2E Testing

Not currently implemented, see #140.

Manual Testing

NOTE: These steps would previously fail because a pre-existing volume would not be respected by CreateVolume(...) after a timeout error.

  1. Build the OCI image and push it to an image registry:

    export REGISTRY_NAME=index.docker.io/mydockerhubuser
    export IMAGE_VERSION=dev
  2. Provision a Kubernetes cluster on Linode. (e.g. RKE2)

  3. Navigate to helm-chart/csi-driver.

  4. Update values.yaml to point to the image pushed in step 1.

  5. Deploy the Helm chart to your Kubernetes cluster:

    export KUBECONFIG=mykubeconfig.yaml
    helm install linode-bs-csi .
  6. Apply a linode-block-storage PVC and a job to populate it with random data:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: pvc-1
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
      storage: 100Gi
    storageClassName: linode-block-storage
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
    name: pvc-populator
    spec:
    template:
    spec:
      containers:
        - name: populate
          image: alpine:latest
          command: ["dd", "if=/dev/urandom", "of=/mnt/pvc/foo", "bs=1M", "count=75000"]
          volumeMounts:
            - mountPath: /mnt/pvc
              name: data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pvc-1
      restartPolicy: Never
    EOF
  7. Wait for the job to complete.

    kubectl wait --for=condition=complete job/pvc-populator 
  8. Create a new PVC cloned from the first PVC (this should take several minutes to finish)

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: pvc-2
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
      storage: 100Gi
    storageClassName: linode-block-storage
    dataSource:
    kind: PersistentVolumeClaim
    name: pvc-1
    EOF
  9. Once the corresponding Linode volume has finished provisioning, observe that the PVC is bound in Kubernetes.

  10. Ensure that only one Linode volume clone event has occurred.

  11. (Optional) Check the CSI controller logs to see the volume creation fail repeatedly until it eventually reconciles.