Containers
Migrating Amazon EKS clusters from gp2 to gp3 EBS volumes
Kubernetes (sometimes referred to as K8s) is an open-source container orchestration engine and a fast-growing project hosted by the Cloud Native Computing Foundation (CNCF). K8s has a massive adoption on premises and in the cloud for running stateless and stateful containerized workloads. Stateful workloads require persistent storage. To support on-premises and cloud-provider-related infrastructure like storage and networking, Kubernetes source code originally included so-called “in-tree plugins.” Storage and cloud vendors who wanted to add new storage systems or features or just wanted to fix bugs had to rely on the Kubernetes release cycle. To decouple the life cycle of Kubernetes from vendor-specific implementations, the development of Container Storage Interface (CSI), a standard for exposing arbitrary block and file storage systems to containerized workloads on container orchestration systems like Kubernetes, was initiated. Customers can now benefit from the latest CSI driver without having to wait for new Kubernetes version releases.
AWS launched their managed Kubernetes service Amazon Elastic Kubernetes Service (Amazon EKS) at re:Invent 2017. In September 2019, AWS released support for the Amazon Elastic Block Store (Amazon EBS) Container Storage Interface (CSI) driver in Amazon EKS, and in May 2021 AWS announced the general availability of this CSI plugin. The Kubernetes Amazon EBS related in-tree storage plugin—called a provisioner of type “kubernetes.io/aws-ebs”—only supports Amazon EBS types io1, gp2, sc1, and st1, and it does not support volume snapshot related features.
Our customers are now asking when and how to migrate an EKS cluster from the Amazon EBS in-tree plugin to the Amazon EBS CSI driver to make use of additional EBS volume types (like gp3 and io2) and take advantage of new features (like Kubernetes Volume Snapshots).
Container Storage Interface (CSI) migration infrastructure has been in beta feature state since Kubernetes v1.17 and is described in detail in this K8s blog post. It is important to understand that the migration will eventually remove the in-tree plugin from the Kubernetes source code, and all migrated volumes will be controlled by the CSI driver. It does not mean that those migrated PVs will get new features and attributes of the CSI driver. It only supports features that are already supported by in-tree drivers as described here.
This blog post will walk you through a migration scenario and outline the necessary steps in detail.
Note: If you are already migrated from in-tree provisioner to EBS CSI or started with EBS CSI using the default gp2 based StorageClass have a look at the following blog post “Simplifying Amazon EBS volume migration and modification on Kubernetes using the EBS CSI Driver“.
Prerequisites
You need an EKS cluster with version 1.17 or newer and a corresponding version of kubectl. Make sure you are authorized to install the Amazon EBS CSI-related objects.
Kubernetes uses so-called feature gates to implement the storage migration. The CSIMigration and CSIMigrationAWS feature for Amazon EBS, when enabled, redirects all plugin operations from the existing in-tree plugin to the ebs.csi.aws.com
CSI driver. Please note that Amazon EKS has not yet turned on the features CSIMigration
and CSIMigrationAWS
for Amazon EBS migration. Nevertheless, you can already use the Amazon EBS CSI driver in parallel to the in-tree plugin.
For the sake of the demo, we will create a dynamic PersistentVolume (PV), which we are going to migrate later.
We use dynamic volume provisioning as described in the K8s documentation.
The in-tree storage driver-based default StorageClass (SC) gp2 will be used to create a PersistentVolumeClaim (PVC) :
The PVC is created in status “pending” because the gp2 StorageClass has a Volume Binding Mode (attribute volumeBindingMode) of WaitForFirstConsumer and there is no pod yet consuming the PVC.
So let’s create a pod (our “demo application”) that uses the PVC:
After a few seconds the pod is created:
This will dynamically provision the underlying PV pvc-646fef81-c677-46f4-8f27-9d394618f236, which is now bound to the PVC “ebs-gp2-claim”
Let’s quickly check if the volume contains some data:
Let’s have a look at the details of the PV:
The PV was (as expected) created by the “kubernetes.io/aws-ebs” provisioner as shown in the annotation. The “awsElasticBlockStore.volumeId” attribute within the spec section shows the actual Amazon EBS Volume ID “vol-03d3cd818a2c2def3” together with the AWS Availability Zone (AZ) the EBS volume was created – eu-central-1c in this case. EBS volumes and EC2 instances are zonal (not Regional) resources. The nodeAffinity section advises the kube-scheduler to provision the pod on a node in the same AZ where the PV is created.
The following command is a short-form to retrieve the Amazon EBS details:
We want to use this PV for the storage migration scenarios described later. To ensure that the PV will not be deleted when the corresponding PVC, using it, is deleted we are going to patch the “VolumeReclaimPolicy” to “Retain”. Note: This is only possible on the PV level not the SC level!
To install the Amazon EBS CSI driver, follow our GitHub documentation. The required high-level steps are:
- Attach the IAM permissions required for Amazon EBS operations to either the worker node profile or alternatively, following least privilege, use IRSA (IAM roles for service account) to create a properly annotated ServiceAccount (SA)
- Install the external volume snapshot controller related K8s objects (CRD, RBAC resources, deployment, and validating webhook) using YAML
- Install Amazon EBS CSI driver using YAML or use corresponding Helm chart (use existing service account if you use IRSA)
Double-check that the Amazon EBS CSI related Kubernetes components are registered to the K8s API server:
Confirm they are up and running:
Migration scenario
First we will discuss the migration scenario at a high level.
We are conducting a physical storage migration by copying the in-tree based PV data using Amazon EBS snapshots as an external snapshot mechanism (note: K8s in-tree Amazon EBS plugin does not support volume snapshots!) and import this data using the CSI Volume Snapshots feature of the CSI Amazon EBS driver.
Now we will guide you through the migration in detail.
We start by taking a snapshot of the in-tree plugin based PV pvc-646fef81-c677-46f4-8f27-9d394618f236 via the AWS API.
Wait until snapshot is in state “completed”
Now create a VolumeSnapshotClass object:
Next we have to create a VolumeSnapshotContent object that uses the AWS snapshot snap-06fb1faafc1409cc5 and already references a VolumeSnapshot we will create in a next step. This seems odd but is necessary for the bidirectional binding of VolumeSnapshotContent and VolumeSnapshot for preexisting snapshots!
Now we need to create the VolumeSnapshot that references the VolumeSnapshotContent object:
During this migration we like to benefit from the new Amazon EBS gp3 storage class. In order to do so we have to create a CSI-based gp3 storage class! Because we want this SC to be the default one we remove the annotation from the Amazon EKS default SC gp2 first:
The VolumeSnapshot we created earlier can be used to create a PersistentVolumeClaim. As the storage class we use the new gp3 CSI based SC.
Note that the PVC is still in pending status because the gp3 SC uses a volumeBindingMode of WaitForFirstConsumer. So we have to create an application (pod) again to create an underlying PV. For demo purposes, we just mount the PVC without writing new data and use “kubectl exec” to have a look at the data of the snapshot:
A PV pvc-25d2d19d-6ede-47d2-bd2e-32d45832ec20 was automatically created and the pod is running with access to the migrated data:
The PVC, as expected, uses CSI based gp3 SC:
Cleanup
To avoid unnecessary costs, clean up your environment after performing the demo migration.
For future use, you can leave the CSI driver in your EKS cluster.
Conclusion
Amazon EKS provides customers with a managed control plane, options for managing the data plane (managed node groups), and managed cluster add-ons for critical components like AWS VPC CNI, CoreDNS, and kube-proxy. Once all features related to Amazon EBS CSI migration are finalized, AWS will take care of the heavy lifting of implementing all the bits and pieces on the managed control plane and data plane for you!
This blog post described how you can even start today migrating your workloads to PersistentVolumes, which supports all the new capabilities and features of the Amazon EBS CSI driver.
We hope this post helps with your Kubernetes projects. If you have questions or suggestions, please leave a comment.