| name | kubernetes-storage |
| description | Manage Zeabur Kubernetes persistent storage directly with kubectl: create or mount PVCs, resize storage, and inspect, copy, or edit files on a service volume. Use whenever a service needs durable disks or volume-file operations without the Zeabur backend. |
Read ../../references/kubernetes.md before changing storage. It provides the kubectl-only boundary, identity labels, PVC naming defaults, and safe mutation loop.
Establish the volume contract
Require the environment ID, service ID, volume ID for an existing Zeabur-style claim, requested capacity, mount path, and access mode. Inventory claims, storage classes, workload mounts, Pods, and events before modifying anything:
kubectl -n "$NS" get pvc -l "zeabur_service_id=$ZEABUR_SERVICE_ID"
kubectl -n "$NS" get storageclass
kubectl -n "$NS" describe pvc "$PVC_NAME"
kubectl -n "$NS" get events --sort-by=.lastTimestamp
The source backend creates a volume claim named <volume-id>-service-<service-id>, labels it with the project, environment, service, and user IDs, requests the declared capacity, and uses ReadWriteOnce. Retain that identity when managing existing claims. Never replace a bound claim merely to change its mount path or capacity.
Complete this step only when the claim name, storage class, access mode, current capacity, selected workload, and existing mount name are known.
Create and mount a PVC
For a new volume, use the cluster's selected StorageClass and a storage request. Use ReadWriteOnce for one writable service Pod; choose ReadWriteMany only after the StorageClass documents that capability and the workload requires shared writes.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <volume-id>-service-<service-id>
namespace: environment-<environment-id>
labels:
zeabur_type: user-service
zeabur_project_id: <project-id>
zeabur_service_id: <service-id>
zeabur_environment_id: <environment-id>
zeabur_user_id: <user-id>
spec:
storageClassName: <storage-class>
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
Mount the claim through a minimal Deployment fragment using a stable volume name and the target container name:
apiVersion: apps/v1
kind: Deployment
metadata:
name: <workload>
namespace: environment-<environment-id>
spec:
template:
spec:
volumes:
- name: data
persistentVolumeClaim:
claimName: <volume-id>-service-<service-id>
containers:
- name: <container>
volumeMounts:
- name: data
mountPath: /data
Apply the claim, wait until status.phase=Bound, then apply the workload fragment and wait for rollout. A volume mount change recreates Pods; report that expected restart.
Resize
Read allowVolumeExpansion on the selected StorageClass. Patch only spec.resources.requests.storage to a larger quantity; Kubernetes does not support shrinking a PVC in place. Wait for the PVC capacity and any FileSystemResizePending condition to settle, then verify the mounted filesystem from the target container.
kubectl -n "$NS" get pvc "$PVC_NAME" -o wide
kubectl -n "$NS" exec "$POD" -c "$CONTAINER" -- df -h "$MOUNT_PATH"
With ReadWriteOnce, scaling a service above one replica or running a second writable maintenance Pod can fail on attachment. Preserve availability by using an existing mounted Pod for file work. A maintenance Pod that needs exclusive mounting requires explicit downtime approval, scaling the workload down, verifying termination, doing the work, and restoring the recorded replica count.
Files on a live mounted volume
Select one Ready Pod by its service label and container name. Confine every operation to the user-approved mount path. Inspect before modifying:
kubectl -n "$NS" exec "$POD" -c "$CONTAINER" -- sh -c 'df -h "$1" && find "$1" -maxdepth 2 -type f -print' sh "$MOUNT_PATH"
kubectl -n "$NS" cp "$POD:$MOUNT_PATH/relative-file" ./relative-file -c "$CONTAINER"
kubectl -n "$NS" cp ./replacement-file "$POD:$MOUNT_PATH/relative-file" -c "$CONTAINER"
kubectl cp depends on tar in the container. If it is unavailable, use a narrowly scoped kubectl exec stream only after confirming the container has compatible tools. Preserve owner and mode expectations; use a separate, explicitly approved maintenance job for recursive ownership changes.
For a write, verify the destination path, record the original checksum and permissions when replacing a file, copy the new data, then verify the new checksum and application health. Never expose Secret-backed files or values in the report.
Completion
Report PVC name, StorageClass, access mode, requested and bound capacity, workload mount path, and Pod used for verification. A storage task is complete only when the PVC is Bound, the intended workload has rolled out, and df or the requested file operation confirms the mounted filesystem reflects the requested state.