Workstation Logo
ผลิตภัณฑ์
AI LabsOpenAI AgentsClaude AgentsGrok BotWorkstation CRM (WSL CRM)การตลาดผลิตภัณฑ์ทั้งหมด
โซลูชัน AI
เวิร์กสเตชัน AIAI SME PackagesAI ส่วนตัวคลัสเตอร์ GPUEdge AIแล็บ AI องค์กรAI ตามอุตสาหกรรม
บริการ
Platform ModernisationDigital EngineeringData Foundations & AIAutonomous Operationsที่ปรึกษา AIระบบอัตโนมัติ DevOpsความมั่นคงปลอดภัยไซเบอร์การพัฒนาซอฟต์แวร์การสร้างเอเจนต์การตั้งค่า MLOps
เกี่ยวกับเรา
พาร์ทเนอร์เรื่องราวลูกค้า
บทความ
เอกสาร
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
บล็อก
ติดต่อเราLogin
Workstation

เวิร์กสเตชัน AI ซอฟต์แวร์มัลติเอเจนต์ AI โครงสร้างพื้นฐาน GPU และโซลูชันเอเจนต์อัจฉริยะสำหรับธุรกิจยุคใหม่

ติดต่อเรา

โซลูชัน AI

เวิร์กสเตชัน AIAI SME PackagesAI ส่วนตัวคลัสเตอร์ GPUEdge AIแล็บ AI องค์กรAI ตามอุตสาหกรรม

ผลิตภัณฑ์

ผลิตภัณฑ์ทั้งหมดWSL CRM และ ERPการตลาดOpenAI AgentsWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

บริษัท

เกี่ยวกับเราทำไมต้อง Workstationพาร์ทเนอร์เรื่องราวลูกค้าราคาติดต่อ

แหล่งข้อมูล

บทความเอกสารประกอบบล็อกค้นหาแผนผังเว็บไซต์
สำนักงานสหราชอาณาจักร
77-79 Marlowes, Hemel Hempstead HP1 1LFเส้นทาง - ออกทางแยกที่ 20 จาก M25 Outer Londonเลขทะเบียนบริษัท: 11641870จ. - ศ.: 9:00 - 18:00 น. GMT
+44 7515 356 146
สำนักงานเบลเยียม
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683จ. - ศ.: 9:00 - 18:00 น. CET
+32 492 45 67 46
สำนักงานอินเดีย
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI สงวนลิขสิทธิ์

ความเป็นส่วนตัวคุกกี้ข้อกำหนดการให้บริการแผนผังเว็บไซต์

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

ความพร้อมใช้งานสูง PostgreSQL พร้อมตัวดำเนินการ Zalando Postgres: คู่มือการปรับใช้ Multi-Cloud Kubernetes

ปรับใช้ PostgreSQL HA ระดับการผลิตจริงกับ Zalando Operator บนแพลตฟอร์ม Kubernetes ใดก็ได้

Balinder Walia12 เมษายน 256919 min read
บทนำ

: ทำไม PostgreSQL ถึงมีความพร้อมใช้งานสูงบน Kubernetes จึงมีความสำคัญกับ

การรัน PostgreSQL ในการผลิตต้องการความพร้อมใช้งานสูง (HA) เวลาหยุดทำงานที่วัดเป็นนาทีอาจทำให้องค์กรต้องสูญเสียรายได้หลายล้านดอลลาร์ กัดกร่อนความไว้วางใจของลูกค้า และละเมิดข้อตกลงระดับการให้บริการ Kubernetes ได้กลายเป็นแพลตฟอร์มโดยพฤตินัยสำหรับการจัดการปริมาณงานในคอนเทนเนอร์ แต่การใช้บริการ stateful เช่น PostgreSQL บน Kubernetes ทำให้เกิดความท้าทายที่ไม่เหมือนใคร ได้แก่ การจัดการพื้นที่จัดเก็บข้อมูลแบบถาวร การเลือกผู้นำ การเฟลโอเวอร์อัตโนมัติ การจัดเตรียมการสำรองข้อมูล และการรวมการเชื่อมต่อ

Zalando Postgres Operatorเป็นโซลูชันโอเพ่นซอร์สที่ผ่านการทดสอบการต่อสู้แล้ว ซึ่ง Zalando ซึ่งเป็นผู้ค้าปลีกแฟชั่นออนไลน์รายใหญ่ที่สุดของยุโรป สร้างขึ้นเพื่อจัดการคลัสเตอร์ PostgreSQL หลายร้อยรายการในการผลิต โดยใช้ประโยชน์จากPatroniสำหรับการเลือกตั้งผู้นำตามฉันทามติ,Spiloเป็นอิมเมจคอนเทนเนอร์ PostgreSQL,WAL-Gสำหรับการเก็บถาวรอย่างต่อเนื่องและการกู้คืน ณ เวลาเฉพาะจุด และPgBouncerสำหรับการรวมการเชื่อมต่อ ส่วนประกอบเหล่านี้ร่วมกันนำเสนอการปรับใช้ PostgreSQL แบบซ่อมแซมตัวเองอัตโนมัติโดยสมบูรณ์ ซึ่งทำงานได้กับการกระจาย Kubernetes ใดๆ ตั้งแต่บริการคลาวด์ที่ได้รับการจัดการ เช่น AWS EKS, Azure AKS และ Google GKE ไปจนถึงคลัสเตอร์ Bare Metal ที่ใช้งาน k3s กับ Rancher

ในคู่มือที่ครอบคลุมนี้ เราจะสำรวจสถาปัตยกรรมของ Zalando Postgres Operator อธิบายการติดตั้งและการกำหนดค่าบนแพลตฟอร์ม Kubernetes หลายแพลตฟอร์ม เจาะลึกในการจำลองแบบ การสำรองข้อมูล การกู้คืนความเสียหาย การตรวจสอบ และการปรับแต่งการผลิต ในตอนท้าย คุณจะมีความรู้ในการปรับใช้และดำเนินการคลัสเตอร์ PostgreSQL HA ระดับการผลิตบนโครงสร้างพื้นฐาน Kubernetes ใดๆ

สถาปัตยกรรมตัวดำเนินการ Zalando Postgres

การทำความเข้าใจสถาปัตยกรรมเป็นสิ่งสำคัญก่อนที่จะปรับใช้ ตัวดำเนินการ Zalando Postgres เป็นไปตามรูปแบบตัวดำเนินการ Kubernetes โดยจะเฝ้าดู Custom Resource Definitions (CRDs) ประเภทpostgresqlและปรับสถานะที่ต้องการให้เป็นทรัพยากร Kubernetes จริง ส่วนประกอบต่างๆ เข้ากันได้ดังนี้:

สถาปัตยกรรมตัวดำเนินการ Zalando PostgresPostgreSQL CRDประเภท: postgresqlPostgres โอเปอเรเตอร์นาฬิกา & ปรับยอดชุดสถานะจัดการวงจรการใช้งาน Podพ็อดหลักเล่น (PostgreSQL)ตัวแทนผู้อุปถัมภ์พ็อดจำลอง 1เล่น (PostgreSQL)ตัวแทนผู้อุปถัมภ์แบบจำลอง Pod 2เล่น (PostgreSQL)ตัวแทนผู้อุปถัมภ์Patroni DCS (Kubernetes API)การเลือกตั้งผู้นำ & สถานะคลัสเตอร์PgBouncerการรวมการเชื่อมต่อWAL-Gสำรองข้อมูลไปยัง S3/GCS/Azureหลักแบบจำลองฉันทามติ/DCSสำรองพูลการเชื่อมต่อ

ตอน: อิมเมจคอนเทนเนอร์ PostgreSQL

