Persistent Disk CSI — Block Storage Nền Tảng
Vì sao PD là nền tảng và vì sao nó hay bị hiểu sai
Persistent Disk là block storage được dùng nhiều nhất trên GKE — gần như mọi database, message broker, hay stateful workload bắt đầu từ một PD. Nhưng nó cũng là loại storage bị hiểu sai nhiều nhất, vì người đến từ on-prem mang theo hai giả định sai chí mạng: rằng IOPS gắn với phần cứng (trên GCP, IOPS gắn với loại disk và dung lượng), và rằng một disk ghi được từ nhiều máy (trên block device, không an toàn). File này phá cả hai giả định đó và đào sâu toàn bộ cơ chế của CSI driver pd.csi.storage.gke.io.
CSI driver này là add-on managed, luôn bật trên Autopilot; trên Standard cluster bật qua --update-addons=GcePersistentDiskCsiDriver=ENABLED (GKE PD CSI Driver). Nó là lớp dịch: mọi giới hạn thật nằm ở tầng Compute Engine bên dưới.
Các loại PD và quan hệ IOPS–throughput–dung lượng
GKE hỗ trợ bốn loại PD qua tham số type trong StorageClass. Điểm cốt lõi cần nội tâm hóa: với PD, hiệu năng IOPS/throughput scale theo dung lượng — đĩa càng lớn, IOPS càng cao, đến mức trần của loại đĩa và của VM. Đây là khác biệt nền tảng với on-prem.
Loại (type) | Phương tiện | Đặc tính | Use case |
|---|---|---|---|
pd-standard | HDD | Throughput tuần tự tốt, IOPS random thấp, rẻ nhất | Log, backup, dữ liệu tuần tự lớn |
pd-balanced | SSD | Cân bằng IOPS/giá, mặc định GKE | Phần lớn workload phổ thông, web app |
pd-ssd | SSD | IOPS/throughput cao hơn balanced | Database, workload nhạy latency |
pd-extreme | SSD | IOPS provision được độc lập (tới hàng trăm nghìn) | Database lớn cần IOPS rất cao |
Hệ quả thực tế của quy luật "IOPS scale theo dung lượng": một database cần IOPS cao không thể đặt trên một pd-ssd 10Gi — dung lượng nhỏ kéo trần IOPS xuống thấp. Giải pháp truyền thống là over-provision dung lượng (tạo disk lớn hơn dữ liệu cần chỉ để có IOPS), một sự lãng phí. pd-extreme giải vấn đề này bằng cách cho phép provision IOPS riêng qua tham số provisioned-iops-on-create — bắt buộc cho pd-extreme (GKE PD CSI Driver). Nhưng cách giải triệt để hơn là chuyển sang Hyperdisk (file 4), nơi hiệu năng và dung lượng tách rời hoàn toàn — đây là hướng GCP đang đẩy mọi workload IOPS-cao tới.
Một ràng buộc machine-type cần nhớ: dòng máy thế hệ mới như C3 không hỗ trợ pd-standard (GKE PD CSI Driver). Chọn loại disk phải khớp với machine type của node pool.
# StorageClass pd-extreme với IOPS provision
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: pd-extreme-100k
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-extreme
provisioned-iops-on-create: "100000"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: trueAttach/detach mechanics và per-node attach limit
Một PD là tài nguyên network-attached: nó tồn tại độc lập và được attach vào VM của node khi Pod cần. Hai sự thật vận hành quan trọng:
Per-node attach limit. Mỗi VM chỉ attach được một số lượng disk giới hạn, phụ thuộc machine type (thường vài chục, máy nhỏ ít hơn). Đây là giới hạn của Compute Engine, không phải Kubernetes. Hệ quả lên scheduling: một node đã attach tối đa disk không nhận thêm Pod cần PVC mới, dù còn dư CPU/memory. Với workload nhiều PVC nhỏ (ví dụ nhiều instance database nhỏ), node hết "slot disk" trước khi hết CPU — gây Pod Pending khó hiểu nếu không biết giới hạn này. CSI driver báo max-volumes-per-node cho scheduler qua plugin NodeResourcesFit/VolumeBinding, nên scheduler tránh được node đầy disk, nhưng kết quả vẫn là bin-packing kém hơn dự kiến.
Độ trễ attach. Attach disk là lời gọi Compute Engine API, mất từ vài giây tới chục giây. Đây là một thành phần của thời gian khởi động Pod stateful, cộng vào sau thời gian scheduling và trước khi container chạy. Khi một node chết và Pod cần dời sang node khác, disk phải detach khỏi node cũ trước — và nếu node cũ chết đột ngột (không graceful), detach bị treo chờ timeout, làm Pod stateful kẹt. Đây chính là vấn đề mà Stateful HA Operator giải (phần cuối file).
Vì sao ReadWriteMany không an toàn trên PD
PD hỗ trợ một chế độ "multi-writer" ở tầng Compute Engine, và GKE cho ReadOnlyMany (nhiều node mount read-only) hoàn toàn an toàn. Nhưng ReadWriteMany (nhiều node ghi đồng thời) không được hỗ trợ cho dùng thông thường (GKE Persistent Volumes). Lý do nằm ở tầng filesystem, không phải tầng disk:
ext4 và xfs là filesystem không cluster-aware — chúng giả định độc quyền truy cập block device, và cache metadata (inode, block bitmap, journal) trong RAM của node. Khi hai node cùng ghi qua một block device, mỗi node có bản cache riêng không đồng bộ với node kia; node A cấp phát một block, node B không biết và cấp phát lại chính block đó → corrupt filesystem không phục hồi. Đây không phải giới hạn nhân tạo của GCP mà là bản chất của filesystem cục bộ.
Nếu thật sự cần nhiều node ghi: dùng file storage (Filestore/Parallelstore, file 6/8) nơi NFS server làm trọng tài; hoặc một cluster filesystem (hiếm trên GKE). ReadOnlyMany của PD vẫn rất hữu ích — ví dụ nhiều Pod đọc cùng một dataset bất biến — nhưng phải đảm bảo disk được ghi xong và unmount read-write trước khi attach read-only.
Regional PD: replication đồng bộ hai-zone
PD thường là zonal — sống trong một zone, mất cả zone là mất disk (tới khi zone phục hồi). Với workload cần survive zonal failure, Regional PD cung cấp replication đồng bộ giữa hai zone trong một region: mọi write được nhân bản sang replica ở zone thứ hai trước khi ack (About regional persistent disk).
Cấu hình qua replication-type: regional-pd trong StorageClass, kèm allowedTopologies chỉ định đúng hai zone:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: regional-pd-ssd
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-ssd
replication-type: regional-pd
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
- key: topology.gke.io/zone
values:
- us-central1-a
- us-central1-bTrade-offs phải cân nhắc:
- Chi phí gần gấp đôi (hai bản dữ liệu) và latency write cao hơn (chờ ack từ zone thứ hai). Không dùng cho workload latency-critical không cần HA.
- Failover không tự động ở tầng disk thuần — khi zone chính chết, disk vẫn còn dữ liệu ở zone kia, nhưng cần một cơ chế để force-attach replica vào node ở zone còn sống. Đây là vai trò của Stateful HA Operator.
- Regional PD chỉ replicate hai zone, không phải toàn region; chọn đúng hai zone có node pool là quan trọng.
Lưu ý xu hướng: GCP đang chuyển hướng HA block storage sang Hyperdisk Balanced High Availability (hyperdisk-balanced-ha, file 4), kế nhiệm hiện đại của Regional PD với mô hình replication đồng bộ tương tự nhưng tách hiệu năng khỏi dung lượng.
Volume snapshots, cloning, expansion
Snapshots. CSI driver hỗ trợ point-in-time snapshot qua đối tượng VolumeSnapshot và VolumeSnapshotClass. Snapshot của PD là incremental ở tầng GCP — chỉ lưu block thay đổi từ snapshot trước, tiết kiệm dung lượng và chi phí. Dùng để backup, hoặc tạo PVC mới từ snapshot (restore). Đây là khối xây dựng của Backup for GKE (file 9).
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: pd-snapshot-class
driver: pd.csi.storage.gke.io
deletionPolicy: Retain # giữ snapshot khi xóa VolumeSnapshot
---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: postgres-snap-20250601
spec:
volumeSnapshotClassName: pd-snapshot-class
source:
persistentVolumeClaimName: postgres-dataMột lưu ý nhất quán quan trọng: snapshot ở tầng block là crash-consistent (như rút điện đột ngột), không phải application-consistent. Với database, cần flush/freeze hoặc dùng cơ chế backup logic của chính database (hoặc Backup for GKE với hook) để snapshot nhất quán ở mức ứng dụng.
Cloning. Từ GKE 1.22+, có thể tạo PVC mới là bản sao đầy đủ dữ liệu của một PVC nguồn (dataSource kiểu PVC) — nhanh hơn snapshot+restore cho mục đích nhân bản môi trường (ví dụ tạo staging từ prod) (GKE PD CSI Driver).
Expansion. Với allowVolumeExpansion: true trong StorageClass, có thể tăng dung lượng PVC bằng cách sửa spec.resources.requests.storage — PD hỗ trợ online resize (không cần dừng Pod) cho nhiều trường hợp. Chỉ tăng được, không giảm. File 9 đào sâu cơ chế expansion (resize disk ở GCP + resize filesystem). Bật allowVolumeExpansion ngay từ đầu là bắt buộc, vì không đổi được StorageClass của PVC đã tồn tại.
Stateful HA Operator: force-attach PD khi node hỏng
Đây là mảnh ghép giải bài toán đau nhất của stateful trên Kubernetes: khi node chạy Pod stateful chết đột ngột, Pod mới không khởi động được vì PD vẫn "attached" vào node đã chết. Kubernetes mặc định rất thận trọng: nó không tự force-detach disk khỏi một node NotReady, vì nếu node thực ra còn sống (chỉ mất mạng tạm thời) và vẫn đang ghi, force-attach vào node khác sẽ gây hai writer → corrupt. Sự thận trọng này đúng về an toàn nhưng làm Pod stateful kẹt rất lâu.
Stateful HA Operator tự động hóa và tăng tốc failover này một cách an toàn. Theo tài liệu, nó phát hiện node failure, detach volume khỏi node hỏng, và đảm bảo attach an toàn vào node failover (Stateful HA Operator). Với Regional PD, khi cả zone chết, nó force-attach replica sang node ở zone khác. Cấu hình qua CRD HighAvailabilityApplication, trong đó tham số then chốt:
apiVersion: ha.gke.io/v1
kind: HighAvailabilityApplication
metadata:
name: my-stateful-app
namespace: default
spec:
resourceSelection:
resourceKind: StatefulSet
policy:
storageSettings:
requireRegionalStorage: true
failoverSettings:
forceDeleteStrategy: AfterNodeUnreachable
afterNodeUnreachable:
afterNodeUnreachableSeconds: 20 # timeout force-delete PodafterNodeUnreachableSeconds (mặc định 20) là timeout để force-delete Pod sau khi node bị đánh dấu unreachable (Stateful HA Operator). Đặt thấp thì failover nhanh hơn nhưng tăng rủi ro force-attach khi node thực ra còn sống (network blip); đặt cao thì an toàn hơn nhưng downtime dài hơn. Đây là một trade-off RTO-vs-an-toàn phải cân theo workload — database nhạy split-brain nên thận trọng, app idempotent có thể quyết liệt hơn.
Kết hợp đúng cho HA stateful trên GKE: Regional PD (hoặc Hyperdisk Balanced HA) + StatefulSet + Stateful HA Operator + PodDisruptionBudget. Bốn mảnh này cùng đảm bảo dữ liệu replicate hai-zone, Pod identity bền vững (file 9), failover tự động nhanh, và không bị disrupt quá mức khi bảo trì.
Real-world scenario: PostgreSQL HA trên GKE
Một kiến trúc production điển hình cho PostgreSQL cần survive zonal failure:
- StorageClass: Regional PD
pd-ssd(hoặchyperdisk-balanced-ha),WaitForFirstConsumer,reclaimPolicy: Retain,allowVolumeExpansion: true. - StatefulSet với
volumeClaimTemplatesđể mỗi replica có PVC riêng identity bền vững (file 9). - Stateful HA Operator với
requireRegionalStorage: truevàafterNodeUnreachableSecondstinh chỉnh theo RTO mục tiêu. - PodDisruptionBudget
minAvailable: 1để bảo trì không hạ cả primary lẫn standby cùng lúc. - Snapshot định kỳ qua Backup for GKE với pre-backup hook gọi
CHECKPOINT/pg_backupđể nhất quán application-level (file 9).
Với cấu hình này: zonal failure → Regional PD còn dữ liệu ở zone hai → Stateful HA Operator force-attach và khởi động Pod ở node zone còn sống → downtime tính bằng chục giây thay vì chờ thủ công. Đây là sự khác biệt giữa "có HA trên giấy" và "HA thật sự hoạt động khi sự cố".
Common mistakes / anti-patterns
Đặt database trên
pd-ssddung lượng nhỏ rồi than IOPS thấp. Quên rằng IOPS scale theo dung lượng. Hệ quả: latency cao, throttle I/O không lý giải. Phòng tránh: tăng dung lượng để có IOPS, hoặc chuyểnpd-extreme/Hyperdisk để provision IOPS riêng.Thử
ReadWriteManytrên PD cho shared write. Corrupt filesystem khi hai node ghi. Phòng tránh: RWX = Filestore/Parallelstore, không bao giờ PD.Dùng zonal PD cho workload cần HA. Mất cả zone là outage dài. Phòng tránh: Regional PD / Hyperdisk Balanced HA + Stateful HA cho workload critical.
Tưởng snapshot block là application-consistent. Restore một database từ snapshot crash-consistent có thể cần recovery, hoặc tệ hơn là không nhất quán. Phòng tránh: dùng hook/quiesce hoặc Backup for GKE với pre-backup hook.
Không cấu hình Stateful HA, dựa vào failover mặc định. Pod stateful kẹt rất lâu khi node chết đột ngột. Phòng tránh: triển khai Stateful HA Operator cho mọi stateful workload critical.
Bỏ qua per-node attach limit khi thiết kế. Nhiều PVC nhỏ làm node hết slot disk trước khi hết CPU, gây Pending. Phòng tránh: tính attach limit vào capacity planning; gộp dữ liệu nếu hợp lý.
Official references
- GKE PD CSI Driver — enable driver, StorageClass parameters, snapshot/clone/expansion.
- GKE Persistent Volumes — access modes, RWX không hỗ trợ trên PD.
- About regional persistent disk — replication đồng bộ hai-zone.
- Provisioning regional PD và Hyperdisk Balanced HA — cấu hình regional storage.
- Stateful HA Operator — force-attach,
afterNodeUnreachableSeconds, failover policy. - Compute Engine disk performance — quan hệ IOPS/throughput với dung lượng và machine type.