PV, PVC, CSI và StatefulSet
Kubernetes orchestration giúp gắn storage vào workload nhưng không tự biến một database thành durable, replicated hay recoverable. Độ bền dữ liệu vẫn phụ thuộc storage backend, CSI driver, topology, replication của ứng dụng và quy trình backup/restore.
1. Storage: persistent không có nghĩa là highly available
Volume có thể tồn tại lâu hơn vòng đời của một Pod, nhưng điều đó chỉ giải quyết một phần bài toán durability. Một disk đơn lẻ trong một zone vẫn có thể mất availability khi node, zone hoặc storage control plane gặp sự cố. Database chạy trên Kubernetes vẫn phải có chiến lược replication, quorum, backup, restore và failover phù hợp với RPO/RTO.
| Lớp | Kubernetes cung cấp | Kubernetes không tự bảo đảm |
|---|---|---|
| Pod / controller | Reconcile số replica, restart/reschedule | Application-level leader election, transaction durability |
| PV/PVC | Claim/binding và lifecycle của storage | Backend replication, corruption protection, backup |
| CSI | Chuẩn provision/attach/mount/snapshot | Mọi driver đều có cùng capability hay failure behavior |
| StatefulSet | Stable ordinal, DNS identity, per-Pod claims | Data replication, consensus, shard placement logic |
2. Provisioning model: PVC → StorageClass → PV → CSI
PVC mô tả capacity, access mode và StorageClass mà workload cần. Với dynamic provisioning, provisioner/CSI driver tạo PV phù hợp rồi control plane bind PVC với PV. Sau đó kubelet và CSI node plugin thực hiện attach/mount theo capability của backend.
volumeBindingMode ảnh hưởng trực tiếp đến scheduling. Immediate có thể provision volume trước khi biết Pod sẽ chạy ở đâu; với storage giới hạn theo zone, lựa chọn này có thể tạo mismatch topology. WaitForFirstConsumer trì hoãn binding/provisioning cho tới khi scheduler có đủ context về node/zone của Pod.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: zonal-ssd
provisioner: csi.example.com
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Retain
Pending nếu không còn capacity/topology phù hợp; hoặc stuck ở attach/mount nếu volume còn gắn vào node cũ, CSI controller/node plugin lỗi, credential hết hạn hay backend storage degraded. Đừng chẩn đoán mọi lỗi storage như lỗi scheduler.3. Access và lifecycle
Các access mode mô tả cách volume có thể được mount, không phải performance SLA và cũng không thay thế locking ở application.
| Mode | Ý nghĩa thực hành | Lưu ý |
|---|---|---|
| RWO | Read/write từ một node | Nhiều Pod trên cùng node có thể vẫn dùng tùy volume/backend |
| ROX | Read-only từ nhiều node | Không phù hợp workload cần ghi |
| RWX | Read/write từ nhiều node | Cần filesystem/backend hỗ trợ và application xử lý concurrent writes |
| RWOP | Read/write bởi một Pod | Hữu ích khi cần single-writer semantics ở mức Pod với CSI hỗ trợ |
Reclaim policy quyết định backend volume sau khi claim bị giải phóng. Delete thường xóa storage asset cùng PV; Retain giữ lại để admin kiểm tra/recover thủ công. Với dữ liệu quan trọng, policy phải là quyết định lifecycle có chủ ý, không chỉ dùng mặc định của StorageClass.
Volume expansion yêu cầu StorageClass cho phép mở rộng và driver/filesystem hỗ trợ; thông thường chỉ grow, không shrink. Finalizer và storage object protection ngăn xóa resource đang được sử dụng, nhưng cũng có thể khiến deletion chờ lâu khi dependency hoặc CSI path không hoàn tất.
4. StatefulSet: identity ổn định, không phải database operator
StatefulSet phù hợp workload cần tên ổn định, thứ tự/ordinal và storage riêng cho từng replica. volumeClaimTemplates tạo PVC theo từng Pod; Headless Service thường được dùng để peer discovery qua DNS. OrderedReady triển khai tuần tự, còn Parallel cho phép tạo/xóa Pod song song khi semantics của ứng dụng cho phép.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: store
spec:
serviceName: store
replicas: 3
selector:
matchLabels:
app: store
template:
metadata:
labels:
app: store
spec:
containers:
- name: store
image: example/store:1.4
volumeMounts:
- name: data
mountPath: /var/lib/store
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: zonal-ssd
resources:
requests:
storage: 100Gi
StatefulSet không replicate dữ liệu, không elect leader và không hiểu quorum. Nếu replica store-0 chết, controller có thể tạo Pod mới với cùng identity/PVC, nhưng application vẫn phải quyết định dữ liệu có đủ mới hay không, node cũ đã được fence chưa và replica mới có thể tham gia cluster an toàn không.
volumeClaimTemplates được giữ lại khi StatefulSet bị xóa hoặc scale down. Kubernetes cũng có persistentVolumeClaimRetentionPolicy để thay đổi hành vi này; dùng Delete chỉ khi data lifecycle đã được hiểu rõ và có backup/recovery phù hợp.5. Rolling update, fencing và failure window
Với stateful workload, rollout không chỉ là thay image. Một Pod mới có thể cần cùng volume, phải chờ detach/attach từ node cũ, replay WAL/log, rejoin quorum hoặc resync data. Nếu node cũ chỉ mất network nhưng vẫn ghi được vào disk, việc attach volume ở nơi khác mà không có fencing đúng có thể tạo split-brain hoặc corruption.
- Đảm bảo readiness phản ánh trạng thái ứng dụng thật: joined quorum, caught up đủ mức cho phép, có thể phục vụ traffic.
- Dùng update partition/canary khi application hỗ trợ để giới hạn blast radius trước khi rollout toàn bộ ordinal.
- Không force-delete Pod stateful như thao tác mặc định; hiểu attach state, fencing và backend semantics trước.
- Plan rollback cả image/schema/protocol. Rolling back binary không cứu được migration dữ liệu không backward-compatible.
6. Backup và restore: snapshot không tự bằng backup
CSI VolumeSnapshot chuẩn hóa việc yêu cầu snapshot cho driver hỗ trợ. Snapshot đơn volume thường chỉ phản ánh trạng thái block/filesystem tại một thời điểm; nó không tự bảo đảm application-consistent cho database đang có write in flight. Cần phối hợp quiesce, flush/checkpoint, WAL/binlog hoặc cơ chế backup native của database khi consistency requirement đòi hỏi.
Backup cluster objects và backup data là hai lớp khác nhau. Muốn phục hồi workload thực sự, phải biết cách tái tạo namespace/config/secret references, PVC/StorageClass, data, DNS/service identity và application/schema version.
| Cần chứng minh | Câu hỏi kiểm tra |
|---|---|
| RPO | Mất tối đa bao nhiêu phút/giờ dữ liệu khi region/storage/account mất? |
| RTO | Từ incident đến lúc service phục vụ bình thường mất bao lâu? |
| Consistency | Snapshot crash-consistent hay application-consistent? Multi-volume có cùng recovery point không? |
| Isolation | Backup có nằm cùng failure domain/credential/account với primary không? |
| Compatibility | Restore đã test với đúng engine, schema và app version chưa? |
7. Capacity và operational signals
Stateful systems thường hết headroom trước khi “hết disk” hoàn toàn. Capacity plan nên bao gồm usable capacity sau replication, zone loss, snapshot/backup overhead, growth rate, resync/rebuild bandwidth và thời gian cần để mở rộng volume hoặc thêm shard/replica.
- PVC/PV phase, pending claims, provisioning latency, attach/mount errors.
- Volume usage %, inode usage, latency/IOPS/throughput, queue depth và throttling của backend.
- CSI controller/node plugin errors, retry rate, credential/auth failures.
- Application replication lag, quorum health, leader changes, rebuild/resync progress.
- Backup age, snapshot failure, restore duration và evidence từ restore drill.
Alert nên dựa trên tốc độ tăng và time-to-exhaustion, không chỉ threshold tĩnh. Khi một zone/node/storage path mất, hệ thống vẫn phải còn capacity để reschedule, reattach và rebuild mà không đẩy các replica còn lại vào saturation.
8. Security và data protection
Storage chứa dữ liệu lâu hơn Pod nên blast radius của credential và misconfiguration lớn. Áp dụng least privilege cho Kubernetes RBAC và cloud/storage API, mã hóa in transit/at rest theo threat model, quản lý key/secret tách biệt, hạn chế ai được tạo StorageClass/snapshot/restore và audit các thao tác delete/retain/restore.
- Không nhúng storage credential tĩnh vào image hoặc manifest public.
- Kiểm soát quyền snapshot/restore vì snapshot có thể chứa toàn bộ dữ liệu nhạy cảm.
- Tách backup khỏi primary failure domain; cân nhắc cross-account/cross-region và immutable retention khi phù hợp.
- Kiểm tra data remanence khi reclaim/delete và yêu cầu compliance của backend.
9. Khi nào nên dùng managed service?
Managed database thường giảm operational burden cho replication/quorum, patching, backup, failover, monitoring và upgrade. Chạy database/stateful middleware trong cluster hợp lý khi có requirement rõ về locality, custom engine/topology, portability, cost hoặc control — và đội ngũ thực sự có năng lực vận hành storage, consensus, backup/restore và incident recovery.
| Câu hỏi quyết định | Nghiêng về managed service | Nghiêng về tự vận hành trong Kubernetes |
|---|---|---|
| Quorum/failover | Muốn provider chịu phần lớn burden | Team hiểu sâu engine và failure modes |
| Backup/PITR | Cần capability tích hợp, tested workflow | Có pipeline + restore drill riêng đáng tin cậy |
| Upgrade | Muốn giảm patching/compatibility toil | Cần kiểm soát version/topology đặc thù |
| Portability/control | Ít quan trọng hơn reliability/toil | Là requirement có giá trị đủ lớn |