Spiloเป็นอิมเมจ Docker ของ Zalando ที่รวม PostgreSQL เข้ากับ Patroni, WAL-G และส่วนขยายที่จำเป็น แต่ละพ็อดใน StatefulSet เรียกใช้คอนเทนเนอร์ Spilo ที่จับสปิโล:

  • เซิร์ฟเวอร์ PostgreSQL— โปรแกรมฐานข้อมูลเอง รองรับเวอร์ชัน 13 ถึง 16
  • Patroni— ตัวแทน HA ที่จัดการการเลือกผู้นำ การจำลองแบบ และเฟลโอเวอร์
  • WAL-G— เครื่องมือเก็บถาวร WAL และสำรองข้อมูลฐานอย่างต่อเนื่อง
  • pg_cron, pg_stat_statements, PostGIS— ส่วนขยายที่จำเป็นทั่วไป
  • ที่ติดตั้งไว้ล่วงหน้า

Patroni: การเลือกตั้งผู้นำและการเฟลโอเวอร์อัตโนมัติ

Patroni คือหัวใจสำคัญของกลไก HA ใช้ Distributed Configuration Store (DCS) เพื่อรักษาสถานะคลัสเตอร์และดำเนินการเลือกผู้นำ ในบริบทของโอเปอเรเตอร์ Zalando Patroni ใช้Kubernetes APIเองเป็น DCS (ผ่าน Endpoints หรือ ConfigMaps) โดยไม่จำเป็นต้องใช้ etcd ภายนอกหรือคลัสเตอร์ ZooKeeper

กระบวนการเฟลโอเวอร์ของ Patroni ทำงานดังนี้:

  1. การตรวจสอบสภาพ— เจ้าหน้าที่ Patroni แต่ละตัวจะตรวจสอบอินสแตนซ์ PostgreSQL ในเครื่องของตนอย่างต่อเนื่อง และรายงานสถานภาพไปยัง DCS
  2. Leader lock— ตัวหลักเก็บล็อคผู้นำใน DCS (วัตถุ Kubernetes Endpoint) ล็อคมี TTL (ค่าเริ่มต้น 30 วินาที)
  3. การตรวจหาความล้มเหลว— หากตัวหลักล้มเหลวในการต่ออายุการล็อคภายใน TTL ตัวจำลองจะตรวจจับการไม่มีอยู่
  4. Election— แบบจำลองที่มีสิทธิ์แข่งขันเพื่อชิงตำแหน่งผู้นำ แบบจำลองที่มีความล่าช้าในการจำลองน้อยที่สุดจะชนะ
  5. โปรโมชั่น— แบบจำลองที่ชนะจะเลื่อนระดับตัวเองเป็นแบบจำลองหลัก อัปเดต DCS และจุดสิ้นสุดบริการ Kubernetesmasterจะอัปเดตโดยอัตโนมัติ
  6. Fencing— รั้วหลักแบบเก่าถูกกั้นรั้ว (หยุดหรือลดระดับเป็นแบบจำลอง) เพื่อป้องกันไม่ให้สมองแตกแยก
โดยทั่วไป

กระบวนการเฟลโอเวอร์นี้จะเสร็จสิ้นภายใน15-30 วินาทีเพื่อให้มั่นใจว่าแอปพลิเคชันของคุณมีเวลาหยุดทำงานน้อยที่สุด

WAL-G: การเก็บถาวรและสำรองข้อมูลอย่างต่อเนื่อง

WAL-G เป็นเครื่องมือเก็บถาวรรุ่นใหม่สำหรับ PostgreSQL ที่รองรับการสำรองข้อมูลไปยัง S3, Google Cloud Storage (GCS) และ Azure Blob Storage มันมี:

  • การสำรองข้อมูลพื้นฐาน— การสำรองข้อมูลทางกายภาพแบบเต็มโดยใช้pg_basebackup
  • WAL การเก็บถาวร— การจัดส่งบันทึกการเขียนล่วงหน้าอย่างต่อเนื่องสำหรับการกู้คืน ณ เวลาใดเวลาหนึ่ง
  • การสำรองข้อมูลเดลต้า— การสำรองข้อมูลส่วนเพิ่มที่เก็บเฉพาะหน้าที่เปลี่ยนแปลง
  • การเข้ารหัส— การเข้ารหัส AES-256 ของการสำรองข้อมูลที่เหลือ
  • การบีบอัด— การบีบอัด LZ4 หรือ ZSTD เพื่อลดต้นทุนการจัดเก็บ

Kubernetes ลำดับชั้นทรัพยากร

เมื่อคุณสร้างpostgresqlCustom Resource ตัวดำเนินการจะสร้างชุดทรัพยากร Kubernetes ที่ครอบคลุมเพื่อจัดการคลัสเตอร์ การทำความเข้าใจลำดับชั้นนี้เป็นสิ่งสำคัญสำหรับการแก้ไขปัญหาและการตรวจสอบ:

Kubernetes ลำดับชั้นทรัพยากร — ผู้ดำเนินการ Zalandopostgresql CRDPostgres โอเปอเรเตอร์ชุดเก็บสถานะบริการ(มาสเตอร์)บริการ(แบบจำลอง)จุดสิ้นสุดPDBพ็อดPVCsความลับPgBouncer ปรับใช้บริการ (พูลเลอร์)หลักแบบจำลองแบบจำลองเส้นทึบ = การสร้างโดยตรง | เส้นประ = การสร้างเงื่อนไขทรัพยากร

ที่สร้างโดยผู้ดำเนินการ

  • StatefulSet— จัดการพ็อด PostgreSQL ด้วยข้อมูลประจำตัวเครือข่ายที่เสถียรและสั่งการใช้งาน
  • Services— บริการ ClusterIP สองบริการ:<cluster-name>สำหรับบริการหลักและ<cluster-name>-replสำหรับการจำลองการอ่าน
  • Endpoints— Patroni อัปเดตตำแหน่งข้อมูลให้ชี้ไปยังผู้นำในปัจจุบันเพื่อการเฟลโอเวอร์ที่ราบรื่น
  • PodDisruptionBudgets (PDB)— ตรวจสอบให้แน่ใจว่าอย่างน้อยหนึ่งอินสแตนซ์ยังคงพร้อมใช้งานระหว่างการหยุดชะงักโดยสมัครใจ
  • Secrets— PostgreSQL superuser, replication และข้อมูลรับรองแอปพลิเคชันที่จัดเก็บไว้เป็นความลับ Kubernetes
  • PersistentVolumeClaims (PVCs)— หนึ่ง PVC ต่อพ็อดสำหรับ PostgreSQL ที่เก็บข้อมูล
  • PgBouncer Deployment— ตัวเลือกการเชื่อมต่อพูลเลอร์ปรับใช้เป็นการปรับใช้แยกต่างหากพร้อมบริการของตัวเอง
การติดตั้ง

บนแพลตฟอร์ม Kubernetes หลายแพลตฟอร์ม

ข้อกำหนดเบื้องต้น

ก่อนที่จะติดตั้ง Zalando Postgres Operator ตรวจสอบให้แน่ใจว่าคุณมี:

  • คลัสเตอร์ Kubernetes ที่ทำงานอยู่ (v1.25+)
  • kubectlกำหนดค่าด้วยการเข้าถึง
  • ของผู้ดูแลระบบคลัสเตอร์
  • helmv3 ติดตั้ง
  • แล้ว
  • StorageClass เริ่มต้นกำหนดค่า
การติดตั้งตัวดำเนินการ

ผ่าน Helm

วิธีการติดตั้งที่แนะนำคือ Helm ซึ่งทำงานอย่างสม่ำเสมอบนแพลตฟอร์ม Kubernetes ทั้งหมด:

# Add the Zalando Postgres Operator Helm repository
helm repo add postgres-operator-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm repo add postgres-operator-ui-charts https://opensource.zalando.com/postgres-operator/charts/postgres-operator-ui
helm repo update

# Create a dedicated namespace
kubectl create namespace postgres-operator

# Install the operator with custom values
helm install postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configKubernetes.enable_pod_antiaffinity=true \
  --set configKubernetes.pod_environment_configmap=postgres-pod-config \
  --set configAwsOrGcp.aws_region=us-east-1 \
  --set configLoadBalancer.db_hosted_zone=db.example.com \
  --set configConnectionPooler.connection_pooler_default_cpu_request=500m \
  --set configConnectionPooler.connection_pooler_default_memory_request=100Mi

