Workstation Logo
Продукты
AI LabsАгенты OpenAIАгенты ClaudeGrok BotWorkstation CRM (WSL CRM)МаркетингВсе продукты
Решения ИИ
Рабочие станции ИИAI SME PackagesЧастный ИИКластеры GPUПограничный ИИЛаборатория корпоративного ИИИИ по отраслям
Услуги
Platform ModernisationDigital EngineeringData Foundations & AIAutonomous OperationsИИ-консалтингАвтоматизация DevOpsКибербезопасностьРазработка ПОСоздание агентовНастройка MLOps
О нас
ПартнёрыИстории клиентов
Статьи
Документация
WSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7
Блог
Связаться с намиLogin
Workstation

AI-рабочие станции, мультиагентное AI-ПО, GPU-инфраструктура и решения на базе интеллектуальных агентов для современного бизнеса.

Связаться с нами

AI-решения

Рабочие станции ИИAI SME PackagesЧастный ИИКластеры GPUПограничный ИИЛаборатория корпоративного ИИИИ по отраслям

Продукты

Все продуктыWSL CRM и ERPМаркетингАгенты OpenAIWSL ProxyRing PromoterWSL VaultJobshoutSysOps 24/7

Компания

О насПочему WorkstationПартнёрыИстории клиентовЦеныКонтакты

Ресурсы

СтатьиДокументацияБлогПоискКарта сайта
Офис в Великобритании
77-79 Marlowes, Hemel Hempstead HP1 1LFКак добраться: съезд 20 с трассы M25, Внешний ЛондонРег. номер компании: 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. Все права защищены.

КонфиденциальностьФайлы cookieУсловия использованияКарта сайта

Loading blog...

Home / Blog
DatabaseKubernetesDevOpsBackend

Высокая доступность PostgreSQL с оператором Zalando Postgres: Руководство по развертыванию Kubernetes в нескольких облаках

Разверните PostgreSQL HA производственного уровня с помощью Zalando Оператора на любой платформе Kubernetes.

Balinder Walia12 апреля 2026 г.26 min read
Введение

: почему важна высокая доступность PostgreSQL на Kubernetes

Для работы PostgreSQL в производственных условиях требуется высокая доступность (HA). Время простоя, измеряемое минутами, может стоить предприятиям миллионы долларов в виде упущенной выгоды, подорвать доверие клиентов и нарушить соглашения об уровне обслуживания. Kubernetes стал де-факто платформой для организации контейнерных рабочих нагрузок, но запуск сервисов с отслеживанием состояния, таких как PostgreSQL, на Kubernetes сопряжен с уникальными проблемами: управление постоянным хранилищем, выбор лидера, автоматическое переключение при сбое, оркестрация резервного копирования и объединение пулов соединений.

Zalando Postgres Оператор— это проверенное в боевых условиях решение с открытым исходным кодом, созданное Zalando — крупнейшим в Европе интернет-магазином модной одежды — для управления сотнями кластеров PostgreSQL в производстве. Он используетPatroniдля выборов лидера на основе консенсуса,Spiloв качестве образа контейнера PostgreSQL,WAL-Gдля непрерывного архивирования и восстановления на определенный момент времени иPgBouncerдля пула соединений. Вместе эти компоненты обеспечивают полностью автоматизированное самовосстанавливающееся развертывание PostgreSQL, которое работает в любом дистрибутиве Kubernetes — от управляемых облачных сервисов, таких как AWS EKS, Azure AKS и Google GKE, до «голых» кластеров, на которых работает k3s с Rancher.

В этом подробном руководстве мы рассмотрим архитектуру оператора Zalando Postgres, рассмотрим установку и настройку на нескольких платформах Kubernetes, углубимся в репликацию, резервное копирование, аварийное восстановление, мониторинг и настройку производства. К концу вы получите знания по развертыванию и эксплуатации кластеров высокой доступности PostgreSQL промышленного уровня в любой инфраструктуре Kubernetes.

Архитектура оператора Zalando Postgres

Перед развертыванием необходимо понять архитектуру. Оператор Zalando Postgres следует шаблону оператора Kubernetes: он отслеживает пользовательские определения ресурсов (CRD) типаpostgresqlи согласовывает желаемое состояние с фактическими ресурсами Kubernetes. Вот как компоненты сочетаются друг с другом:

Архитектура оператора Zalando PostgresPostgreSQL CRDТип: postgresqlОператор PostgresЧасы и усилители; СогласовываетStatefulSetуправляет жизненным циклом модуляОсновной модульСпило (PostgreSQL)Агент PatroniРеплика модуля 1Спило (PostgreSQL)Агент PatroniРепликаPod 2Спило (PostgreSQL)Агент PatroniPatroni DCS (Kubernetes API)Выборы лидера и усилитель; Состояние кластераPgBouncerПул соединенийWAL-GРезервное копирование на S3/GCS/AzureПервичныйРепликаКонсенсус/DCSРезервное копированиеПул соединений

Spilo: образ контейнера PostgreSQL

Spilo— это образ Docker от Zalando, который объединяет PostgreSQL с Patroni, WAL-G и основными расширениями. Каждый модуль в StatefulSet запускает контейнер Spilo. Спиральные ручки:

  • Сервер PostgreSQL— сама база данных, поддерживающая версии с 13 по 16
  • Patroni— агент высокой доступности, который управляет выбором лидера, репликацией и аварийным переключением
  • WAL-G— инструмент непрерывного архивирования WAL и базового резервного копирования
  • pg_cron, pg_stat_statements, PostGIS— предустановленные часто необходимые расширения

Patroni: выбор лидера и автоматическое аварийное переключение

Patroni — это сердце механизма высокой доступности. Он использует распределенное хранилище конфигураций (DCS) для поддержания состояния кластера и выполнения выборов лидера. В контексте оператора Zalando Patroni использует самKubernetes APIв качестве DCS (через Endpoints или ConfigMaps), устраняя необходимость во внешнем кластере etcd или ZooKeeper.

Вот как работает процесс аварийного переключения Patroni:

  1. Проверки работоспособности— каждый агент Patroni постоянно контролирует свой локальный экземпляр PostgreSQL и сообщает о работоспособности DCS.
  2. Блокировка лидера— основной блок удерживает блокировку лидера в РСУ (объект конечной точки Kubernetes). Блокировка имеет TTL (по умолчанию 30 секунд).
  3. Обнаружение сбоя— если первичному серверу не удается возобновить блокировку в пределах TTL, реплики обнаруживают это отсутствие.
  4. Выборы— подходящие реплики соревнуются за замок лидера. Реплика с наименьшей задержкой репликации побеждает.
  5. Продвижение— выигравшая реплика становится основной, обновляет DCS, а конечная точка службы Kubernetesmasterобновляется автоматически.
  6. Ограждение— старый основной сервер изолируется (остановлен или понижен до уровня реплики), чтобы предотвратить разделение мозга.

Весь этот процесс аварийного переключения обычно занимает15–30 секунд (), что обеспечивает минимальное время простоя ваших приложений.

WAL-G: непрерывное архивирование и резервное копирование

WAL-G — это инструмент архивирования нового поколения для PostgreSQL, который поддерживает резервное копирование в S3, Google Cloud Storage (GCS) и хранилище BLOB-объектов Azure. Он обеспечивает:

  • Базовые резервные копии— Полные физические резервные копии с использованиемpg_basebackup
  • Архивирование WAL— непрерывная доставка журналов с упреждающей записью для восстановления на определенный момент времени
  • Дельта-резервные копии— инкрементальные резервные копии, в которых сохраняются только измененные страницы
  • Шифрование— шифрование неактивных резервных копий AES-256
  • Сжатие— сжатие LZ4 или ZSTD для снижения затрат на хранение

Иерархия ресурсов Kubernetes

При создании пользовательского ресурсаpostgresqlоператор создает полный набор ресурсов Kubernetes для управления кластером. Понимание этой иерархии важно для устранения неполадок и мониторинга:

Иерархия ресурсов Kubernetes — оператор ZalandoPostgreSQL CRDОператор PostgresStatefulSetСервис(главный)Сервис(реплика)Конечные точкиPDBМодулиPVCsСекретыРазвертывание PgBouncerСервис (пулер)ПервичныйРепликаРепликаСплошные линии = прямое создание | Пунктирные линии = условное созданиеРесурсы

