<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>PVC Protection on Digi Hunch</title><link>https://static.digihunch.com/tag/pvc-protection/</link><description>Recent content in PVC Protection on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Mon, 28 Apr 2025 14:08:06 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/pvc-protection/index.xml" rel="self" type="application/rss+xml"/><item><title>Kubernetes Storage Explained – from in-tree plugin to CSI</title><link>https://static.digihunch.com/2021/06/kubernetes-storage-explained/</link><pubDate>Sat, 12 Jun 2021 21:55:46 -0400</pubDate><guid>https://static.digihunch.com/2021/06/kubernetes-storage-explained/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/feature-k8s-csi.webp" alt="Featured image of post Kubernetes Storage Explained – from in-tree plugin to CSI" /&gt;&lt;p class="wp-block-paragraph"&gt;To support a variety of storage backend, Kubernetes abstract storage issues with several objects (&lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/"&gt;volume&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/"&gt;persistent volume&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims"&gt;persistent volume claim&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/"&gt;storage class&lt;/a&gt;) and adopts &lt;a href="https://github.com/container-storage-interface/spec/blob/master/spec.md"&gt;container storage interface&lt;/a&gt;. Unfortunately, the documents are not very well organized to deliver the idea of these concepts, most likely because features are introduced at very different times. Hence this article. At the bottom of this article, I also go through five examples of using volumes in different ways, taking azure disk (SSD as an example).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The first to think about is whether we need just ephemeral storage or persistent storage. Generic volume with ephemeral storage lives and dies with the Pod and we don&amp;#8217;t really care where it is from. With persistent storage, we need to consider where it is from and how to create (provision) the storage. The storage can be created statically or dynamically.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-persistentvolume-pv-and-persistentvolumeclaim-pvc"&gt;PersistentVolume (PV) and PersistentVolumeClaim (PVC)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Regardlessly of static or dynamic storage provision, we first need to understand two objects before getting to that: Persistent Volume (PV) and Persistent Volume Claim (PVC). &lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;We use PV object to represent external storage volume. A single external storage volume can be represented by a single PV. So PV goes with external volumes in 1 to 1 relationship. A 100G volume cannot be represented by two PVs each with 50G, unless the storage administrator divides it into two separate volumes, each with 50G.&lt;/li&gt;&#10;&lt;li&gt;PVC goes with Pod in 1 to 1 relationship. The Pods needs a PVC in order to claim ownership of a PV. A valid PVC allows a Pod to mount a PV as its volume.&lt;/li&gt;&#10;&lt;li&gt;Here we call storage volume external in relative to the pods. If the storage volume is mapped to a directory on the host file system, it is still considered an external storage.&lt;/li&gt;&#10;&lt;li&gt;A single PV can link to multiple PVCs, so long as the total request in PVCs does not exceed PV&amp;#8217;s capacity. So PV and PVC are in 1 to many relationship.&lt;/li&gt;&#10;&lt;li&gt;How PVC binds to PV is defined by Access Mode, with three options. Note that the options are effective for the entire PV. You cannot have different options for each PVC linked to a PV:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;RWO (ReadWriteOnce): allowing the PV to be bound to a single PVC (for read write). This mode is typically used in block storage;&lt;/li&gt;&#10;&lt;li&gt;RWM (ReadWriteMany): allowing the PV to be bound to multiple PVCs (for read write). This mode is only supported by file (e.g. NFS) and object storage;&lt;/li&gt;&#10;&lt;li&gt;ROM (ReadOnlyMany): allowing the PV bound to multiple PVCs for read only.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;When a PVC is released, what to do with the PV is defined as persistentVolumeReclaimPolicy, and the two options (effective at PV level) are:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Delete&lt;/li&gt;&#10;&lt;li&gt;Retain&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 class="wp-block-heading" id="h-static-provisioning-and-dynamic-provisioning"&gt;Static Provisioning and Dynamic Provisioning&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With static provisioning, the external storage volume must be pre-created. In this context, a PV object represents a pre-created external storage volume. So PVs must be explicit declared. The K8s literature also refers to such PVs as pre-created PV.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With dynamic provisioning, the external storage volume is provisioned dynamically. Therefore, you do not need to explicitly create PVs. By the same token, access mode does not apply. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Instead of PV, now we need to explicitly declare storage class, which specifies how to dynamically provision PVs, with the following properties:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;volumeBindingMode defines when the binding and provisioning of a PersistentVolume occurs, with two options:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Immediate (default)&lt;/li&gt;&#10;&lt;li&gt;WaitForFirstConsumer (recommended): delays until a Pod using the PVC is created&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;reclaimPolicy (the equivalent of persistentVolumeReclaimPolicy for pre-created PV) with two options:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Delete (default)&lt;/li&gt;&#10;&lt;li&gt;Retain&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;provisioners: determines what volume plugin is used for provisioning PVs. There are two categories:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;Internal provisioner &lt;/strong&gt;(prefixed with kubernetes.io): common ones are listed &lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner"&gt;here&lt;/a&gt;. Note that there isn&amp;#8217;t an internal &lt;a href="https://github.com/kubernetes-retired/external-storage"&gt;provisioner for NFS &lt;/a&gt;any more. External NFS provisioner is needed.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;External provisioner&lt;/strong&gt;: third-party out-of-tree plugins compliant to CSI. For example: Dell &lt;a href="https://github.com/dell/csi-xtremio-deploy"&gt;XtremIO&lt;/a&gt; CSI plugin, Dell &lt;a href="https://github.com/dell/csi-powerscale"&gt;Isilon&lt;/a&gt; plugin, &lt;a href="https://github.com/purestorage/pso-csi"&gt;PureStorage&lt;/a&gt; CSI driver, Scality &lt;a href="file:///Users/yi.lu/Downloads/artesca_wp_v4.pdf"&gt;Artesca&lt;/a&gt; (launched in Apr 2021), and NetApp &lt;a href="https://netapp-trident.readthedocs.io/en/stable-v19.01/index.html"&gt;Trident&lt;/a&gt; CSI drivers, and &lt;a href="https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner"&gt;NFS subdir provisioner&lt;/a&gt; in Kubernetes-sigs repo.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/#parameters"&gt;parameters&lt;/a&gt;: each provisioner has its own set of mandatory and optional parameters;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/#allow-volume-expansion"&gt;allowVolumeExpansion&lt;/a&gt;: can be set to true if the underlying storage class supports volume expansion;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/#mount-options"&gt;mountOptions&lt;/a&gt;: specify only if the storage class supports it;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With the information above, we can simplify the rules as follows:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;In static provisioning, PV needs to be declared explicitly and SC is not needed&lt;/li&gt;&#10;&lt;li&gt;In dynamic provisioning, SC is required so we can specify provisioner and the parameters needed by the provisioner. PV doesn&amp;#8217;t need to be explicitly declared, even though it exists in the interaction.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In real life however, you might come across the following edge cases which seems to contradict with the two generic rules above:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/storage/storage-classes/#local"&gt;Local volume&lt;/a&gt;, currently does not support dynamic provisioning. However a StorageClass should still be created to delay volume binding until Pod scheduling. The volume binding mode &lt;em&gt;WaitForFirstConsumer&lt;/em&gt;&amp;nbsp;should be specified.&lt;/li&gt;&#10;&lt;li&gt;In dynamic provisioning, if a PVC does not explicitly define PVC, the administrator should have specified a &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#dynamic"&gt;default StorageClass&lt;/a&gt; in place for the cluster. You might also come across PVC with empty string (&amp;#8220;&amp;#8221;) as storageClassName, which indicates that &lt;span style="text-decoration: underline;"&gt;no storage class will be used&lt;/span&gt; (i.e. dynamic provisioning is disabled for the PVC). According to &lt;a href="https://kubernetes.io/blog/2017/03/dynamic-provisioning-and-storage-classes-kubernetes/"&gt;this&lt;/a&gt; post, in a PVC:&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;If storageClassName=&amp;#8221;&amp;#8221;, then it is static provisioning&lt;/li&gt;&#10;&lt;li&gt;If storageClassName is not specified, then the default storage class will be used. &lt;/li&gt;&#10;&lt;li&gt;If storageClassName is set to a specific value, then the matching storageClassName will be considered. If no corresponding storage class exists, the PVC will fail.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-the-confusing-volumes"&gt;The confusing &amp;#8220;Volumes&amp;#8221;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We&amp;#8217;ve discussed PersistentVolume, which is a K8s object that represents an external storage volume. When the word Volume stands by itself, it generally refers to the part of storage exposed to the Kubernetes cluster, no matter what type of storage it is or where it comes from. We can distinguish them in the following table:&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-regular"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Generic &lt;strong&gt;Volumes&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Persistent Volumes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pod assignment&lt;/td&gt;&lt;td&gt;Bound to a single pod, declared as part of a Pod.&lt;/td&gt;&lt;td&gt;A standalone resource type decoupled from Pod and can be bound to single, or multiple Pods via PVC&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Lifecycle&lt;/td&gt;&lt;td&gt;Volume is deleted as the owner Pod dies. Data on the volume may or may not persist.&lt;/td&gt;&lt;td&gt;Assuming PVC is gone with Pod, the PV persists. Data on PV may or may not persist depending on ReclaimPolicy.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Configuration&lt;/td&gt;&lt;td&gt;Pod creator (e.g. app developer) needs to know the details of storage resource in the cloud environment. (e.g volume ID)&lt;/td&gt;&lt;td&gt;Pod creator does not need the details of storage resource in the cloud environment. K8s Cluster administrator can provision PV, either statically or dynamically for Pod creator.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If you want to use PeristentVolume to back a Volume in Pod, you&amp;#8217;d have to use PersistentVolumeClaim. This means, some types of volumes (including hostPath) can be both mounted as a persistent volume as well as a regular volume. To compare the two ways of mount volume (direct vs via PVC), we take a look at the Kubernetes configuration &lt;a href="https://github.com/kubernetes/examples/tree/master/staging/volumes/azure_disk"&gt;examples&lt;/a&gt; for Azure Disk. The examples are provided at the bottom of this post. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that, no matter which method of using the volumes, some types of volumes just work natively, and some requires plugin to operate. The table below summarizes the mechanism behind common volume types.&lt;/p&gt;&#10;&lt;figure class="wp-block-table is-style-regular"&gt;&lt;table class="has-background" style="background-color:#e9fbe5"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Volume Types&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Mechanism&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Mountable as &lt;strong&gt;non-persistent volume&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;mountable as &lt;strong&gt;persistent volume&lt;/strong&gt; (through PVC or SC)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;emptyDir &lt;/td&gt;&lt;td&gt;A native volume type, for temporary data only. Data is wiped along with volume. The storage media is determined by the medium of the filsystem holding the kubelet root dir (typically /var/lib/kubelet). You can even set emptyDir.medium to &amp;#8220;Memory&amp;#8221;&lt;/td&gt;&lt;td&gt;YES&lt;/td&gt;&lt;td&gt;NO. By definition, emptyDir is not persistent.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ConfigMap, Secret&lt;/td&gt;&lt;td&gt;Native volume type to store non-sensitive or sensitive configuration data. ConfigMap and Secrets are stored in etcd.&lt;/td&gt;&lt;td&gt;YES&lt;/td&gt;&lt;td&gt;NO. However, by nature, ConfigMap and Secret are stored persistently. There is no need to mount them as PV.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HostPath&lt;/td&gt;&lt;td&gt;A native volume type to mount a file or directory from the host node&amp;#8217;s filesystem into the Pod. In addition to path property, you may optionally specify a type for a hostPath volume (e.g. DirectoryOrCreate, Directory, FileOrCreate, etc). Note that there is also a type named empty string (&amp;#8220;&amp;#8221;) which is the default value. It means means that no checks will be performed before mounting the hostPath volume. &lt;br&gt;In addition to the &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#hostpath"&gt;caveat&lt;/a&gt; with using hostPath from the documentation, we also need to understand that: &lt;br&gt;1. HostPath gives Pod the ability to maliciously modify files on the host system, or simply fill up the host file system;&lt;br&gt;2. As the document suggests, you may end up with multiple Pods trying to write simultaneously to a host path.&lt;/td&gt;&lt;td&gt;YES. Read &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#hostpath"&gt;this&lt;/a&gt;.&lt;/td&gt;&lt;td&gt;YES. Check out &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumes-typed-hostpath"&gt;PersistentVolumes typed hostPath&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Local&lt;/td&gt;&lt;td&gt;It represents a mounted local storage device such as a disk, partition, or directory. Compared to hostPath volumes, local volumes are used in a durable and portable manner, without manually scheduling pods to nodes. The system is aware of the volume&amp;#8217;s node constraints by looking at the node affinity on the PV. You must set nodeAffinity on the PV when using local volumes. This also means local volumes are subject to the availability of the underlying node. Refer to &lt;a href="https://kubernetes.io/blog/2019/04/04/kubernetes-1.14-local-persistent-volumes-ga/#how-is-it-different-from-a-hostpath-volume"&gt;this&lt;/a&gt; post.&lt;br&gt;This is also referred to as &lt;a href="https://kubernetes.io/blog/2019/04/04/kubernetes-1.14-local-persistent-volumes-ga/#what-is-a-local-persistent-volume"&gt;Local persistent Volume&lt;/a&gt;.&lt;/td&gt;&lt;td&gt;NO&lt;/td&gt;&lt;td&gt;YES. Static provisioning only. &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CephFS, NFS, GlusterFS, Ginder, RBD, FC, iSCSI&amp;#8230;&amp;#8230;&lt;/td&gt;&lt;td&gt;These volume types are backed by legacy in-tree plugins. They are used to connect to external storage in self-hosted clusters.&lt;/td&gt;&lt;td&gt;YES&lt;/td&gt;&lt;td&gt;YES&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;awsElasticBlockStore, AzureDisk, AzureFile, GCEPersistentDisk&lt;/td&gt;&lt;td&gt;These volume types are backed by legacy in-tree plugins. They are used to connect to external storage in public cloud&lt;/td&gt;&lt;td&gt;YES&lt;/td&gt;&lt;td&gt;YES&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Note&lt;/strong&gt; that the table above does not list &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim"&gt;PersistenVolumeClaim&lt;/a&gt; as a volume type, because it obviously only support being mounted as persistent volume.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-from-in-tree-plugins-to-out-of-tree-csi-plugins"&gt;From in-tree plugins to out-of-tree CSI plugins&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the table above, the bottom two rows involves in-tree plugins (aka built-in plugins). In-tree means the volume plugins are built in the Kubernetes code repository. They were built, linked, compiled, and shipped with the core Kubernetes binaries. There has been 20+ in-tree plugins. The problems of this plugin development model are:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;These in-tree plugins introduces risk to the stability of Kubernetes itself;&lt;/li&gt;&#10;&lt;li&gt;The maintenance and upgrade of plugin is tightly coupled with Kubernetes release&lt;/li&gt;&#10;&lt;li&gt;The Kubernetes community carries the burden of maintaining plugins for all storage backends.&lt;/li&gt;&#10;&lt;li&gt;Plugin developers have to open-source all their volume plugin code.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Kubernetes community seeks better alternatives, and has stopped accepting any more in-tree plugins since GA 1.8. The first alternative paradigm for shipping storage plugin, is &lt;a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-storage/flexvolume.md"&gt;flexVolume&lt;/a&gt;, which existed since version 1.2. However, &lt;a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-storage/flexvolume.md"&gt;flexVolume&lt;/a&gt; is still not good enough. For example, some packages like Ceph requires dependency package (ceph-common), and the deployment of plugin requires elevated access to the worker node. For that reason, the community later shifted to the Container Storage Interface (CSI) paradigm. A CSI-compliant plugin allows the storage resource to be surfaced as volumes (be it persistent or not) in Kubernetes cluster. More details in &lt;a href="https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/"&gt;this&lt;/a&gt; post and &lt;a href="https://kubernetes-csi.github.io/docs/drivers.html"&gt;here&lt;/a&gt; is a list of supported CSI-compliant drivers.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Back to our azure disk example, &lt;a href="https://github.com/kubernetes-sigs/azuredisk-csi-driver/blob/master/deploy/example/e2e_usage.md"&gt;this&lt;/a&gt; page provides examples for both dynamic and static provisioning.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;CSI-compliant plugin development is more complicate but it offloads it the driver developer. The community hopes users to shift to CSI so the 20+ grandfathered in-tree plugins can eventually be phased out. With that as the goal, there are several types of volumes with the name &amp;#8220;CSI migration&amp;#8221;, allowing users to migrate from in-tree volume plugins to CSI-based plugins.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;All the &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#csi"&gt;CSI&lt;/a&gt;-based plugins are fairly recent. As of today, the document outlines three ways to use CSI volume in a Pod:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;through a reference to a PersistentVolumeClaim (examples 4 and 5 below)&lt;/li&gt;&#10;&lt;li&gt;with a &lt;a href="https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volume"&gt;generic ephemeral volume&lt;/a&gt; (alpha feature)&lt;/li&gt;&#10;&lt;li&gt;with a &lt;a href="https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#csi-ephemeral-volume"&gt;CSI ephemeral volume&lt;/a&gt; if the driver supports that (beta feature)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 class="wp-block-heading" id="h-examples"&gt;Examples&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We&amp;#8217;ll go over five examples, as listed in the able below. Note that out of all the combinations, you cannot mount a csi-based plugin as a volume. No such volume type supported by CSI exist.&lt;/p&gt;&#10;&lt;table id="tablepress-15" class="tablepress tablepress-id-15 tbody-has-connected-cells"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;th class="column-1"&gt;Plug-in mechanism&lt;/th&gt;&lt;th class="column-2"&gt;Mount method&lt;/th&gt;&lt;th class="column-3"&gt;Example&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td rowspan="3" class="column-1"&gt;In-tree legacy volume plug-in&lt;/td&gt;&lt;td class="column-2"&gt;as volume&lt;/td&gt;&lt;td class="column-3"&gt;#1. using azureDisk property of Volume&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-2"&gt;as PV (static)&lt;/td&gt;&lt;td class="column-3"&gt;#2. using azureDisk property of PersistentVolume&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td class="column-2"&gt;as PV (dynamic)&lt;/td&gt;&lt;td class="column-3"&gt;#3. using kubernetes.io/azure-disk as provisioner for SC&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5"&gt;&#10;&#9;&lt;td rowspan="3" class="column-1"&gt;Out-of-tree CSI volume plugin&lt;/td&gt;&lt;td class="column-2"&gt;as volume&lt;/td&gt;&lt;td class="column-3"&gt;This mode does not exist. Example is not available&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6"&gt;&#10;&#9;&lt;td class="column-2"&gt;as PV (static)&lt;/td&gt;&lt;td class="column-3"&gt;#4. using disk.csi.azure.com as csi driver of PV&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-7"&gt;&#10;&#9;&lt;td class="column-2"&gt;as PV (dynamic)&lt;/td&gt;&lt;td class="column-3"&gt;#5 using disk.csi.azure.com as provisioner for SC&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- #tablepress-15 from cache --&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now, let&amp;#8217;s take a look at the example code snippet. Some examples are from Azure &lt;a href="https://docs.microsoft.com/en-us/azure/aks/azure-disks-dynamic-pv"&gt;documentation&lt;/a&gt;. Some are from the &lt;a href="https://github.com/kubernetes-sigs/azuredisk-csi-driver/tree/master/deploy/example"&gt;azure-disk-csi-driver&lt;/a&gt; repository. I&amp;#8217;ve made minor modifications for conciseness.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Example 1 uses legacy in-tree plugin, and directly mount the volume. The example &lt;a href="https://github.com/kubernetes/examples/blob/master/staging/volumes/azure_disk/azure.yaml"&gt;code&lt;/a&gt; is in Kubernetes repo.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: Pod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: mypod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; containers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - image: kubernetes/pause&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: mypod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeMounts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mountPath: /mnt/azure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; azureDisk:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kind: Managed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; diskName: myAKSDisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; diskURI: /subscriptions/&amp;amp;lt;subscriptionID&amp;gt;/resourceGroups/MC_myAKSCluster_myAKSCluster_eastus/providers/Microsoft.Compute/disks/myAKSDisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Example 2 uses legacy in-tree plugin, and mount the PV statically via PVC. No storage class is used (as indicated by empty string in storage class property)&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: PersistentVolume&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: azure-disk-pv&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; capacity:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage: 2Gi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storageClassName: &amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeMode: Filesystem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; accessModes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ReadWriteOnce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; azureDisk:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kind: Managed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; diskName: &amp;amp;lt;enter-disk-name&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; diskURI: &amp;amp;lt;enter-disk-resource-id&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: PersistentVolumeClaim&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: azure-disk-pvc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storageClassName: &amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; accessModes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ReadWriteOnce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resources:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; requests:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage: 2Gi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: apps/v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: Pod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: logz-deployment&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; containers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: pause&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: kubernetes/pause&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeMounts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azure-disk-vol&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mountPath: /mnt/logs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azure-disk-vol&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; persistentVolumeClaim:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; claimName: azure-disk-pvc&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Example 3 uses legacy in-tree plugin, and mount the PV dynamically and implicitly via SC. Note that Azure AKS will create several SCs for you by default so use existing ones whenever available.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;allowVolumeExpansion: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: storage.k8s.io/v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: StorageClass&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: managed-premium&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parameters:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cachingmode: ReadOnly&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kind: Managed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storageaccounttype: Premium_LRS&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;provisioner: kubernetes.io/azure-disk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;volumeBindingMode: WaitForFirstConsumer&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: PersistentVolumeClaim&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: azure-managed-disk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; accessModes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ReadWriteOnce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storageClassName: managed-premium&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resources:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; requests:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage: 5Gi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: Pod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: mypod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; containers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: mypod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: kubernetes/pause&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeMounts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - mountPath: &amp;#34;/mnt/azure&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: volume&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: volume&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; persistentVolumeClaim:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; claimName: azure-managed-disk&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Example 4 uses CSI-based plugin, and mount the PV statically via PVC&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: PersistentVolume&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: pv-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; capacity:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage: 10Gi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; accessModes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ReadWriteOnce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; persistentVolumeReclaimPolicy: Retain&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; csi:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; driver: disk.csi.azure.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; readOnly: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeHandle: /subscriptions/{sub-id}/resourcegroups/{group-name}/providers/microsoft.compute/disks/{disk-id}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeAttributes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fsType: ext4&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; partition: &amp;#34;1&amp;#34; # optional, remove this if there is no partition&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: PersistentVolumeClaim&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: pvc-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; accessModes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ReadWriteOnce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resources:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; requests:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage: 10Gi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeName: pv-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storageClassName: &amp;#34;&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: Pod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: nginx-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nodeSelector:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kubernetes.io/os: linux&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; containers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - image: kubernetes/pause&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: mypod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeMounts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azuredisk01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mountPath: &amp;#34;/mnt/azuredisk&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azuredisk01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; persistentVolumeClaim:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; claimName: pvc-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Example 5 uses CSI-based plugin, and mount the PV dynamically and implicitly via SC&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: StorageClass&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: storage.k8s.io/v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: azuredisk-csi-waitforfirstconsumer&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;provisioner: disk.csi.azure.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parameters:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; skuname: StandardSSD_LRS &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;allowVolumeExpansion: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;reclaimPolicy: Delete&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;volumeBindingMode: WaitForFirstConsumer&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: PersistentVolumeClaim&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: pvc-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; accessModes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ReadWriteOnce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resources:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; requests:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage: 10Gi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storageClassName: managed-csi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kind: Pod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;apiVersion: v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;metadata:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: nginx-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;spec:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nodeSelector:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kubernetes.io/os: linux&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; containers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - image: kubernetes/pause&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name: mypod&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumeMounts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azuredisk01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mountPath: &amp;#34;/mnt/azuredisk&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: azuredisk01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; persistentVolumeClaim:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; claimName: pvc-azuredisk&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading" id="h-bottomline"&gt; Bottomline&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As of June 2021, the CSI support is still new. Generally, if a CSI-based plugin is available and in GA, you should consider using it. If you have existing legacy volume types using in-tree plugin, you should consider migration, and create a migration plan. Also, try to avoid the use case of mounting as generic volume (without PVC) because it is rare and not supported with CSI drivers. Without PVC, it also cannot take advantage of the &lt;strong&gt;volumeClaimTemplates&lt;/strong&gt; property in StatefulSet object.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/05/getting-started-with-github-actions/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Getting started with GitHub Actions&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/06/kubernetes-networking-solutions-overview/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kubernetes Networking Solutions Overview&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>