PostgreSQL High Availability trên Kubernetes: Hướng dẫn thực hành CloudNativePG

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Khởi đầu nhanh: Cụm HA đầu tiên của bạn trong chưa đầy 5 phút

Quản trị một cụm PostgreSQL chuẩn production trên Kubernetes từng giống như đi trên dây. Bạn phải cân bằng độ trễ replication thủ công, xử lý các đợt failover đáng sợ và vật lộn với các StatefulSet cơ bản. CloudNativePG (CNPG) thay đổi cuộc chơi bằng cách sử dụng mô hình ‘Operator’. Nó coi Postgres như một ‘first-class citizen’ hiểu rõ trạng thái nội tại của chính mình, thay vì chỉ là một container thông thường.

Bắt đầu bằng cách cài đặt CloudNativePG operator. Hãy coi đây là một ‘DBA kỹ thuật số’ luôn túc trực 24/7 để quản lý các cơ sở dữ liệu của bạn:

kubectl apply -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/releases/cnpg-1.24.0.yaml

Khi operator đã hoạt động, bạn có thể triển khai một cụm high-availability 3 node bằng một file YAML đơn giản. Tôi thường sử dụng file cluster.yaml như sau:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: production-db
spec:
  instances: 3
  storage:
    size: 20Gi
  # Phân tán các pod trên các physical node khác nhau để đảm bảo an toàn
  affinity:
    enablePodAntiAffinity: true
    topologyKey: "kubernetes.io/hostname"

Chạy lệnh kubectl apply -f cluster.yaml. Trong khoảng ba phút, ba pod sẽ xuất hiện. Một pod đóng vai trò Primary (read/write), trong khi hai pod còn lại đóng vai trò Replica. Nếu node Primary gặp sự cố, operator sẽ phát hiện lỗi heartbeat và nâng cấp một replica lên thay thế chỉ trong vài giây. Không cần can thiệp thủ công lúc 3 giờ sáng.

Cách Operator xử lý các chi tiết kỹ thuật phức tạp

Tại sao không dùng StatefulSet tiêu chuẩn? Các controller K8s truyền thống quá ‘ngây ngô’ đối với các cơ sở dữ liệu stateful. Chúng không biết liệu một DB đang thực hiện dở dang transaction hay replication đang bị mất đồng bộ. Tuy nhiên, CNPG nằm ngay trong reconciliation loop.

Vòng lặp điều hòa (Reconciliation Loop) thông minh

Operator giám sát cụm của bạn sau mỗi vài giây. Nó theo dõi sức khỏe của Primary, độ trễ replica và sự ổn định của node. Nếu một node lỗi, operator không chỉ ngồi chờ nó khôi phục. Nó sẽ lập tức cấp phát một pod mới trên một node khỏe mạnh, clone dữ liệu từ Primary và đồng bộ lại vào cụm. Trong các thử nghiệm của tôi, quy trình tự phục hồi (self-healing) này thường hoàn tất trước khi các cảnh báo giám sát kịp kích hoạt.

Failover mà không gặp ác mộng ‘Split-Brain’

Sự cố là không thể tránh khỏi, nhưng hỏng dữ liệu thì không nên xảy ra. CNPG sử dụng giao thức fencing nghiêm ngặt để đảm bảo Primary cũ bị cô lập hoàn toàn trước khi nâng cấp cái mới. Điều này ngăn chặn kịch bản ‘split-brain’ nơi hai node cùng cố gắng ghi vào cùng một dữ liệu đồng thời. Tôi đã thấy nhiều hệ thống tự thiết lập thất bại thảm hại vì lỗi này; CNPG biến nó thành chuyện nhỏ.

Sao lưu và Khôi phục tại thời điểm bất kỳ (PITR)

Một cơ sở dữ liệu chỉ thực sự tốt khi bản restore cuối cùng của nó thành công. CNPG tích hợp với Barman (Backup and Recovery Manager) để stream dữ liệu trực tiếp đến object storage như AWS S3 hoặc MinIO. Đây không chỉ là bản dump hàng đêm; đó là quá trình lưu trữ WAL (Write-Ahead Log) liên tục.