# Optionally install the operator UI for visual management
helm install postgres-operator-ui postgres-operator-ui-charts/postgres-operator-ui \
  --namespace postgres-operator

ตรวจสอบว่าโอเปอเรเตอร์กำลังทำงานอยู่:

kubectl get pods -n postgres-operator
# Expected output:
# NAME                                 READY   STATUS    RESTARTS   AGE
# postgres-operator-7f8b9c6d4-x2k9j   1/1     Running   0          2m
ข้อมูลจำเพาะการปรับใช้

AWS EKS

Amazon EKS ต้องการการกำหนดค่าเฉพาะเพื่อประสิทธิภาพ PostgreSQL ที่เหมาะสมที่สุด:

# EKS-specific Helm values (eks-values.yaml)
configAwsOrGcp:
  aws_region: us-east-1
  enable_ebs_gp3_migration: true
  additional_secret_mount: "aws-iam-token"

configKubernetes:
  enable_pod_antiaffinity: true
  pod_environment_configmap: "postgres-pod-config"
  spilo_privileged: false
  storage_resize_mode: pvc

# Use EBS gp3 StorageClass for better performance
# Create the StorageClass first:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-gp3-postgres
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: "6000"
  throughput: "400"
  encrypted: "true"
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true

สำหรับการสำรองข้อมูล WAL-G บน EKS ให้กำหนดค่าบทบาท IAM สำหรับบัญชีบริการ (IRSA):

# Create IAM policy for WAL-G S3 access
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:ListBucket",
        "s3:DeleteObject",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::my-pg-backups",
        "arn:aws:s3:::my-pg-backups/*"
      ]
    }
  ]
}

Azure AKS การปรับใช้

Azure AKS ใช้ดิสก์ Azure สำหรับการจัดเก็บข้อมูลถาวรและ Managed Identity สำหรับการตรวจสอบสิทธิ์การสำรองข้อมูล:

# AKS-specific StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-premium-postgres
provisioner: disk.csi.azure.com
parameters:
  skuName: Premium_LRS
  cachingMode: ReadOnly
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# WAL-G backup to Azure Blob Storage environment variables
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: default
data:
  AZURE_STORAGE_ACCOUNT: "pgbackupsstorage"
  AZURE_STORAGE_ACCESS_KEY: "" # Use Managed Identity instead
  WALG_AZ_PREFIX: "azure://pg-wal-backups/$(SCOPE)"
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  BACKUP_SCHEDULE: "0 2 * * *"
  BACKUP_NUM_TO_RETAIN: "7"

การปรับใช้ Google GKE

Google Kubernetes Engine ใช้ Persistent Disk และ Workload Identity สำหรับการเข้าถึงข้อมูลสำรอง GCS:

# GKE StorageClass for SSD Persistent Disks
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ssd-postgres
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
---
# GCS backup configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: default
data:
  WALG_GS_PREFIX: "gs://my-pg-backups/$(SCOPE)"
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  GOOGLE_APPLICATION_CREDENTIALS: "/var/secrets/google/key.json"
  BACKUP_SCHEDULE: "0 2 * * *"
  BACKUP_NUM_TO_RETAIN: "7"

Bare Metal k3s/Rancher พร้อมที่เก็บ Longhorn

สำหรับการปรับใช้ภายในองค์กร k3s มอบการกระจาย Kubernetes ที่มีน้ำหนักเบา และ Longhorn นำเสนอพื้นที่จัดเก็บแบบบล็อกแบบกระจาย การรวมกันนี้เหมาะอย่างยิ่งเมื่อคุณต้องการควบคุมโครงสร้างพื้นฐานของคุณโดยสมบูรณ์โดยไม่ต้องผูกมัดกับผู้จำหน่ายระบบคลาวด์

# Install k3s on all nodes
# Master node:
curl -sfL https://get.k3s.io | sh -s - server \
  --cluster-init \
  --disable traefik \
  --write-kubeconfig-mode 644

# Worker nodes:
curl -sfL https://get.k3s.io | sh -s - agent \
  --server https://master-ip:6443 \
  --token $(cat /var/lib/rancher/k3s/server/node-token)

# Install Longhorn for persistent storage
helm repo add longhorn https://charts.longhorn.io
helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set defaultSettings.defaultReplicaCount=3 \
  --set defaultSettings.defaultDataPath=/mnt/longhorn

# Install MetalLB for LoadBalancer services
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml

# Configure MetalLB IP pool
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: postgres-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.200-192.168.1.210
k3s / Rancher การปรับใช้โลหะเปลือยเซิร์ฟเวอร์การจัดการ Rancherโหนด 1 (เซิร์ฟเวอร์ k3s)PostgreSQL หลักเล่น + Patroniโอเปอเรเตอร์ ZalandoPgBouncer พูลวอลลุ่มเสียงยาว/mnt/longhorn (3 แบบจำลอง)โหนด 2 (เซิร์ฟเวอร์ k3s)PostgreSQL แบบจำลองเล่น + PatroniPgBouncer พูลPrometheus ผู้ส่งออกลองฮอร์น โวลุ่ม/mnt/longhorn (3 แบบจำลอง)โหนด 3 (เอเจนต์ k3s)PostgreSQL แบบจำลองเล่น + ผู้อุปถัมภ์PgBouncer พูลGrafana แดชบอร์ดลองฮอร์น โวลุ่ม/mnt/longhorn (3 แบบจำลอง)HAProxy / MetalLB LoadBalancerWAL-G การสำรองข้อมูลNFS / MiniIO S3 ที่เข้ากันได้กับหลักแบบจำลองPgBouncerลองฮอร์นการจำลองแบบสตรีมมิ่ง

PostgreSQL คลัสเตอร์ CRD ข้อมูลจำเพาะ

แกนหลักของการปรับใช้ a คลัสเตอร์ PostgreSQL ที่มีตัวดำเนินการ Zalando คือpostgresqlCustom Resource ไฟล์ Manifest YAML นี้ประกาศสถานะคลัสเตอร์ที่ต้องการ และผู้ปฏิบัติงานจะปรับให้คลัสเตอร์เป็นจริง ด้านล่างนี้คือข้อกำหนด CRD ที่ครอบคลุมและพร้อมสำหรับการผลิต:

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-production-cluster
  namespace: databases
  labels:
    team: platform
    environment: production
spec:
  teamId: "platform"
  volume:
    size: 100Gi
    storageClass: ebs-gp3-postgres
  numberOfInstances: 3
  enableConnectionPooler: true
  enableReplicaConnectionPooler: true
  connectionPooler:
    numberOfInstances: 2
    mode: transaction
    schema: pooler
    user: pooler
    resources:
      requests:
        cpu: 500m
        memory: 100Mi
      limits:
        cpu: "1"
        memory: 256Mi
  users:
    app_user:
    - superuser
    - createdb
    readonly_user: []
  databases:
    app_database: app_user
  postgresql:
    version: "16"
    parameters:
      shared_buffers: "2GB"
      max_connections: "200"
      work_mem: "64MB"
      maintenance_work_mem: "512MB"
      effective_cache_size: "6GB"
      random_page_cost: "1.1"
      effective_io_concurrency: "200"
      wal_buffers: "64MB"
      max_wal_size: "4GB"
      min_wal_size: "1GB"
      checkpoint_completion_target: "0.9"
      default_statistics_target: "100"
      log_statement: "ddl"
      log_min_duration_statement: "1000"
      idle_in_transaction_session_timeout: "600000"
      lock_timeout: "30000"
      statement_timeout: "60000"
  patroni:
    initdb:
      encoding: "UTF8"
      locale: "en_US.UTF-8"
      data-checksums: "true"
    pg_hba:
    - hostssl all all 0.0.0.0/0 md5
    - host    all all 0.0.0.0/0 md5
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    synchronous_mode: false
    synchronous_mode_strict: false
    maximum_lag_on_failover: 33554432
  resources:
    requests:
      cpu: "2"
      memory: 8Gi
    limits:
      cpu: "4"
      memory: 16Gi
  podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "9187"
  tolerations:
  - key: "database"
    operator: "Equal"
    value: "postgres"
    effect: "NoSchedule"
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: workload-type
          operator: In
          values:
          - database
  enableShmVolume: true
  spiloRunAsUser: 101
  spiloRunAsGroup: 103
  spiloFSGroup: 103

คีย์ CRD ฟิลด์อธิบาย

  • numberOfInstances— จำนวนพ็อดทั้งหมด ผู้ดำเนินการจะกำหนดให้รายการหนึ่งเป็นรายการหลักและส่วนที่เหลือเป็นแบบจำลองการสตรีมโดยอัตโนมัติ
  • EnableConnectionPooler— ปรับใช้ PgBouncer sidecar สำหรับบริการหลัก ซึ่งช่วยลดค่าใช้จ่ายในการเชื่อมต่อ
  • EnableReplicaConnectionPooler— ปรับใช้ PgBouncer แยกต่างหากสำหรับบริการจำลอง ซึ่งจำเป็นสำหรับเวิร์กโหลดที่มีการอ่านจำนวนมาก
  • postgresql.parameters— พารามิเตอร์การกำหนดค่า PostgreSQL โดยตรงที่ส่งผ่านไปยังpostgresql.conf
  • ผู้อุปถัมภ์— กำหนดค่าลักษณะการทำงานของ Patroni รวมถึง TTL, การรอแบบวนซ้ำ, การหมดเวลาการลองอีกครั้ง และโหมดการจำลองแบบซิงโครนัส
  • volume.storageClass— แมปกับ StorageClass เฉพาะแพลตฟอร์ม (EBS gp3 บน AWS, Premium SSD บน Azure, SSD PD บน GCP, Longhorn บน k3s)
  • EnableShmVolume— ติดตั้งtmpfsที่/dev/shmสำหรับหน่วยความจำที่ใช้ร่วมกัน PostgreSQL ซึ่งมีความสำคัญต่อประสิทธิภาพ

การรวมการเชื่อมต่อด้วย PgBouncer

โมเดลกระบวนการต่อการเชื่อมต่อของ

PostgreSQL ทำให้การจัดการการเชื่อมต่อไคลเอนต์จำนวนมากมีราคาแพง การเชื่อมต่อแต่ละครั้งใช้ RAM ประมาณ 10MB PgBouncer แก้ปัญหานี้ด้วยการมัลติเพล็กซ์การเชื่อมต่อไคลเอนต์นับพันผ่านกลุ่มการเชื่อมต่อ PostgreSQL จริงขนาดเล็ก

ตัวดำเนินการ Zalando รองรับการใช้งาน PgBouncer โดยกำเนิด เมื่อคุณตั้งค่าenableConnectionPooler: trueใน CRD ตัวดำเนินการจะสร้าง:

  • การปรับใช้ PgBouncer พร้อมจำนวนการจำลองที่กำหนดค่าได้
  • บริการเฉพาะ (<cluster-name>-pooler) สำหรับการเชื่อมต่อแบบพูล
  • การซิงโครไนซ์ข้อมูลรับรองอัตโนมัติกับ PostgreSQL

โหมดการกำหนดค่า PgBouncer

# PgBouncer connection pooler modes:
#
# transaction (recommended for most workloads)
#   - Connection returned to pool after each transaction
#   - Best balance of efficiency and compatibility
#   - Cannot use session-level features (prepared statements, temp tables)
#
# session
#   - Connection held for entire client session
#   - Full PostgreSQL compatibility
#   - Lower pooling efficiency
#
# statement
#   - Connection returned after each statement
#   - Most efficient but most restrictive
#   - Only works with autocommit queries

# Custom PgBouncer configuration via operator
spec:
  connectionPooler:
    numberOfInstances: 3
    mode: transaction
    schema: pooler
    user: pooler
    defaultPoolSize: 25
    maxDBConnections: 100
    resources:
      requests:
        cpu: 250m
        memory: 128Mi
      limits:
        cpu: "1"
        memory: 256Mi

สำหรับแอปพลิเคชันที่ต้องการคำสั่งที่เตรียมไว้หรือคุณสมบัติระดับเซสชัน ให้เชื่อมต่อโดยตรงกับบริการ PostgreSQL โดยข้าม PgBouncer หรือใช้โหมดพูลsessionโดยแลกกับประสิทธิภาพการเชื่อมต่อที่ต่ำกว่า

การจำลอง PostgreSQL หลายภูมิภาค

สำหรับแอปพลิเคชันระดับโลกที่ต้องการการอ่านข้อมูลที่มีความหน่วงต่ำจากที่ตั้งทางภูมิศาสตร์หลายแห่งหรือการกู้คืนความเสียหายข้ามภูมิภาค การจำลองแบบหลายภูมิภาคถือเป็นสิ่งสำคัญ ตัวดำเนินการ Zalando รองรับสิ่งนี้ผ่านคลัสเตอร์สแตนด์บายที่จำลองจากคลัสเตอร์หลักผ่านการจำลองแบบสตรีมมิ่งหรือไฟล์เก็บถาวร WAL-G

PostgreSQL การจำลองแบบสตรีมมิ่งหลายภูมิภาคUS-EAST-1 (AWS EKS)คลัสเตอร์หลักpg-prod-us (3 พ็อด)หลักแบบจำลองการจำลองแบบซิงค์ภายใน AZWAL-G → S3 (ต่อเนื่อง)PgBouncer PoolerEU-WEST-1 (Azure AKS)คลัสเตอร์สแตนด์บายpg-standby-eu (2 พ็อด)สแตนด์บายแบบจำลองการจำลองแบบเรียงซ้อนWAL-G → Azure หยดPgBouncer (อ่านอย่างเดียว)AP-ตะวันออกเฉียงใต้ (GCP GKE)คลัสเตอร์สแตนด์บายpg-standby-ap (2 พ็อด)สแตนด์บายแบบจำลองการจำลองแบบเรียงซ้อนWAL-G → บั๊กเก็ต GCSPgBouncer (อ่านอย่างเดียว)อะซิงค์ASYNC (จัดส่งแบบ WAL)โทโพโลยีการจำลองPrimary (US-EAST) → การสตรีม Async ไปยัง EU-WEST & AP-SOUTHEAST คลัสเตอร์สแตนด์บาย | RPO: ~วินาที | RTO: <5 นาที พร้อมการโปรโมตด้วยตนเองการจำลองแบบซิงค์การจำลองแบบอะซิงโครนัสหลักผู้นำสแตนด์บายอ่านแบบจำลองการกำหนดค่าการจำลองแบบสตรีมมิ่ง

การจำลองแบบสตรีมมิ่ง

PostgreSQL เป็นรากฐานของ HA ในตัวดำเนินการ Zalando ทำงานโดยการจัดส่งบันทึก Write-Ahead Log (WAL) จากรายการหลักไปยังแบบจำลองในเวลาใกล้เคียงเรียลไทม์ ผู้ปฏิบัติงานจะกำหนดค่านี้โดยอัตโนมัติ แต่การทำความเข้าใจรายละเอียดจะช่วยในการปรับแต่งและแก้ไขปัญหาได้

  • การจำลองแบบซิงโครนัส— ตัวหลักรอแบบจำลองอย่างน้อยหนึ่งตัวเพื่อยืนยันการรับ WAL ก่อนทำธุรกรรม สิ่งนี้รับประกันการสูญเสียข้อมูลเป็นศูนย์ (RPO=0) แต่เพิ่มเวลาแฝง เปิดใช้งานด้วยpatroni.synchronous_mode: true
  • การจำลองแบบอะซิงโครนัส— การดำเนินการหลักทันทีและส่ง WAL แบบอะซิงโครนัส เวลาแฝงลดลงเล็กน้อย แต่ข้อมูลอาจสูญหายระหว่างการเฟลโอเวอร์ นี่คือค่าเริ่มต้น
  • Cascading replication— เรพลิกาสามารถจำลองจากเรพลิกาอื่นๆ แทนที่จะเป็นตัวหลัก ช่วยลดภาระบนตัวหลักในคลัสเตอร์ขนาดใหญ่
