# Kubernetes Persistent Storage on E2E {/* TODO: Add PV/PVC architecture diagram */} ## 1. Introduction Stateful workloads require storage that persists independently of Pod lifecycles. E2E Kubernetes supports persistent storage using **Kubernetes Persistent Volumes (PV)** and **Persistent Volume Claims (PVC)**. This document explains **how to configure and use persistent storage from scratch on an E2E Kubernetes cluster**, including: - E2E-specific storage behavior - Static provisioning - Dynamic provisioning - Deploying a sample stateful MySQL application - Demonstrating why PV and PVC are required > For SFS-based persistent storage (shared filesystem), see [Persistent Volume using SFS](/docs/myaccount/kubernetes/deploy_fault_tolerant_using_sfs/). ## 2. Prerequisites Before starting, ensure the following prerequisites are met: - An active E2E Kubernetes cluster - At least one worker node in Ready state - Access to the [E2E Cloud Dashboard](https://myaccount.e2enetworks.com) - `kubectl` configured with cluster access Verify cluster access: ```bash kubectl get nodes ``` {/* TODO: Add screenshot of kubectl get nodes output showing nodes in Ready state */} ## 3. E2E Storage Behavior (Important) ### Default StorageClass Behavior in E2E Kubernetes By default, **no StorageClass is available** in an E2E Kubernetes cluster. > At least one **Persistent Volume (PV)** must be created from the E2E Cloud Dashboard to expose and enable the StorageClass in the cluster. This step is **mandatory** before using: - Static provisioning - Dynamic provisioning ## 4. Enable StorageClass in E2E Kubernetes ### 4.1 Create a Persistent Volume from E2E UI 1. Log in to the [E2E Cloud Dashboard](https://myaccount.e2enetworks.com) 2. Navigate to **Kubernetes** 3. Go to **Persistent Volumes** 4. Click **Create PV** 5. Select required size (example: **10 Gi**) 6. Create the PV {/* TODO: Add screenshot of Add Persistent Volume dialog in E2E UI */} The Persistent Volume is created successfully. ### 4.2 Verify Storage Resources in the Cluster Once the PV is created from the UI: - A **StorageClass** (example: `csi-rbd-sc`) is automatically provisioned - A **PersistentVolume (PV)** is created - A **PersistentVolumeClaim (PVC)** is automatically created and bound ```bash kubectl get storageclass kubectl get pv kubectl get pvc ``` {/* TODO: Add screenshot of kubectl get storageclass/pv/pvc output */} > **Important (E2E Specific):** In an E2E Kubernetes cluster, at least one PV must be created from the UI to enable the StorageClass. This is mandatory for both **static and dynamic provisioning**. ## 5. Storage Provisioning Models ### 5.1 Static Provisioning - Storage is created **manually** from the E2E Cloud Dashboard - PV exists **before** the application is deployed - PVC is pre-bound - Recommended for **production workloads** ### 5.2 Dynamic Provisioning - Storage is created **automatically** when a PVC is created - Uses a StorageClass - Recommended for **development and testing** ## 6. Verify Persistent Volumes in Kubernetes ```bash kubectl get pv kubectl get pvc ``` **Expected Output:** - At least one StorageClass exists - One PV is in `Bound` state - One PVC is in `Bound` state This PVC will be reused for static volume testing. ## 7. Database WITHOUT Persistent Volume (Data Loss Scenario) This section demonstrates **why PV and PVC are required**. ### 7.1 Deploy MySQL WITHOUT a Volume ```yaml apiVersion: v1 kind: Pod metadata: name: test-e2e namespace: test-mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD value: e2e@123 - name: MYSQL_DATABASE value: e2etestdb ``` Apply the manifest: ```bash kubectl apply -f pod.yaml -n test-mysql kubectl get pods -n test-mysql ``` {/* TODO: Add screenshot of kubectl get pods showing test-e2e running */} ### 7.2 Insert Data into MySQL ```bash kubectl exec -it -n test-mysql test-e2e -- mysql -u root -p ``` ```sql USE e2etestdb; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) ); INSERT INTO users VALUES (1, 'test-user'); EXIT; ``` {/* TODO: Add screenshot of MySQL output showing inserted data */} ### 7.3 Delete and Recreate the Pod ```bash kubectl delete pod test-e2e -n test-mysql ``` Recreate the Pod and check the data again. {/* TODO: Add screenshot showing pod deleted and recreated */} **Result: Data is LOST** ### Conclusion (Without PV/PVC) - Pod filesystem is **ephemeral** - Data stored inside containers is **not persistent** - Databases must **not** rely on container filesystem storage ## 8. Persistent Storage with PV & PVC In the previous section, we confirmed that data stored inside a Pod is lost when the Pod is deleted. This section demonstrates how **Persistent Volumes (PV)** and **Persistent Volume Claims (PVC)** solve this problem on E2E Kubernetes. ## 9. Static Provisioning: MySQL with PV & PVC ### 9.1 Architecture ``` MySQL Pod → PVC (pre-created) → PV (E2E UI) → E2E Storage ``` ### 9.2 Deploy MySQL Using Existing PVC ```yaml apiVersion: v1 kind: Pod metadata: name: mysql-static spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD value: e2e@123 - name: MYSQL_DATABASE value: e2edb volumeMounts: - name: mysql-storage mountPath: /var/lib/mysql volumes: - name: mysql-storage persistentVolumeClaim: claimName: ``` > Replace `` with the actual PVC name from your cluster. Run `kubectl get pvc` to find the available PVC name. Apply the manifest: ```bash kubectl apply -f e2e-test-pv.yaml kubectl get pods ``` {/* TODO: Add screenshot of kubectl get pods showing mysql-static running */} ### 9.3 Insert Data into MySQL Login to the Pod: ```bash kubectl exec -it mysql-static -- mysql -u root -p ``` ### 9.4 Verify Data Persistence 1. Insert data: ```sql USE e2edb; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) ); INSERT INTO users VALUES (1, 'test-user'); ``` 2. Delete Pod: ```bash kubectl delete pod mysql-static ``` 3. Recreate Pod (apply the same manifest again). 4. Query data again: ```sql mysql> select * from users; ``` **Data is retained.** {/* TODO: Add screenshot showing data persists after Pod recreation */} ## 10. Dynamic Provisioning: MySQL with StorageClass ### 10.1 Architecture ``` MySQL Pod → PVC → StorageClass → Auto-created PV → E2E Storage ``` ### 10.2 Create Namespace ```bash kubectl create namespace mysql-dynamic ``` ### 10.3 Create PVC (Dynamic) ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-dynamic-pvc namespace: mysql-dynamic spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: csi-rbd-sc ``` Apply the manifest: ```bash kubectl apply -f pvc.yaml kubectl get pvc -n mysql-dynamic ``` {/* TODO: Add screenshot of kubectl get pvc showing mysql-dynamic-pvc Bound */} The PVC is created. ### 10.4 Deploy MySQL Using Dynamic PVC ```yaml apiVersion: v1 kind: Pod metadata: name: mysql-dynamic namespace: mysql-dynamic spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD value: e2e@123 - name: MYSQL_DATABASE value: e2edb volumeMounts: - name: mysql-storage mountPath: /var/lib/mysql volumes: - name: mysql-storage persistentVolumeClaim: claimName: mysql-dynamic-pvc ``` Apply the manifest: ```bash kubectl apply -f mysql-dynamic.yaml kubectl get pods -n mysql-dynamic ``` {/* TODO: Add screenshot of kubectl get pods showing mysql-dynamic running */} Once deployed: - A new PV is created automatically - Data persists after Pod recreation {/* TODO: Add screenshot confirming data persists after Pod recreation */} ---