Dưới đây là cấu hình sao lưu S3 đã được kiểm chứng qua thực tế:

spec:
  backup:
    barmanObjectStore:
      destinationPath: s3://my-backups-bucket/pg-data
      s3Credentials:
        accessKeyId:
          name: s3-creds
          key: ACCESS_KEY_ID
        secretAccessKey:
          name: s3-creds
          key: SECRET_ACCESS_KEY
      wal:
        compression: gzip
    retentionPolicy: "30d"

Cấu hình này là một ‘cứu cánh’. Nếu một developer vô tình xóa mất một bảng quan trọng ở môi trường production lúc 2:15 PM, bạn có thể quay ngược toàn bộ cơ sở dữ liệu về thời điểm 2:14:55 PM. Khả năng khôi phục chính xác đến từng giây mang lại một mạng lưới an toàn tuyệt vời cho bất kỳ đội ngũ nào.

Tối ưu hóa việc nhập dữ liệu

Việc di chuyển dữ liệu cũ vào một cụm K8s hiện đại thường gặp rắc rối với định dạng. Khi cần chuyển đổi dữ liệu thô nhanh chóng, tôi thường dùng toolcraft.app/vi/tools/data/csv-to-json. Vì công cụ này chạy hoàn toàn trong trình duyệt, dữ liệu nhạy cảm của bạn sẽ không bao giờ rời khỏi máy tính, khiến nó trở thành lựa chọn bảo mật để chuẩn bị metadata trước khi chạy các script import SQL.

Những bài học xương máu từ môi trường Production

Sau khi quản trị nhiều cụm CNPG trên môi trường production, tôi đã đúc kết được một vài quy tắc thiết yếu để có một hệ thống ổn định.

1. Cố định tài nguyên (Resource Pinning)

Postgres rất “ngốn” RAM. Nếu bạn không thiết lập giới hạn nghiêm ngặt, Kubernetes OOM (Out Of Memory) Killer cuối cùng sẽ “trảm” database của bạn khi traffic tăng đột biến. Tôi luôn đặt requestslimits ở cùng một giá trị. Với khối lượng công việc trung bình, hãy bắt đầu với 4Gi RAM và 2 CPU, sau đó mở rộng dựa trên dữ liệu từ pg_stat_statements.

2. Ưu tiên độ trễ lưu trữ

Lưu trữ qua mạng thì tiện lợi nhưng chậm. Đối với các cơ sở dữ liệu có lượng transaction cao, hãy sử dụng các phân vùng hiệu năng cao như AWS io2 hoặc GCP premium-rwo. Nếu bạn có thể sử dụng Local Persistent Volumes (LPV) với ổ cứng NVMe, hiệu năng thường sẽ tăng vọt từ 3 đến 5 lần so với đĩa cloud tiêu chuẩn.

3. Sử dụng Plugin CLI của CNPG

Đừng chỉ dựa vào kubectl get pods để kiểm tra sức khỏe DB. Hãy cài đặt plugin CNPG để xem chi tiết trạng thái replication:

kubectl cnpg status production-db

Lệnh này cho bạn thấy chính xác node nào là Primary, độ trễ replication cụ thể theo byte, và liệu các bản backup liên tục của bạn có thực sự ổn định hay không.

4. Nâng cấp “nhẹ nhàng”

Việc nâng cấp phiên bản Postgres từng là một dự án kéo dài cả cuối tuần. Với CNPG, nó diễn ra cực kỳ nhẹ nhàng. Khi bạn cập nhật phiên bản image trong file YAML, operator sẽ thực hiện rolling update. Nó sẽ patch các replica trước, thực hiện một đợt switchover có kiểm soát, sau đó mới patch node Primary cũ. Thời gian downtime thường dưới 5 giây.

Bằng cách giao phó các công việc vận hành nặng nhọc cho CloudNativePG operator, bạn sẽ không còn phải đóng vai ‘lao công cơ sở dữ liệu’ mà có thể tập trung vào code. Nó mang lại cho bạn sức mạnh của một dịch vụ được quản lý như AWS RDS nhưng với quyền kiểm soát hoàn toàn và chi phí thấp hơn trên các node Kubernetes của riêng bạn.

Share: