linode-blockstorage-csi-driver

Linode Block Storage CSI Driver Test Docker build

Overview

The Container Storage Interface (CSI) Driver for Linode Block Storage enables container orchestrators such as Kubernetes to manage the life-cycle of persistent storage claims.

More information about the Kubernetes CSI can be found in the GitHub Kubernetes CSI and CSI Spec repos.

Deployment

There are two ways of deploying CSI. The recommended way is to use Helm and second way is to use manually set secrets on the kubernetes cluster then use kubectl to deploy using the given yaml file.

Requirements

Secure a Linode API Access Token:

Generate a Personal Access Token (PAT) using the Linode Cloud Manager.

This token will need:

Use the helm chart located under ‘./helm-chart/csi-driver’. This dir has the manifest for Linode Block Storage CSI Driver.

To deploy the CSI Driver from the release artifact

export VERSION=v0.6.0
export LINODE_API_TOKEN=<linodeapitoken>
export REGION=<linoderegion>

helm install linode-csi-driver --set apiToken=$LINODE_API_TOKEN,region=$REGION https://github.com/linode/linode-blockstorage-csi-driver/releases/download/$VERSION/helm-chart-$VERSION.tgz

See helm install for command documentation.

Uninstall

To uninstall linode-csi-driver from kubernetes cluster, run the following command:

helm uninstall linode-csi-driver

See helm uninstall for command documentation.

Upgrade

To upgrade when new changes are made to the helm chart, run the following command:

export VERSION=v0.6.0
export LINODE_API_TOKEN=<linodeapitoken>
export REGION=<linoderegion>

helm upgrade linode-csi-driver --install --set apiToken=$LINODE_API_TOKEN,region=$REGION https://github.com/linode/linode-blockstorage-csi-driver/releases/download/$VERSION/helm-chart-$VERSION.tgz

See helm upgrade for command documentation.

Configurations

There are other variables that can be set to a different value. For list of all the modifiable variables/values, take a look at ‘./helm-chart/csi-driver/values.yaml’.

Values can be set/overrided by using the ‘–set var=value,…’ flag or by passing in a custom-values.yaml using ‘-f custom-values.yaml’.

Recommendation: Use custom-values.yaml to override the variables to avoid any errors with template rendering

Using Kubectl to deploy CSI

Create a kubernetes secret:

Run the following commands to stash a LINODE_TOKEN in your Kubernetes cluster:

read -s -p "Linode API Access Token: " LINODE_TOKEN
read -p "Linode Region of Cluster: " LINODE_REGION
cat <<EOF | kubectl create -f -

Paste the following text at the prompt:

apiVersion: v1
kind: Secret
metadata:
  name: linode
  namespace: kube-system
stringData:
  token: "$LINODE_TOKEN"
  region: "$LINODE_REGION"
EOF

You should receive notification that the secret was created. You can confirm this by running:

$ kubectl -n kube-system get secrets
NAME                  TYPE                                  DATA      AGE
linode          Opaque                                2         18h

Deploying CSI through kubectl:

The following command will deploy the latest version of the CSI driver with all related Kubernetes volume attachment, driver registration, and provisioning sidecars:

kubectl apply -f https://raw.githubusercontent.com/linode/linode-blockstorage-csi-driver/master/pkg/linode-bs/deploy/releases/linode-blockstorage-csi-driver.yaml

If you need a specific release of the CSI driver you can specify the release version in the URL like the following:

kubectl apply -f https://raw.githubusercontent.com/linode/linode-blockstorage-csi-driver/master/pkg/linode-bs/deploy/releases/linode-blockstorage-csi-driver-v0.5.3.yaml

This deployment is a concatenation of all of the yaml files in pkg/linode-bs/deploy/kubernetes/.

Notably, this deployment will:

Example Usage

This repository contains two manifests that demonstrate use of the Linode BlockStorage CSI. These manifests will create a PersistentVolume Claim using the linode-block-storage-retain storage class and then consume it in a minimal pod.