# Enable synchronous replication for zero data loss
spec:
  patroni:
    synchronous_mode: true
    synchronous_mode_strict: false  # Allow async if no sync replica available
    synchronous_node_count: 1       # Number of sync replicas required
  postgresql:
    parameters:
      synchronous_commit: "on"      # Matches Patroni synchronous_mode
      max_wal_senders: "10"         # Maximum WAL sender processes
      wal_keep_size: "1GB"          # WAL retention for replica catch-up
      hot_standby: "on"             # Allow queries on replicas
      hot_standby_feedback: "on"    # Reduce query conflicts on replicas
การสำรองและกู้คืน

ด้วย WAL-G

การกำหนดค่าการสำรองข้อมูล

WAL-G

การกำหนดค่าการสำรองข้อมูลที่เหมาะสมเป็นสิ่งสำคัญสำหรับการกู้คืนระบบ ตัวดำเนินการ Zalando ผสานรวม WAL-G เพื่อการสำรองข้อมูลอย่างต่อเนื่องไปยังพื้นที่จัดเก็บอ็อบเจ็กต์ ต่อไปนี้คือการกำหนดค่าที่สมบูรณ์สำหรับพื้นที่จัดเก็บข้อมูลที่เข้ากันได้กับ S3:

# ConfigMap for WAL-G backup configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: databases
data:
  # S3 backup configuration
  AWS_ENDPOINT: "https://s3.us-east-1.amazonaws.com"
  AWS_S3_FORCE_PATH_STYLE: "false"
  AWS_REGION: "us-east-1"
  WALG_S3_PREFIX: "s3://my-pg-backups/$(SCOPE)"
  WALG_DISABLE_S3_SSE: "false"
  WALG_S3_SSE: "aws:kms"
  WALG_S3_SSE_KMS_ID: "arn:aws:kms:us-east-1:123456789:key/mrk-abcdef"

  # Backup scheduling and retention
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  BACKUP_SCHEDULE: "0 1 * * *"       # Daily at 1 AM UTC
  BACKUP_NUM_TO_RETAIN: "14"          # Keep 14 daily backups

  # WAL archiving
  WALG_COMPRESSION_METHOD: "zstd"     # Better compression than lz4
  WALG_DELTA_MAX_STEPS: "6"           # Delta backups between full backups
  WALG_UPLOAD_CONCURRENCY: "4"        # Parallel upload streams
  WALG_DOWNLOAD_CONCURRENCY: "4"      # Parallel download for restore
  WALG_UPLOAD_DISK_CONCURRENCY: "4"   # Disk read concurrency

  # Clone configuration
  CLONE_AWS_ENDPOINT: "https://s3.us-east-1.amazonaws.com"
  CLONE_AWS_REGION: "us-east-1"
  CLONE_WALG_S3_PREFIX: "s3://my-pg-backups/$(CLONE_SCOPE)"
  CLONE_METHOD: "CLONE_WITH_WALG"
  CLONE_USE_WALG_RESTORE: "true"

การกู้คืนช่วงเวลา (PITR)

PITR ช่วยให้คุณสามารถกู้คืนฐานข้อมูลของคุณในช่วงเวลาใดเวลาหนึ่ง ซึ่งมีความสำคัญอย่างยิ่งต่อการกู้คืนจากการลบข้อมูลโดยไม่ตั้งใจหรือความเสียหาย ตัวดำเนินการ Zalando รองรับ PITR ผ่านกลไกการโคลน:

# Clone a cluster with PITR
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-restored-cluster
  namespace: databases
spec:
  teamId: "platform"
  volume:
    size: 100Gi
    storageClass: ebs-gp3-postgres
  numberOfInstances: 3
  postgresql:
    version: "16"
  clone:
    cluster: "pg-production-cluster"
    timestamp: "2026-04-11T14:30:00+00:00"  # Restore to this exact moment
    s3_wal_path: "s3://my-pg-backups/wal/16/pg-production-cluster"
    s3_endpoint: "https://s3.us-east-1.amazonaws.com"
    s3_access_key_id: ""      # Use IAM role instead
    s3_secret_access_key: ""  # Use IAM role instead

เมื่อใช้ CRD นี้ ผู้ปฏิบัติงานจะดำเนินการตามขั้นตอนต่อไปนี้:

  1. ค้นหาการสำรองข้อมูลพื้นฐานล่าสุดก่อนการประทับเวลาเป้าหมาย
  2. คืนค่าการสำรองข้อมูลฐานไปยังพ็อดหลักของ StatefulSet ใหม่
  3. เล่นซ้ำส่วน WAL จนถึงเวลาประทับที่ระบุ
  4. เปิดฐานข้อมูลสำหรับการดำเนินการอ่าน-เขียน
  5. ตั้งค่าการจำลองแบบสตรีมมิ่งไปยังพ็อดแบบจำลอง
คลัสเตอร์สแตนด์บาย

สำหรับการกู้คืนความเสียหาย

คลัสเตอร์สแตนด์บายจำลองอย่างต่อเนื่องจากคลัสเตอร์หลัก มอบสแตนด์บายแบบอุ่นที่สามารถส่งเสริมได้ในระหว่างเกิดภัยพิบัติ สิ่งนี้แตกต่างจากการจำลองภายในคลัสเตอร์ คลัสเตอร์สแตนด์บายเป็นทรัพยากร Kubernetes อิสระโดยสมบูรณ์ซึ่งสามารถทำงานในเนมสเปซ คลัสเตอร์ หรือแม้แต่ภูมิภาคอื่นได้

# Standby cluster in a different region
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-standby-eu
  namespace: databases
spec:
  teamId: "platform"
  volume:
    size: 100Gi
    storageClass: managed-premium-postgres
  numberOfInstances: 2
  postgresql:
    version: "16"
  standby:
    standby_host: "pg-production-cluster.databases.svc.cluster.local"
    standby_port: "5432"
    # Alternative: replicate from S3 WAL archive
    # s3_wal_path: "s3://my-pg-backups/wal/16/pg-production-cluster"
  enableConnectionPooler: true
  enableReplicaConnectionPooler: true

หากต้องการเลื่อนระดับคลัสเตอร์สแตนด์บายเป็นคลัสเตอร์หลักอิสระ (ระหว่างการกู้คืนระบบ) เพียงลบส่วนstandbyออกจาก CRD แล้วใช้:

# Edit the standby cluster CRD to remove standby section
kubectl patch postgresql pg-standby-eu -n databases --type json \
  -p '[{"op": "remove", "path": "/spec/standby"}]'

# The operator will promote the standby to primary
# Update your application DNS/service mesh to point to the new primary
การตรวจสอบ

ด้วย Prometheus และ Grafana

การตรวจสอบที่ครอบคลุมไม่สามารถต่อรองได้สำหรับการปรับใช้ PostgreSQL ที่ใช้งานจริง ตัวดำเนินการ Zalando รองรับการส่งออกตัววัด Prometheus ผ่านตัวช่วยpostgres_exporterต่อไปนี้เป็นวิธีการตั้งค่าสแต็กการตรวจสอบที่สมบูรณ์:

ServiceMonitor สำหรับ Prometheus

# ServiceMonitor for PostgreSQL metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: postgres-monitor
  namespace: databases
  labels:
    team: platform
    release: prometheus
spec:
  selector:
    matchLabels:
      team: platform
  namespaceSelector:
    matchNames:
    - databases
  endpoints:
  - port: exporter
    interval: 15s
    scrapeTimeout: 10s
    path: /metrics
    relabelings:
    - sourceLabels: [__meta_kubernetes_pod_label_spilo_role]
      targetLabel: role
    - sourceLabels: [__meta_kubernetes_pod_label_cluster_name]
      targetLabel: cluster
