Oops! Something went wrong while submitting the form.
We use cookies to improve your browsing experience on our website, to show you personalised content and to analize our website traffic. By browsing our website, you consent to our use of cookies. Read privacy policy.
Kubernetes Volume plugins have been a great way for the third-party storage providers to support a block or file storage system by extending the Kubernetes volume interface and are “In-Tree” in nature.
In this post, we will dig into Kubernetes Container Storage Interface. We will use Hostpath CSI Driver locally on a single node bare metal cluster, to get the conceptual understanding of the CSI workflow in provisioning the Persistent Volume and its lifecycle. Also, a cool feature of snapshotting the volume and recover it back is explained.
Introduction
CSI is a standard for exposing storage systems in arbitrary block and file storage to containerized workloads on Container Orchestrations like Kubernetes, Mesos, and Cloud Foundry. It becomes very extensible for third-party storage provider to expose their new storage systems using CSI, without actually touching the Kubernetes code. Single independent implementation of CSI Driver by a storage provider will work on any orchestrator.
This new plugin mechanism has been one of the most powerful features of Kubernetes. It enables the storage vendors to:
Automatically create storage when required.
Make storage available to containers wherever they’re scheduled.
Automatically delete the storage when no longer needed.
This decoupling helps the vendors to maintain the independent release and feature cycles and focus on the API implementation without actually worrying about the backward incompatibility and to support their plugin just as easy as deploying a few pods.
Prior to CSI, k8s volume plugins have to be “In-tree”, compiled and shipped with core kubernetes binaries. This means, it will require the storage providers to check-in their into the core k8s codebase if they wish to add the support for a new storage system.
A plugin-based solution, flex-volume, tried to address this issue by exposing the exec based API for external plugins. Although it also tried to work on the similar notion of being detached with k8s binary, there were several major problems with that approach. Firstly, it needed the root access to the host and master file system to deploy the driver files.
Secondly, it comes with the huge baggage of prerequisites and OS dependencies which are assumed to be available on the host. CSI implicitly solves all these issues by being containerized and using the k8s storage primitives.
CSI has evolved as the one-stop solution addressing all the above issues which enables storage plugins to be out-of-tree and deployed via standard k8s primitives, such as PVC, PV and StorageClasses.
The main aim of introducing CSI is to establish a standard mechanism of exposing any type of storage system under-the-hood for all the container orchestrators.
Deploy the Driver Plugin
The CSI Driver comprises of a few main components which are various side cars and also the implementation of the CSI Services by the vendor, which will be understood by the Cos. The CSI Services will be described later in the blog. Let’s try out deploying hostpath CSI Driver.
Prerequisites:
Kubernetes cluster (not Minikube or Microk8s): Running version 1.13 or later
Access to the terminal with Kubectl installed
Deploying HostPath Driver Plugin:
Clone the repo of HostPath Driver Plugin locally or just copy the deploy and example folder from the root path
Checkout the master branch (if not)
The hostpath driver comprises of manifests for following side-cars: (in ./deploy/master/hostpath/) - csi-hostpath-attacher.yaml - csi-hostpath-provisioner.yaml - csi-hostpath-snapshotter.yaml - csi-hostpath-plugin.yaml: It will deploy 2 containers, one is node-driver-registrar and a hospath-plugin
The driver also includes separate Service for each component and in the deployment file with statefulsets for the containers
It also deploys Cluster-role-bindings and RBAC rules for each component, maintained in a separate repo
Each Component (side-car) is managed in a separate repository
The /deploy/util/ contains a shell script which handles the complete deployment process
After copying the folder or cloning the repo, just run:
There are resources from core apigroups, storage.k8s.io and resources which created by CRDs snapshot.storage.k8s.io and csi.storage.k8s.io.
CSI SideCars
K8s CSI containers are sidecars that simplify the development and deployment of the CSI Drivers on a k8s cluster. Different Drivers have some similar logic to trigger the appropriate operations against the “CSI volume driver” container and update the Kubernetes API as appropriate.
The common controller (common containers) has to be bundled with the provider-specific containers.
The official sig-k8s contributors maintain the following basic skeleton containers for any CSI Driver:
Note: In case of Hostpath driver, only ‘csi-hostpath-plugin’ container will be having the specific code. All the others are common CSI sidecar containers. These containers have a socket mounted in the socket-dir volume of type EmptyDir, which makes their communication possible using gRPC
External Provisioner: It is a sidecar container that watches Kubernetes PersistentVolumeClaim objects and triggers CSI CreateVolume and DeleteVolume operations against a driver endpoint. The CSI external-attacher also supports the Snapshot DataSource. If a Snapshot CRD is specified as a data source on a PVC object, the sidecar container fetches the information about the snapshot by fetching the SnapshotContent object and populates the data source field indicating to the storage system that new volume should be populated using specified snapshot.
External Attacher : It is a sidecar container that watches Kubernetes VolumeAttachment objects and triggers CSI ControllerPublish and ControllerUnpublish operations against a driver endpoint
Node-Driver Registrar: It is a sidecar container that registers the CSI driver with kubelet, and adds the drivers custom NodeId to a label on the Kubernetes Node API Object. The communication of this sidecar is handled by the ‘Identity-Service’ implemented by the driver. The CSI Driver is registered with the kubelet using its device--plugin mechanisms
External Snapshotter: It is a sidecar container that watches the Kubernetes API server for VolumeSnapshot and VolumeSnapshotContent CRD objects.The creation of a new VolumeSnapshot object referencing a SnapshotClass CRD object corresponding to this driver causes the sidecar container to provision a new snapshot.
This sidecar listens to the service which indicates the successful creation of VolumeSnapshot, and immediately creates the VolumeSnapshotContent resource
Cluster-driver Registrar: CSI driver is registered with the cluster by a sidecar container CSI cluster-driver-registrar creating a CSIDriver object. This CSIDriver enables the driver to customize the way of k8s interaction with it.
Developing a CSI Driver
To start the implementation of CSIDriver, an application must implement the gRPC services described by the CSI Specification.
The minimum service a CSI application should implement are following:
CSI Identity service: Enables Kubernetes components and CSI containers to identify the driver
CSI Node service: Required methods enable callers to make volume available at a specified path.
All the required services may be implemented independently or in the same driver application. The CSI driver application should be containerised to make it easy to deploy on Kubernetes. Once the main specific logic of the driver is containerized, they can be attached to the sidecars and deployed, in node and/or controller mode.
Capabilities
CSI also have provisions to enable the custom CSI driver to support many additional features/services by using the “Capabilities”. It contains a list of all the features the driver supports.
Note: Refer the link for detailed explanation for developing a CSI Driver.
2. Now, A PVC is also needed to be consumed by the sample Pod.
And also a sample pod is also required, so that it can be bounded with the PV created by the PVC from above step The above files are found in ./exmples directory and can be deployed using create or apply kubectl commands
csi-provisioner issuesCreateVolumeRequest call to the CSI socket, then hostpath-plugin calls CreateVolume and informs CSI about its creation
csi-provisioner creates PV and updates PVC to be bound and the VolumeAttachment object is created by controller-manager
csi-attacher which watches for VolumeAttachments submits ControllerPublishVolume rpc call to hostpath-plugin, then hostpaths-plugin gets ControllerPublishVolume and calls hostpath AttachVolumecsi-attacher update VolumeAttachment status
All this time kubelet waits for volume to be attached and submits NodeStageVolume (format and mount to the node to the staging dir) to the csi-node.hostpath-plugin
csi-node.hostpath-plugin getsNodeStageVolumecall and mounts to `/var/lib/kubelet/plugins/kubernetes.io/csi/pv/<pv-name>/globalmount`, then responses to kubelet</pv-name>
csi-node.hostpath-plugin performsNodePublishVolume and mounts the volume to `/var/lib/kubelet/pods/<pod-uuid>/volumes/</pod-uuid>kubernetes.io~csi/<pvc-name>/mount`</pvc-name>
Finally, kubelet starts container of the pod with the provisioned volume.
Let’s confirm the working of Hostpath CSI driver:
The Hostpath driver is configured to create new volumes in the hostpath container in the plugin daemonset under the ‘/tmp’ directory. This path persist as long as the DaemonSet pod is up and running.
If a file is written in the hostpath mounted volume in an application pod, should be seen in the hostpath cotainer.A file written in a properly mounted Hostpath volume inside an application should show up inside the Hostpath container.
1. To try out the above statement, Create a file on application pod
Note: The better way of the verification is to inspect the VolumeAttachment object created that represents the attached volume API object created that represents the attached volume
Support for Snapshot
Volume Snapshotting is introduced as an Alpha feature for the Kubernetes persistent volume in v1.12.
Being an alpha feature, ‘VolumeSnapshotDataSource’ feature gate needs to be enabled. This feature opens a pool of use cases of keeping the snapshot of data locally. The API objects used are VolumeSnapshot, VolumeSnapshotContent and VolumeSnapshotClass. It was developed with a similar notion and relationship of PV, PVC and StorageClass.
To create a snapshot, the VolumeSnapshot object needs to be created with the source as PVC and VolumeSnapshotClass
and the CSI-Snapshotter container will create a VolumeSnaphsotContent.
Let’s try out with an example:
Just like the provisioner create a PV for us when a PVC is created, similarly a VolumeSnapshotContent object will be created when VolumeSnapshot object is created.
The DataSource field in the PVC can accept the source of kind: VolumeSnapsot which will create a new PV from that volume snapshot, when a Pod is bound to this PVC.
The new PV will be having the same data as of the PV from which the snapshot was taken and it can be attached to any other pod. The new pod having that PV, proves of the possible “Restore” and “Cloning” use cases.
Since Kubernetes has started supporting the Raw Block Device type of Persistent Volume, hospath driver and any other driver may also support it, which will be explained in the next part of the blog. In this blog, we got deep understanding of the CSI, its components and services. The new features of CSI and the problems it solves. The CSI Hostpath driver was deeply in this blog to experiment and understand the provisioner, snapshotter flows for PV and VolumeSnapshots. Also, the PV snapshot, restore and cloning use cases were demonstrated.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Kubernetes CSI in Action: Explained with Features and Use Cases
Kubernetes Volume plugins have been a great way for the third-party storage providers to support a block or file storage system by extending the Kubernetes volume interface and are “In-Tree” in nature.
In this post, we will dig into Kubernetes Container Storage Interface. We will use Hostpath CSI Driver locally on a single node bare metal cluster, to get the conceptual understanding of the CSI workflow in provisioning the Persistent Volume and its lifecycle. Also, a cool feature of snapshotting the volume and recover it back is explained.
Introduction
CSI is a standard for exposing storage systems in arbitrary block and file storage to containerized workloads on Container Orchestrations like Kubernetes, Mesos, and Cloud Foundry. It becomes very extensible for third-party storage provider to expose their new storage systems using CSI, without actually touching the Kubernetes code. Single independent implementation of CSI Driver by a storage provider will work on any orchestrator.
This new plugin mechanism has been one of the most powerful features of Kubernetes. It enables the storage vendors to:
Automatically create storage when required.
Make storage available to containers wherever they’re scheduled.
Automatically delete the storage when no longer needed.
This decoupling helps the vendors to maintain the independent release and feature cycles and focus on the API implementation without actually worrying about the backward incompatibility and to support their plugin just as easy as deploying a few pods.
Prior to CSI, k8s volume plugins have to be “In-tree”, compiled and shipped with core kubernetes binaries. This means, it will require the storage providers to check-in their into the core k8s codebase if they wish to add the support for a new storage system.
A plugin-based solution, flex-volume, tried to address this issue by exposing the exec based API for external plugins. Although it also tried to work on the similar notion of being detached with k8s binary, there were several major problems with that approach. Firstly, it needed the root access to the host and master file system to deploy the driver files.
Secondly, it comes with the huge baggage of prerequisites and OS dependencies which are assumed to be available on the host. CSI implicitly solves all these issues by being containerized and using the k8s storage primitives.
CSI has evolved as the one-stop solution addressing all the above issues which enables storage plugins to be out-of-tree and deployed via standard k8s primitives, such as PVC, PV and StorageClasses.
The main aim of introducing CSI is to establish a standard mechanism of exposing any type of storage system under-the-hood for all the container orchestrators.
Deploy the Driver Plugin
The CSI Driver comprises of a few main components which are various side cars and also the implementation of the CSI Services by the vendor, which will be understood by the Cos. The CSI Services will be described later in the blog. Let’s try out deploying hostpath CSI Driver.
Prerequisites:
Kubernetes cluster (not Minikube or Microk8s): Running version 1.13 or later
Access to the terminal with Kubectl installed
Deploying HostPath Driver Plugin:
Clone the repo of HostPath Driver Plugin locally or just copy the deploy and example folder from the root path
Checkout the master branch (if not)
The hostpath driver comprises of manifests for following side-cars: (in ./deploy/master/hostpath/) - csi-hostpath-attacher.yaml - csi-hostpath-provisioner.yaml - csi-hostpath-snapshotter.yaml - csi-hostpath-plugin.yaml: It will deploy 2 containers, one is node-driver-registrar and a hospath-plugin
The driver also includes separate Service for each component and in the deployment file with statefulsets for the containers
It also deploys Cluster-role-bindings and RBAC rules for each component, maintained in a separate repo
Each Component (side-car) is managed in a separate repository
The /deploy/util/ contains a shell script which handles the complete deployment process
After copying the folder or cloning the repo, just run:
There are resources from core apigroups, storage.k8s.io and resources which created by CRDs snapshot.storage.k8s.io and csi.storage.k8s.io.
CSI SideCars
K8s CSI containers are sidecars that simplify the development and deployment of the CSI Drivers on a k8s cluster. Different Drivers have some similar logic to trigger the appropriate operations against the “CSI volume driver” container and update the Kubernetes API as appropriate.
The common controller (common containers) has to be bundled with the provider-specific containers.
The official sig-k8s contributors maintain the following basic skeleton containers for any CSI Driver:
Note: In case of Hostpath driver, only ‘csi-hostpath-plugin’ container will be having the specific code. All the others are common CSI sidecar containers. These containers have a socket mounted in the socket-dir volume of type EmptyDir, which makes their communication possible using gRPC
External Provisioner: It is a sidecar container that watches Kubernetes PersistentVolumeClaim objects and triggers CSI CreateVolume and DeleteVolume operations against a driver endpoint. The CSI external-attacher also supports the Snapshot DataSource. If a Snapshot CRD is specified as a data source on a PVC object, the sidecar container fetches the information about the snapshot by fetching the SnapshotContent object and populates the data source field indicating to the storage system that new volume should be populated using specified snapshot.
External Attacher : It is a sidecar container that watches Kubernetes VolumeAttachment objects and triggers CSI ControllerPublish and ControllerUnpublish operations against a driver endpoint
Node-Driver Registrar: It is a sidecar container that registers the CSI driver with kubelet, and adds the drivers custom NodeId to a label on the Kubernetes Node API Object. The communication of this sidecar is handled by the ‘Identity-Service’ implemented by the driver. The CSI Driver is registered with the kubelet using its device--plugin mechanisms
External Snapshotter: It is a sidecar container that watches the Kubernetes API server for VolumeSnapshot and VolumeSnapshotContent CRD objects.The creation of a new VolumeSnapshot object referencing a SnapshotClass CRD object corresponding to this driver causes the sidecar container to provision a new snapshot.
This sidecar listens to the service which indicates the successful creation of VolumeSnapshot, and immediately creates the VolumeSnapshotContent resource
Cluster-driver Registrar: CSI driver is registered with the cluster by a sidecar container CSI cluster-driver-registrar creating a CSIDriver object. This CSIDriver enables the driver to customize the way of k8s interaction with it.
Developing a CSI Driver
To start the implementation of CSIDriver, an application must implement the gRPC services described by the CSI Specification.
The minimum service a CSI application should implement are following:
CSI Identity service: Enables Kubernetes components and CSI containers to identify the driver
CSI Node service: Required methods enable callers to make volume available at a specified path.
All the required services may be implemented independently or in the same driver application. The CSI driver application should be containerised to make it easy to deploy on Kubernetes. Once the main specific logic of the driver is containerized, they can be attached to the sidecars and deployed, in node and/or controller mode.
Capabilities
CSI also have provisions to enable the custom CSI driver to support many additional features/services by using the “Capabilities”. It contains a list of all the features the driver supports.
Note: Refer the link for detailed explanation for developing a CSI Driver.
2. Now, A PVC is also needed to be consumed by the sample Pod.
And also a sample pod is also required, so that it can be bounded with the PV created by the PVC from above step The above files are found in ./exmples directory and can be deployed using create or apply kubectl commands
csi-provisioner issuesCreateVolumeRequest call to the CSI socket, then hostpath-plugin calls CreateVolume and informs CSI about its creation
csi-provisioner creates PV and updates PVC to be bound and the VolumeAttachment object is created by controller-manager
csi-attacher which watches for VolumeAttachments submits ControllerPublishVolume rpc call to hostpath-plugin, then hostpaths-plugin gets ControllerPublishVolume and calls hostpath AttachVolumecsi-attacher update VolumeAttachment status
All this time kubelet waits for volume to be attached and submits NodeStageVolume (format and mount to the node to the staging dir) to the csi-node.hostpath-plugin
csi-node.hostpath-plugin getsNodeStageVolumecall and mounts to `/var/lib/kubelet/plugins/kubernetes.io/csi/pv/<pv-name>/globalmount`, then responses to kubelet</pv-name>
csi-node.hostpath-plugin performsNodePublishVolume and mounts the volume to `/var/lib/kubelet/pods/<pod-uuid>/volumes/</pod-uuid>kubernetes.io~csi/<pvc-name>/mount`</pvc-name>
Finally, kubelet starts container of the pod with the provisioned volume.
Let’s confirm the working of Hostpath CSI driver:
The Hostpath driver is configured to create new volumes in the hostpath container in the plugin daemonset under the ‘/tmp’ directory. This path persist as long as the DaemonSet pod is up and running.
If a file is written in the hostpath mounted volume in an application pod, should be seen in the hostpath cotainer.A file written in a properly mounted Hostpath volume inside an application should show up inside the Hostpath container.
1. To try out the above statement, Create a file on application pod
Note: The better way of the verification is to inspect the VolumeAttachment object created that represents the attached volume API object created that represents the attached volume
Support for Snapshot
Volume Snapshotting is introduced as an Alpha feature for the Kubernetes persistent volume in v1.12.
Being an alpha feature, ‘VolumeSnapshotDataSource’ feature gate needs to be enabled. This feature opens a pool of use cases of keeping the snapshot of data locally. The API objects used are VolumeSnapshot, VolumeSnapshotContent and VolumeSnapshotClass. It was developed with a similar notion and relationship of PV, PVC and StorageClass.
To create a snapshot, the VolumeSnapshot object needs to be created with the source as PVC and VolumeSnapshotClass
and the CSI-Snapshotter container will create a VolumeSnaphsotContent.
Let’s try out with an example:
Just like the provisioner create a PV for us when a PVC is created, similarly a VolumeSnapshotContent object will be created when VolumeSnapshot object is created.
The DataSource field in the PVC can accept the source of kind: VolumeSnapsot which will create a new PV from that volume snapshot, when a Pod is bound to this PVC.
The new PV will be having the same data as of the PV from which the snapshot was taken and it can be attached to any other pod. The new pod having that PV, proves of the possible “Restore” and “Cloning” use cases.
Since Kubernetes has started supporting the Raw Block Device type of Persistent Volume, hospath driver and any other driver may also support it, which will be explained in the next part of the blog. In this blog, we got deep understanding of the CSI, its components and services. The new features of CSI and the problems it solves. The CSI Hostpath driver was deeply in this blog to experiment and understand the provisioner, snapshotter flows for PV and VolumeSnapshots. Also, the PV snapshot, restore and cloning use cases were demonstrated.
Velotio Technologies is an outsourced software product development partner for top technology startups and enterprises. We partner with companies to design, develop, and scale their products. Our work has been featured on TechCrunch, Product Hunt and more.
We have partnered with our customers to built 90+ transformational products in areas of edge computing, customer data platforms, exascale storage, cloud-native platforms, chatbots, clinical trials, healthcare and investment banking.
Since our founding in 2016, our team has completed more than 90 projects with 220+ employees across the following areas:
Building web/mobile applications
Architecting Cloud infrastructure and Data analytics platforms