, созданные оператором

  • StatefulSet— управляет модулями PostgreSQL со стабильной сетевой идентификацией и упорядоченным развертыванием
  • Службы— две службы ClusterIP:<cluster-name>для основной и<cluster-name>-replдля реплик чтения
  • Конечные точки— Patroni обновляет конечные точки, чтобы они указывали на текущего лидера для плавного переключения при сбое
  • PodDisruptionBudgets (PDB)— гарантирует, что хотя бы один экземпляр остается доступным во время добровольных сбоев
  • Секреты— учетные данные суперпользователя, репликации и приложения PostgreSQL, хранящиеся как секреты Kubernetes
  • PersistentVolumeClaims (PVCs)— один PVC на модуль для PostgreSQL хранилище данных
  • Развертывание PgBouncer— дополнительный пул соединений, развернутый как отдельное развертывание с собственной службой
Установка

на нескольких платформах Kubernetes

Предварительные требования

Перед установкой оператора Zalando Postgres убедитесь, что у вас есть:

.
  • Работающий кластер 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 для постоянного хранения и управляемое удостоверение для резервной аутентификации:

# 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 использует постоянный диск и идентификатор рабочей нагрузки для доступа к резервным копиям 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 ПервичныйСпило + ПатрониОператор ZalandoПул PgBouncerТом Longhorn/mnt/longhorn (3 реплики)Узел 2 (сервер k3s)Реплика PostgreSQLСпило + ПатрониПул PgBouncerЭкспортер PrometheusТом Longhorn/mnt/longhorn (3 реплики)Узел 3 (агент k3s)Реплика PostgreSQLСпило + ПатрониПул PgBouncerПриборная панель GrafanaТом Longhorn/mnt/longhorn (3 реплики)HAProxy/MetalLB LoadBalancerРезервное копирование WAL-GNFS/MinIO S3-совместимыйПервичныйРепликаPgBouncerЛонгхорнПотоковая репликация

Кластер PostgreSQL CRD Технические характеристики

Основа развертывания Кластер PostgreSQL с оператором Zalando — это специальный ресурсpostgresql. Этот манифест 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 для основного сервиса, сокращая накладные расходы на соединение.
  • EnableReplicaConnectionPooler— развертывает отдельный PgBouncer для службы реплик, что необходимо для рабочих нагрузок с большим объемом чтения.
  • postgresql.parameters— параметры конфигурации Direct PostgreSQL, передаваемые вpostgresql.conf.
  • патрони— настраивает поведение Patroni, включая TTL, ожидание цикла, тайм-аут повторной попытки и режим синхронной репликации.
  • том.storageClass— соответствует классу StorageClass для конкретной платформы (EBS gp3 на AWS, Premium SSD на Azure, SSD PD на GCP, Longhorn на k3s).
  • EnableShmVolume— монтируетtmpfsна/dev/shmдля общей памяти PostgreSQL, что критически важно для производительности.
Пул соединений

с помощью PgBouncer

Модель PostgreSQL «обработка каждого соединения» делает обработку большого количества клиентских подключений дорогостоящей. Каждое соединение потребляет примерно 10 МБ ОЗУ. 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США-ВОСТОК-1 (AWS EKS)ПЕРВИЧНЫЙ КЛАСТЕРpg-prod-us (3 модуля)ПервичныйРепликаРепликация синхронизации в пределах зоны доступностиWAL-G → S3 (непрерывный)Пулер PgBouncerEU-WEST-1 (Azure AKS)РЕЗЕРВНЫЙ КЛАСТЕРpg-standby-eu (2 модуля)Режим ожиданияРепликаКаскадная репликацияWAL-G → Azure BlobPgBouncer (только чтение)Точка доступа-ЮГО-ВОСТОК (GCP GKE)РЕЗЕРВНЫЙ КЛАСТЕРpg-standby-ap (2 модуля)Режим ожиданияРепликаКаскадная репликацияWAL-G → Ковш GCSPgBouncer (только чтение)АСИНХРОННЫЙASYNC (доставка WAL)Топология репликацииОсновной (США-ВОСТОК) → Асинхронная потоковая передача в ЕС-ЗАПАД и amp; Резервные кластеры AP-SOUTEAST | RPO: ~секунд | RTO: <5 минут при повышении вручную.Синхронизация репликацииАсинхронная репликацияПервичныйРезервный лидерЧтение реплики

Конфигурация потоковой репликации