Once you have installed the Linode BlockStorage CSI, the following commands will run the example. Once you are finished with the example, please be sure to delete the pod, PVC, and the associated Block Storage Volume. The PVC created in this example uses the linode-block-storage-retain storage class, so you will need to remove the Block Storage Volume from your Linode account via the Cloud Manager or the Linode CLI.

kubectl create -f https://raw.githubusercontent.com/linode/linode-blockstorage-csi-driver/master/pkg/linode-bs/examples/kubernetes/csi-pvc.yaml
kubectl create -f https://raw.githubusercontent.com/linode/linode-blockstorage-csi-driver/master/pkg/linode-bs/examples/kubernetes/csi-app.yaml

Verify that the pod is running and can consume the volume:

kubectl get pvc/csi-example-pvc pods/csi-example-pod
kubectl describe pvc/csi-example-pvc pods/csi-example-pod | less

Now, let’s add some data into the PVC, delete the POD, and recreate the pod. Our data will remain intact.

$ kubectl exec -it csi-example-pod -- /bin/sh -c "echo persistence > /data/example.txt; ls -l /data"
total 20
-rw-r--r--    1 root     root            12 Dec  5 13:06 example.txt
drwx------    2 root     root         16384 Dec  5 06:03 lost+found

$ kubectl delete pods/csi-example-pod
pod "csi-example-pod" deleted

$ kubectl create -f https://raw.githubusercontent.com/linode/linode-blockstorage-csi-driver/master/pkg/linode-bs/examples/kubernetes/csi-app.yaml
pod/csi-example-pod created

$ sleep 30; kubectl exec -it csi-example-pod -- /bin/sh -c "ls -l /data; cat /data/example.txt"
total 20
-rw-r--r--    1 root     root            12 Dec  5 13:06 example.txt
drwx------    2 root     root         16384 Dec  5 06:03 lost+found
persistence

Encrypted Drives using LUKS

The ability to encrypt a PVC with a user owned secret provides an additional security layer that gives control of the data to the cluster owner instead of the platform provider.

Notes

  1. Resize is possible with similar steps to resizing PVCs on LKE and are not handled by driver. Need cryptSetup resize + resize2fs on LKE node.
  2. Key rotation process is not handled by driver but is possible via similar steps to out of band resize operations.
  3. Encryption is only possible on a new/empty PVC.
  4. LUKS key is currently pulled from a native Kubernetes secret. Take note of how your cluster handles secrets in etcd. The CSI driver is careful to otherwise keep the secret on an ephemeral tmpfs mount and otherwise refuses to continue.

Example StorageClass

Note To use an encryption key per PVC you can make a new StorageClass/Secret combination each time.

allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
  name: linode-block-storage-retain-luks
  namespace: kube-system
provisioner: linodebs.csi.linode.com
reclaimPolicy: Retain
parameters:
  linodebs.csi.linode.com/luks-encrypted: "true"
  linodebs.csi.linode.com/luks-cipher: "aes-xts-plain64"
  linodebs.csi.linode.com/luks-key-size: "512"
  csi.storage.k8s.io/node-stage-secret-namespace: csi-encrypt-example
  csi.storage.k8s.io/node-stage-secret-name: csi-encrypt-example-luks-key
---
apiVersion: v1
kind: Secret
metadata:
  name: csi-encrypt-example-luks-key
  namespace: csi-encrypt-example
stringData:
  luksKey: "SECRETGOESHERE"  

Example PVC.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-example-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: linode-block-storage-retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-example-pvcluks
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: linode-block-storage-retain-luks

Adding Tags to created volumes

This feature gives users the ability to add tags to volumes created by a specific storageClass, to allow for better tracking of volumes. Tags are added as a comma seperated string value for a parameter linodebs.csi.linode.com/volumeTags

Example StorageClass

allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
  name: linode-block-storage
  namespace: kube-system
provisioner: linodebs.csi.linode.com
parameters:
    linodebs.csi.linode.com/volumeTags: "test, foo, yolo"

Disclaimers

Contribution Guidelines

Want to improve the linode-blockstorage-csi-driver? Please start here.

Join us on Slack

For general help or discussion, join the Kubernetes Slack channel #linode.

For development and debugging, join the Gopher’s Slack channel #linodego.