---
# PodMonitor alternative (scrapes pods directly)
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: postgres-pod-monitor
  namespace: databases
spec:
  selector:
    matchLabels:
      application: spilo
  podMetricsEndpoints:
  - port: exporter
    interval: 15s
    path: /metrics

ตัวชี้วัดหลักในการตรวจสอบ

นี่คือตัวชี้วัด PostgreSQL ที่สำคัญที่สุดในการติดตามในแดชบอร์ด Grafana ของคุณ:

  • pg_stat_replication_lag— ความล่าช้าในการจำลองเป็นไบต์และวินาที แจ้งเตือนหากความล่าช้าเกินเกณฑ์ RPO ของคุณ
  • pg_stat_activity_count— การเชื่อมต่อที่ใช้งานอยู่ตามสถานะ แจ้งเตือนเมื่อพูลการเชื่อมต่อหมดลง
  • pg_stat_database_tup_fetched/returned/insert/updated/deleted— ตัววัดปริมาณงานการสืบค้น
  • pg_stat_bgwriter_buffers_checkpoint/clean/backend— ประสิทธิภาพการจัดการบัฟเฟอร์
  • pg_database_size_bytes— การเติบโตของขนาดฐานข้อมูลเมื่อเวลาผ่านไปสำหรับการวางแผนความจุ
  • pg_locks_count— ล็อคการโต้แย้ง แจ้งเตือนเมื่อล็อคการรอมากเกินไป
  • pg_stat_statements_calls/mean_time— ค้นหาสถิติประสิทธิภาพสำหรับการเพิ่มประสิทธิภาพ
  • Patroni_postgres_running— สถานะความสมบูรณ์ของ Patroni (1 = กำลังดำเนินการ, 0 = ลง)
  • Patroni_master— พ็อดใดที่เป็นพ็อดหลักในปัจจุบัน (1 = ต้นแบบ, 0 = เรพลิกา)
  • pg_up— โพรบความพร้อมใช้งาน PostgreSQL พื้นฐาน

กฎการแจ้งเตือน

# PrometheusRule for PostgreSQL alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: postgres-alerts
  namespace: databases
spec:
  groups:
  - name: postgresql.rules
    rules:
    - alert: PostgreSQLDown
      expr: pg_up == 0
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "PostgreSQL instance {{ $labels.instance }} is down"
    - alert: PostgreSQLReplicationLag
      expr: pg_stat_replication_pg_wal_lsn_diff > 100000000
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Replication lag is {{ $value }} bytes on {{ $labels.instance }}"
    - alert: PostgreSQLHighConnections
      expr: sum(pg_stat_activity_count) by (instance) > 180
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "{{ $value }} active connections on {{ $labels.instance }}"
    - alert: PostgreSQLDeadlocks
      expr: rate(pg_stat_database_deadlocks[5m]) > 0
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "Deadlocks detected on {{ $labels.datname }}"
    - alert: PatroniFailover
      expr: changes(patroni_master[5m]) > 0
      labels:
        severity: critical
      annotations:
        summary: "Patroni failover occurred in cluster {{ $labels.cluster }}"
คู่มือการปรับแต่ง

การปรับแต่งอย่างเหมาะสมถือเป็นสิ่งสำคัญในการดึงประสิทธิภาพสูงสุดจาก PostgreSQL บน Kubernetes ควรปรับพารามิเตอร์ต่อไปนี้ตามขีดจำกัดทรัพยากรพ็อดและลักษณะภาระงาน

การกำหนดค่าหน่วยความจำ

# For a pod with 16GB memory limit:
postgresql:
  parameters:
    # shared_buffers: 25% of total memory
    shared_buffers: "4GB"

    # effective_cache_size: 75% of total memory
    # (tells planner how much OS cache to expect)
    effective_cache_size: "12GB"

    # work_mem: shared_buffers / (max_connections * 2)
    # Conservative to prevent OOM
    work_mem: "10MB"

    # maintenance_work_mem: 5-10% of total memory
    # Used for VACUUM, CREATE INDEX, ALTER TABLE
    maintenance_work_mem: "1GB"

    # temp_buffers: memory for temp tables per session
    temp_buffers: "32MB"

    # huge_pages: try to use huge pages (requires OS config)
    huge_pages: "try"

WAL และการกำหนดค่าจุดตรวจ

postgresql:
  parameters:
    # WAL settings
    wal_buffers: "64MB"           # 1/32 of shared_buffers, max 64MB
    wal_compression: "zstd"        # Compress WAL (PG 15+)
    max_wal_size: "8GB"            # Before forced checkpoint
    min_wal_size: "2GB"            # WAL disk reservation
    wal_level: "replica"           # Required for replication

    # Checkpoint settings
    checkpoint_completion_target: "0.9"  # Spread I/O over 90% of interval
    checkpoint_timeout: "15min"          # Max time between checkpoints

เครื่องมือวางแผนแบบสอบถามและ I/O

postgresql:
  parameters:
    # Cost parameters for SSD storage
    random_page_cost: "1.1"          # SSD: close to seq_page_cost
    seq_page_cost: "1.0"             # Sequential I/O baseline
    effective_io_concurrency: "200"   # Concurrent I/O for SSD

    # Planner behavior
    default_statistics_target: "200"  # More accurate statistics
    from_collapse_limit: 12           # JOIN planning threshold
    join_collapse_limit: 12           # JOIN planning threshold

    # Parallel queries
    max_parallel_workers_per_gather: "4"
    max_parallel_workers: "8"
    max_parallel_maintenance_workers: "4"
    parallel_tuple_cost: "0.01"
    parallel_setup_cost: "1000"
การเชื่อมต่อ

และการบันทึก

postgresql:
  parameters:
    # Connection limits
    max_connections: "200"                   # Keep low, use PgBouncer
    superuser_reserved_connections: "5"       # Reserve for admin access

    # Logging for troubleshooting
    log_statement: "ddl"                     # Log DDL statements
    log_min_duration_statement: "500"         # Log queries > 500ms
    log_checkpoints: "on"                    # Log checkpoint activity
    log_connections: "off"                   # Too noisy in production
    log_disconnections: "off"                # Too noisy in production
    log_lock_waits: "on"                     # Log lock waits
    log_temp_files: "0"                      # Log all temp file usage
    log_autovacuum_min_duration: "1000"       # Log slow autovacuum

    # Statement timeouts
    statement_timeout: "60000"               # 60 second query timeout
    lock_timeout: "30000"                    # 30 second lock timeout
    idle_in_transaction_session_timeout: "600000"  # 10 min idle txn timeout

การอัปเดตแบบ Rolling และการอัพเกรดเวอร์ชัน

เวอร์ชันรองอัปเกรด

การอัปเกรดเวอร์ชันรองของ

(เช่น 16.2 ถึง 16.3) จะได้รับการจัดการโดยอัตโนมัติโดยผู้ดำเนินการเมื่อคุณอัปเดตแท็กรูปภาพ Spilo ผู้ปฏิบัติงานทำการรีสตาร์ทแบบกลิ้ง:

# Update the operator configuration to use a new Spilo image
helm upgrade postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configGeneral.docker_image=ghcr.io/zalando/spilo-16:3.1-p1 \
  --reuse-values

# The operator will perform rolling updates:
# 1. Restart replicas one at a time
# 2. Failover the primary to a freshly updated replica
# 3. Restart the old primary (now a replica)

เวอร์ชันหลักอัปเกรด

การอัพเกรด

เวอร์ชันหลัก (เช่น PostgreSQL 15 ถึง 16) จำเป็นต้องมีการวางแผนอย่างรอบคอบมากขึ้น ตัวดำเนินการ Zalando รองรับการอัพเกรดหลักแบบแทนที่โดยใช้pg_upgrade:

# Step 1: Update the CRD to the new major version
spec:
  postgresql:
    version: "16"  # Changed from "15"

# Step 2: The operator detects the version change and:
# a) Scales down the StatefulSet to 1 replica
# b) Runs pg_upgrade on the primary pod
# c) Scales back up to the desired numberOfInstances
# d) Replicas are rebuilt from the upgraded primary

# Step 3: Verify the upgrade
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "psql -c 'SELECT version()'"

# Step 4: Run ANALYZE to update statistics after upgrade
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "psql -c 'ANALYZE VERBOSE'"

ข้อควรพิจารณาที่สำคัญสำหรับการอัพเกรดที่สำคัญ:

  • ทำการสำรองข้อมูลใหม่ทุกครั้งก่อนอัปเกรด
  • ทดสอบการอัพเกรดบนคลัสเตอร์ที่โคลนก่อน
  • การอัปเกรดหลักต้องใช้เวลาหยุดทำงาน (โดยทั่วไปประมาณ 5-30 นาที ขึ้นอยู่กับขนาดฐานข้อมูล)
  • ตรวจสอบบันทึกประจำรุ่น PostgreSQL สำหรับการทำลายการเปลี่ยนแปลง
  • ตรวจสอบความล่าช้าในการจำลองแบบอย่างใกล้ชิดหลังจากสร้างแบบจำลอง
  • ใหม่
  • รันANALYZEบนฐานข้อมูลทั้งหมดเพื่อสร้างสถิติตัววางแผนคิวรีใหม่

รูปแบบการทำงานขั้นสูง

การสำรองข้อมูลเชิงตรรกะ

นอกเหนือจากการสำรองข้อมูล WAL-G ทางกายภาพแล้ว ผู้ปฏิบัติงานยังสนับสนุนการสำรองข้อมูลแบบลอจิคัลโดยใช้pg_dumpการสำรองข้อมูลแบบลอจิคัลมีประโยชน์สำหรับการย้ายข้ามเวอร์ชันและการกู้คืนตารางแบบเลือก:

# Enable logical backups in the operator configuration
helm upgrade postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configLogicalBackup.logical_backup_schedule="0 3 * * *" \
  --set configLogicalBackup.logical_backup_s3_bucket="my-pg-logical-backups" \
  --set configLogicalBackup.logical_backup_s3_region="us-east-1" \
  --set configLogicalBackup.logical_backup_s3_sse="AES256" \
  --reuse-values

# The operator creates a CronJob for each cluster that:
# 1. Connects to the primary PostgreSQL instance
# 2. Runs pg_dumpall (or pg_dump per database)
# 3. Compresses and uploads to S3

ตัวแปรสภาพแวดล้อมพ็อดแบบกำหนดเอง

คุณสามารถฉีดตัวแปรสภาพแวดล้อมลงในพ็อด Spilo ได้โดยใช้ ConfigMap สิ่งนี้มีประโยชน์สำหรับการกำหนดค่า WAL-G, สคริปต์ที่กำหนดเอง หรือการปรับพารามิเตอร์ระดับระบบปฏิบัติการ:

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: databases
data:
  # Custom Spilo configurations
  SPILO_CONFIGURATION: |
    bootstrap:
      dcs:
        ttl: 30
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 33554432
        postgresql:
          use_pg_rewind: true
          use_slots: true
          parameters:
            archive_mode: "on"
            archive_timeout: 1800s
  # Enable pg_stat_statements
  POSTGRESQL_SHARED_PRELOAD_LIBRARIES: "bg_mon,pg_stat_statements,pgextwlist,pg_auth_mon,set_user,timescaledb,pg_cron,pg_stat_kcache"
  # Cron jobs inside PostgreSQL
  ENABLE_PG_CRON: "true"
นโยบายเครือข่าย

เพื่อความปลอดภัย

ในการใช้งานจริง ให้จำกัดการเข้าถึงเครือข่ายไปยังพ็อด PostgreSQL โดยใช้ Kubernetes NetworkPolicies:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: postgres-network-policy
  namespace: databases
spec:
  podSelector:
    matchLabels:
      application: spilo
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: app-namespace
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 5432
    - protocol: TCP
      port: 8008   # Patroni REST API
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9187   # Prometheus exporter
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
    ports:
    - protocol: TCP
      port: 443    # S3/GCS/Azure for backups

การแก้ไขปัญหาทั่วไป

แม้จะมีระบบอัตโนมัติ แต่ก็ยังมีปัญหาเกิดขึ้น ต่อไปนี้เป็นปัญหาที่พบบ่อยที่สุดและวิธีแก้ปัญหาเมื่อใช้งาน PostgreSQL ด้วยตัวดำเนินการ Zalando:

1. พ็อดติดอยู่ในสถานะรอดำเนินการ

# Check events for the pod
kubectl describe pod pg-production-cluster-0 -n databases

# Common causes:
# - No nodes with matching tolerations/affinity
# - Insufficient CPU or memory on nodes
# - PVC cannot be provisioned (check StorageClass)

# Fix: Check node resources and storage availability
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEM:.status.allocatable.memory
kubectl get pvc -n databases

2. ความล่าช้าในการจำลองที่เพิ่มขึ้น

# Check replication status on the primary
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "psql -c 'SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag FROM pg_stat_replication'"

# Common causes:
# - Replica CPU/IO saturation
# - Network bandwidth limits
# - Long-running queries on replica blocking WAL replay
# - Insufficient wal_keep_size

# Fix: Check replica resources and cancel blocking queries
kubectl exec -it pg-production-cluster-1 -n databases -- \
  su postgres -c "psql -c 'SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE state = \"active\" AND query_start < now() - interval \"5 minutes\"'"

3. เฟลโอเวอร์ไม่ทริกเกอร์

# Check Patroni cluster status
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "patronictl list"

# Check Patroni logs
kubectl logs pg-production-cluster-0 -n databases -c postgres | grep -i patroni

# Manual failover (if auto-failover is stuck)
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "patronictl failover --candidate pg-production-cluster-1 --force"

4. การสำรองข้อมูลล้มเหลว

# Check WAL-G backup status
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "envdir /run/etc/wal-e.d/env wal-g backup-list"

# Check backup CronJob logs
kubectl logs -l application=spilo,cluster-name=pg-production-cluster -n databases | grep -i wal-g

# Verify S3/GCS credentials
kubectl exec -it pg-production-cluster-0 -n databases -- \
  su postgres -c "envdir /run/etc/wal-e.d/env aws s3 ls s3://my-pg-backups/"

แนวทางปฏิบัติที่ดีที่สุดด้านความปลอดภัย

การรักษาความปลอดภัย PostgreSQL บน Kubernetes ต้องใช้แนวทางการป้องกันเชิงลึก:

  • การเข้ารหัส TLS— เปิดใช้งาน SSL สำหรับการเชื่อมต่อไคลเอ็นต์ทั้งหมด ผู้ดำเนินการสามารถจัดเตรียมใบรับรองโดยอัตโนมัติโดยใช้ cert-manager
  • การจัดการข้อมูลลับ— ใช้ข้อมูลลับ Kubernetes (หรือผู้จัดการข้อมูลลับภายนอก เช่น ห้องนิรภัย) สำหรับข้อมูลรับรองฐานข้อมูล อย่าเก็บรหัสผ่านไว้ใน ConfigMaps
  • RBAC— จำกัดผู้ดำเนินการ สิทธิ์ ServiceAccount ใช้สิทธิ์การเข้าถึงน้อยที่สุดสำหรับผู้ใช้ฐานข้อมูลแอปพลิเคชัน
  • NetworkPolicies— จำกัดการสื่อสารแบบ pod-to-pod ดังที่แสดงในส่วนก่อนหน้า
  • pg_hba.conf— กำหนดค่าการตรวจสอบสิทธิ์ตามโฮสต์เพื่อจำกัด IP และผู้ใช้สามารถเชื่อมต่อได้
  • การบันทึกการตรวจสอบ— เปิดใช้งานส่วนขยายpgauditสำหรับการบันทึกการตรวจสอบ SQL ในสภาพแวดล้อมที่มีการควบคุม
  • ที่เก็บข้อมูลที่เข้ารหัส— ใช้ StorageClasses ที่เข้ารหัส (การเข้ารหัส EBS, การเข้ารหัสดิสก์ Azure ฯลฯ )
  • Pod มาตรฐานความปลอดภัย— เรียกใช้ Spilo pods แบบไม่ใช่รูทโดยมีบริบทความปลอดภัยแบบจำกัด
# Security-hardened CRD settings
spec:
  spiloRunAsUser: 101
  spiloRunAsGroup: 103
  spiloFSGroup: 103
  enableShmVolume: true
  patroni:
    pg_hba:
    - hostssl all all 0.0.0.0/0 md5
    - host    replication standby all md5
    - hostssl replication standby all md5
  postgresql:
    parameters:
      ssl: "on"
      ssl_min_protocol_version: "TLSv1.3"
      password_encryption: "scram-sha-256"
  additionalVolumes:
  - name: postgres-tls
    mountPath: /tls
    secret:
      secretName: pg-tls-cert
      defaultMode: 0640

การวางแผนความจุและการกำหนดขนาด

ขนาดที่เหมาะสมช่วยให้มั่นใจถึงประสิทธิภาพที่มั่นคงและความคุ้มค่า ใช้แนวทางเหล่านี้เป็นจุดเริ่มต้นและปรับเปลี่ยนตามข้อมูลการตรวจสอบภาระงานของคุณ:

ปริมาณงานCPUหน่วยความจำอุปกรณ์จัดเก็บข้อมูลอินสแตนซ์
การพัฒนา500ม.1Gi10Gi1
ผลิตขนาดเล็ก2 คอร์8Gi50Gi SSD3
การผลิตขนาดกลาง4 คอร์16Gi200Gi SSD3
การผลิตขนาดใหญ่8 คอร์32Gi500Gi SSD5
ระดับองค์กร / การวิเคราะห์16+ แกน64Gi+1Ti+ SSD5+

ตัวอย่างการใช้งานแบบ end-to-end เสร็จสมบูรณ์

ให้เรารวมทุกอย่างเข้าด้วยกันพร้อมกับการปรับใช้งานที่สมบูรณ์ตั้งแต่เริ่มต้นบนคลัสเตอร์ Kubernetes ใหม่:

# Step 1: Create namespace and configure storage
kubectl create namespace databases
kubectl create namespace postgres-operator

# Step 2: Install the Zalando Postgres Operator
helm repo add postgres-operator-charts \
  https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm repo update

helm install postgres-operator postgres-operator-charts/postgres-operator \
  --namespace postgres-operator \
  --set configKubernetes.enable_pod_antiaffinity=true \
  --set configKubernetes.pod_environment_configmap=databases/postgres-pod-config

# Step 3: Create backup configuration
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-pod-config
  namespace: databases
data:
  USE_WALG_BACKUP: "true"
  USE_WALG_RESTORE: "true"
  WALG_S3_PREFIX: "s3://my-pg-backups/\$(SCOPE)"
  BACKUP_SCHEDULE: "0 1 * * *"
  BACKUP_NUM_TO_RETAIN: "14"
EOF

# Step 4: Deploy the PostgreSQL cluster
kubectl apply -f - <<EOF
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: pg-app-cluster
  namespace: databases
  labels:
    team: platform
spec:
  teamId: "platform"
  volume:
    size: 50Gi
  numberOfInstances: 3
  enableConnectionPooler: true
  enableReplicaConnectionPooler: true
  users:
    app_user:
    - superuser
    - createdb
  databases:
    app_db: app_user
  postgresql:
    version: "16"
    parameters:
      shared_buffers: "2GB"
      work_mem: "64MB"
      effective_cache_size: "6GB"
  resources:
    requests:
      cpu: "2"
      memory: 8Gi
    limits:
      cpu: "4"
      memory: 16Gi
EOF

# Step 5: Wait for cluster readiness
kubectl wait --for=condition=Running postgresql/pg-app-cluster \
  -n databases --timeout=300s

# Step 6: Verify cluster status
kubectl get postgresql -n databases
kubectl get pods -n databases -l cluster-name=pg-app-cluster
kubectl get svc -n databases -l cluster-name=pg-app-cluster

# Step 7: Get connection credentials
export PGPASSWORD=$(kubectl get secret app-user.pg-app-cluster.credentials.postgresql.acid.zalan.do \
  -n databases -o jsonpath='{.data.password}' | base64 -d)

# Step 8: Connect and verify
kubectl run pg-client --rm -it --image=postgres:16 -n databases -- \
  psql -h pg-app-cluster-pooler -U app_user -d app_db -c "SELECT version();"

สรุป

เจ้าหน้าที่ปฏิบัติการ Zalando Postgres แปลง PostgreSQL บน Kubernetes จากความท้าทายในการปฏิบัติงานที่ซับซ้อนให้กลายเป็นการปรับใช้งานอัตโนมัติที่สามารถจัดการได้ ด้วยการใช้ประโยชน์จาก Patroni สำหรับเฟลโอเวอร์ตามฉันทามติ, Spilo สำหรับอิมเมจคอนเทนเนอร์ที่รวมแบตเตอรี่, WAL-G สำหรับการสำรองข้อมูลและการกู้คืนอย่างต่อเนื่อง และ PgBouncer สำหรับการรวมการเชื่อมต่อที่มีประสิทธิภาพ คุณจะได้รับแพลตฟอร์มฐานข้อมูลระดับการผลิตที่ทำงานอย่างสม่ำเสมอในคลัสเตอร์ AWS EKS, Azure AKS, Google GKE และ Bare-Metal k3s

ประเด็นสำคัญจากคู่มือนี้คือ:

  • ทำทุกอย่างอัตโนมัติ— ให้ผู้ปฏิบัติงานจัดการการจัดการ StatefulSet การเฟลโอเวอร์ และกำหนดเวลาการสำรองข้อมูล การแทรกแซงด้วยตนเองควรเป็นข้อยกเว้น
  • ตรวจสอบอย่างจริงจัง — ปรับใช้ Prometheus และ Grafana ตั้งแต่วันแรก ความล่าช้าในการจำลอง จำนวนการเชื่อมต่อ และการแย่งชิงการล็อกเป็นสัญญาณเตือนล่วงหน้าของคุณ
  • วางแผนสำหรับภัยพิบัติ— กำหนดค่าการสำรองข้อมูล WAL-G, ทดสอบ PITR เป็นประจำ และดูแลรักษาคลัสเตอร์สแตนด์บายสำหรับปริมาณงานที่สำคัญ
  • ปรับแต่งสำหรับปริมาณงานของคุณ— พารามิเตอร์ PostgreSQL เริ่มต้นเป็นแบบอนุรักษ์นิยม ปรับการตั้งค่า shared_buffers, work_mem และจุดตรวจสอบตามการจัดสรรทรัพยากรและรูปแบบการสืบค้นของคุณ
  • ปลอดภัยตามค่าเริ่มต้น— เปิดใช้งาน TLS ใช้การตรวจสอบสิทธิ์ SCRAM-SHA-256 จำกัดการเข้าถึงเครือข่าย และเข้ารหัสที่เก็บข้อมูลที่เหลือ
  • ทดสอบการอัพเกรด— โคลนคลัสเตอร์ของคุณและทดสอบการอัพเกรดเวอร์ชันหลักเสมอก่อนที่จะนำไปใช้กับการใช้งานจริง

ด้วยรากฐานที่ครอบคลุมนี้ คุณมีความพร้อมในการปรับใช้และดำเนินการคลัสเตอร์ PostgreSQL ที่พร้อมใช้งานสูงบนแพลตฟอร์ม Kubernetes ใดๆ โดยให้บริการแอปพลิเคชันที่ต้องการความน่าเชื่อถือ ประสิทธิภาพ และความสมบูรณ์ของข้อมูลในวงกว้าง