Потоковая репликация PostgreSQL — это основа высокой доступности у оператора Zalando. Он работает путем доставки записей журнала упреждающей записи (WAL) от первичного сервера к репликам практически в реальном времени. Оператор настраивает это автоматически, но понимание деталей помогает при настройке и устранении неполадок.

  • Синхронная репликация— Первичный сервер ожидает, пока хотя бы одна реплика подтвердит получение WAL, прежде чем совершить транзакцию. Это гарантирует нулевую потерю данных (RPO=0), но увеличивает задержку. Включите с помощьюpatroni.synchronous_mode: true.
  • Асинхронная репликация— основной фиксирует немедленно и отправляет WAL асинхронно. Немного меньшая задержка, но возможная потеря данных во время аварийного переключения. Это значение по умолчанию.
  • Каскадная репликация— реплики могут реплицироваться из других реплик вместо основной, что снижает нагрузку на основную реплику в больших кластерах.
# 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. .
  3. Восстанавливает базовую резервную копию основного модуля нового StatefulSet
  4. .
  5. Воспроизводит сегменты WAL до указанной отметки времени.
  6. .
  7. Открывает базу данных для операций чтения и записи.
  8. .
  9. Настраивает потоковую репликацию на модули реплик
  10. .

Резервный кластер для аварийного восстановления

Резервный кластер непрерывно реплицируется из основного кластера, обеспечивая «теплый» резерв, который можно повысить во время аварии. Это отличается от реплик внутри кластера: резервный кластер — это полностью независимый ресурс 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. Вот как настроить полный стек мониторинга:

Сервисный монитор для 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/inserted/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 = не работает).
  • патрони_мастер— какой модуль является текущим основным (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

Планировщик запросов и ввод-вывод

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

Последовательные обновления и обновления версий

Обновления младшей версии

Незначительные обновления версии (например, с 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:

.
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 (или внешние менеджеры секретов, такие как Vault) для учетных данных базы данных. Никогда не храните пароли в ConfigMaps.
  • RBAC— Ограничить разрешения ServiceAccount оператора. Используйте доступ с наименьшими привилегиями для пользователей базы данных приложения.
  • NetworkPolicies— Ограничить связь между модулями, как показано в предыдущем разделе.
  • pg_hba.conf— настройте аутентификацию на основе хоста, чтобы ограничить IP-адреса и пользователей, которые могут подключаться.
  • Ведение журнала аудита— включите расширениеpgauditдля ведения журнала аудита SQL в регулируемых средах.
  • Зашифрованное хранилище— используйте зашифрованные классы хранения (шифрование EBS, шифрование диска Azure и т. д.).
  • Стандарты безопасности модулей— запуск модулей Spilo от имени пользователя без полномочий root с ограниченным контекстом безопасности.
# 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 ядра8GiТвердотельный накопитель 50Gi3
Среднее производство4 ядра16GiТвердотельный накопитель 200Gi3
Крупносерийное производство8 ядер32GiТвердотельный накопитель 500Gi5
Предприятие/Аналитика16+ ядер64Gi+Твердотельный накопитель 1Ti+5+

Полный пример сквозного развертывания

Давайте соберем все вместе и осуществим полное развертывание с нуля на новом кластере 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 и «голых» кластерах k3s.

Основные выводы из этого руководства:

  • Автоматизируйте все— позвольте оператору управлять StatefulSet, аварийным переключением и планированием резервного копирования. Ручное вмешательство должно быть исключением.
  • Активный мониторинг— развертывание Prometheus и Grafana с первого дня. Задержка репликации, количество подключений и конфликты блокировок — это сигналы раннего предупреждения.
  • Планируйте аварийные ситуации— настройте резервное копирование WAL-G, регулярно тестируйте PITR и поддерживайте резервный кластер для критических рабочих нагрузок.
  • Настройте свою рабочую нагрузку— параметры PostgreSQL по умолчанию являются консервативными. Настройте параметры Shared_buffers, Work_mem и Checkpoint в зависимости от распределения ресурсов и шаблонов запросов.
  • Безопасность по умолчанию— включите TLS, используйте аутентификацию SCRAM-SHA-256, ограничьте доступ к сети и зашифруйте хранящееся хранилище.
  • Тестовые обновления— всегда клонируйте свой кластер и тестируйте обновления основных версий перед применением их в рабочей среде.

Благодаря этой комплексной базе вы хорошо подготовлены к развертыванию и эксплуатации высокодоступных кластеров PostgreSQL на любой платформе Kubernetes, обслуживающих приложения, требующие надежности, производительности и целостности данных в любом масштабе.