0

PostgreSQL Bài 50: Triển khai cụm PostgreSQL High Availability trên Kubernetes bằng Zalando Postgres Operator

Ở Bài 49, chúng ta đã xây dựng thành công kiến trúc High Availability (HA) hoàn chỉnh trên môi trường máy chủ ảo (VM/Bare-metal). Chúng ta phải tự tay cấu hình Patroni, etcd, cài đặt HAProxy, và khởi chạy PgBouncer.

Nhưng khi chuyển dịch lên môi trường Kubernetes (K8s), việc quản lý thủ công các Stateful workloads như Database là một cơn ác mộng (phải xử lý Persistent Volumes, StatefulSets, cấu hình mạng Pod-to-Pod). Để giải quyết triệt để vấn đề này, mô hình Operator Pattern ra đời. Bài học này sẽ hướng dẫn bạn sử dụng công cụ mạnh mẽ nhất trong hệ sinh thái K8s cho PostgreSQL: Zalando Postgres Operator.

image.png

1. Operator Pattern là gì và Sức mạnh của Zalando?

Trong Kubernetes, Operator đóng vai trò như một "Quản trị viên Database (DBA) bằng code" chạy ngầm 24/7. Thay vì bạn phải tự cấu hình từng Pod, bạn chỉ cần khai báo: "Tôi muốn một cụm PostgreSQL version 15, có 3 node, dung lượng 50GB mỗi node, tự động có PgBouncer". Operator sẽ tự động thực hiện mọi thao tác (tạo ổ đĩa, cài đặt DB, cấu hình HA, giám sát) để đạt được trạng thái đó.

Kiến trúc lõi của Zalando Postgres Operator bao gồm:

  1. Tiến trình Operator (postgres-operator): Chạy như một Deployment độc lập trong K8s. Nó lắng nghe các đối tượng Custom Resource (CRD) do bạn tạo ra.

  2. Container Image Spilo: Thay vì dùng image postgres nguyên bản từ DockerHub, Zalando dùng image tự chế tên là Spilo. Spilo đóng gói sẵn: PostgreSQL, Patroni (quản lý HA), PgBouncer (Connection pooling) và WAL-G (để backup lên S3).

  3. K8s API thay cho etcd/ZooKeeper: Patroni bên trong Spilo không cần bạn phải dựng thêm cụm etcd riêng! Nó sử dụng trực tiếp Kubernetes API (thông qua đối tượng Endpoints hoặc ConfigMaps) để lưu trữ trạng thái bầu chọn Master (Leader Election).

2. Giải pháp Định tuyến (Routing) không cần HAProxy

Trên K8s, HAProxy trở nên thừa thãi. Zalando Operator tự động giải quyết bài toán định tuyến Read/Write thông qua Kubernetes Services và Label Selectors.

Khi bạn khởi tạo cụm tên là my-db, Operator sẽ tự động tạo ra 2 K8s Service:

  • my-db (Master Service): Trỏ duy nhất vào Pod đang giữ vai trò Master.

  • my-db-repl (Replica Service): Trỏ vào tất cả các Pod đang giữ vai trò Slave (Read-only).

Phép màu diễn ra như thế nào khi Master bị sập?

  1. Pod Master hiện tại (pod-0) bị crash.

  2. Patroni trong các Pod còn lại lập tức bầu ra Master mới (ví dụ: pod-1).

  3. Patroni trên pod-1 thay đổi nhãn (label) của chính nó thành spilo-role: master. Đồng thời nó gỡ nhãn master khỏi pod-0.

  4. Kubernetes Service my-db liên tục theo dõi nhãn spilo-role: master. Khi nhãn thay đổi, Service tự động cập nhật Endpoint, chuyển toàn bộ traffic (luồng Ghi) từ pod-0 sang pod-1 ngay lập tức! Ứng dụng Backend chỉ cần kết nối vào tên miền nội bộ my-db:5432 cho luồng Ghi và my-db-repl:5432 cho luồng Đọc.

3. Thực hành: Cài đặt và Khởi tạo Cụm PostgreSQL HA

Bước 1: Cài đặt Zalando Postgres Operator qua Helm

Bạn cần có một cụm Kubernetes (Minikube, EKS, GKE) và Helm đã cài đặt.

Bash

# Thêm Helm repo của Zalando
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator

# Cài đặt Operator vào K8s
helm install postgres-operator postgres-operator-charts/postgres-operator

Bước 2: Viết file Khai báo Cụm (Manifest YAML)

Đây là toàn bộ những gì bạn cần viết để tạo ra một cụm Database Production-ready thay vì phải viết hàng ngàn dòng script Bash:

Tạo file cluster.yaml:

YAML

apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: acid-production-db
  namespace: default
spec:
  teamId: "acid"
  volume:
    size: 50Gi
  numberOfInstances: 3            # Tạo 3 node (1 Master, 2 Slaves)
  users:
    api_user:                     # Tự động tạo user cho backend
    - superuser
    - createdb
  databases:
    my_app_db: api_user           # Tự động tạo database và gán quyền owner
  postgresql:
    version: "15"                 # Phiên bản PostgreSQL
  enableConnectionPooler: true    # SIÊU VIỆT: Tự động deploy thêm Pod PgBouncer
  allowedSourceRanges:
    - 10.0.0.0/8                  # Bảo mật mạng

Bước 3: Triển khai và Kiểm tra

Bash

# Apply cấu hình
kubectl apply -f cluster.yaml

# Theo dõi quá trình Operator tạo StatefulSet và các Pod
kubectl get pods -l application=spilo -w

Sau vài phút, chạy lệnh kiểm tra Service:

Bash

kubectl get svc | grep acid-production-db

Bạn sẽ thấy K8s trả về:

  • acid-production-db (Cổng 5432) ──► Đi vào Master (Write).

  • acid-production-db-repl (Cổng 5432) ──► Đi vào Slaves (Read).

  • acid-production-db-pooler (Cổng 5432) ──► Kết nối PgBouncer Transaction Pooling siêu tốc.

4. Tự động hóa Backup lên S3 (WAL-G)

Ngoài HA, Zalando Operator tích hợp cực kỳ sâu công cụ sao lưu vật lý WAL-G (phiên bản hiện đại của WAL-E).

Bạn chỉ cần cấu hình thông tin AWS S3 Bucket và Access Key vào ConfigMap của Operator. Từ đó, mỗi khi cụm acid-production-db chạy:

  • Định kỳ hàng ngày nó tự động nén toàn bộ thư mục PGDATA đẩy lên S3 (Base Backup).

  • Mỗi khi có file WAL mới (như học ở Bài 33), WAL-G tự động stream file đó lên S3.

Nếu lỡ tay làm rơi database, bạn chỉ cần tạo một file YAML mới mang tên acid-production-db-clone, chỉ định thêm tham số clone: trỏ tới mốc thời gian (Timestamp) trong quá khứ. Operator sẽ tự động tải Base Backup từ S3 về và phát lại WAL (PITR - Point-in-Time Recovery) để hồi sinh database sang một cụm K8s hoàn toàn mới.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí