Kubernetes PostgreSQL / EDB

PostgreSQL w Kubernetes – nowa era zarządzania bazami danych z CloudNativePG

2025-08-07
Podziel się

Migracja do chmury i rosnąca popularność kontenerów, w tym Kubernetes, stawiają przed administratorami baz danych nowe wyzwania. Choć technologie te obiecują elastyczność i skalowalność, pojawiają się również obawy, szczególnie w kontekście systemów zarządzania bazami danych, jak PostgreSQL. Jedną z kluczowych kwestii jest trwałość danych. Jak zapewnić, by cenne informacje nie zostały utracone w dynamicznym środowisku kontenerowym? Równie ważna jest wydajność – czy uruchomienie PostgreSQL w kontenerze nie wpłynie negatywnie na jego szybkość? Wreszcie pojawia się obawa o złożoność wdrożenia. Warto podkreślić, że omawiane rozwiązania nie są optymalne dla pojedynczych instancji PostgreSQL. Ich prawdziwa wartość ujawnia się w zarządzaniu wieloma klastrami. W tym artykule przedstawimy rozwiązanie CloudNativePG, wyjaśniając, czym jest i jakie oferuje funkcjonalności. Skupimy się także na praktyce, demonstrując, jak postawić pierwszy klaster PostgreSQL w kontenerach oraz omawiając jego składowe przedstawione w pliku YAML.

W kontekście zarządzania bazami danych PostgreSQL w Kubernetes CloudNativePG jest operatorem PostgreSQL typu open source, zaprojektowanym z myślą o środowiskach wysokiej dostępności (HA). Nie jest to jedynie PostgreSQL uruchomiony w kontenerze, lecz kompleksowe narzędzie, które w pełni wykorzystuje możliwości Kubernetes do automatyzacji, orkiestracji i zarządzania klastrami PostgreSQL.

Warto podkreślić, że CloudNativePG celuje w dostarczenie możliwości z najwyższego poziomu – Poziomu V (Auto Pilot) – w systemie klasyfikacji funkcji zarządzania operatorów, bazującym na Operator SDK Capability Levels framework. Poziomy te określają zakres funkcji, które udostępnia operator – od podstawowej instalacji (Poziom I) po pełną automatyzację i samoadaptację (Poziom V). Choć CloudNativePG dąży do maksymalnej automatyzacji i autonomii w zarządzaniu klastrami, jego dokumentacja zaznacza, że użytkownik może spodziewać się części funkcjonalności przypisanych do Poziomu V. Więcej na ten temat znajdziesz w sekcji Operator Capability Levels w oficjalnej dokumentacji.

Głównym celem CloudNativePG jest uproszczenie wdrażania i zarządzania PostgreSQL w Kubernetes, eliminując wiele ręcznych zadań, które tradycyjnie są związane z utrzymaniem baz danych. Zamiast martwić się o replikację, przełączanie awaryjne (failover), tworzenie kopii zapasowych czy skalowanie, CloudNativePG automatyzuje te procesy, integrując się z mechanizmami Kubernetes.

Spis treści:

Jakie kluczowe funkcjonalności oferuje CloudNativePG?

  • Zapewnienie wysokiej dostępności i odporności na awarie – operator automatycznie zarządza replikacją strumieniową PostgreSQL i zapewnia automatyczne przełączanie awaryjne w przypadku awarii węzła lub instancji, minimalizując przestoje.
  • Łatwe skalowanie – operator umożliwia proste zwiększanie lub zmniejszanie liczby replik, co pozwala dostosować wydajność odczytów do bieżących potrzeb.
  • Tworzenie kopii zapasowych i odzyskiwanie danych – CloudNativePG integruje się z popularnymi rozwiązaniami do przechowywania danych w chmurze z interfejsem S3, umożliwiając łatwe tworzenie kopii zapasowych, archiwizację plików WAL oraz odzyskiwanie danych.
  • Monitorowanie i observability – operator udostępnia metryki Prometheus, co pozwala na monitorowanie stanu i wydajności baz danych w Kubernetes.
  • Zarządzanie cyklem życia klastra – od początkowego wdrożenia, przez aktualizacje, po usuwanie klastra – CloudNativePG zarządza całym cyklem życia bazy danych.
  • Bezpieczeństwo – oferuje funkcje, takie jak integracja z systemami zarządzania certyfikatami Kubernetes, co ułatwia bezpieczną komunikację.

Dzięki tym funkcjonalnościom CloudNativePG staje się potężnym narzędziem dla administratorów i deweloperów, którzy chcą uruchamiać PostgreSQL w sposób niezawodny, skalowalny i efektywny w środowisku Kubernetes.

W tym kontekście warto wspomnieć o Lek­kiej Platformie Konteneryzacji (LPK) – stworzonym przez nas rozwiązaniu, które ułatwia integrację i zarządzanie narzędziami do monitorowania oraz zabezpieczenia Kubernetes. LPK została stworzona po to, by organizacje mogły szybko wdrożyć spersonalizowaną, bezpieczną platformę konteneryzacji z modułów, w skład których wchodzą komponenty takie jak Prometheus, Istio, Kibana Elastic, Jaeger, Kyverno, Kubewarden, Sealed Secret, NeuVector, Conjur (CyberArk) czy HashiCorp Vault – bez potrzeby ręcznego konfigurowania każdego elementu.

Modułowa budowa Lek­kiej Platformy Konteneryzacji pozwala dobierać tylko te komponenty, które są niezbędne, co znacząco upraszcza wdrożenie i późniejsze utrzymanie. Dowiedz się więcej na temat LPK: https://linuxpolska.com/pl/rozwiazania/lekka-platforma-konteneryzacji/.

Praktyczne wdrożenie – Twój pierwszy klaster PostgreSQL z CloudNativePG

Mając już podstawową wiedzę o CloudNativePG i jego możliwościach, przejdźmy do praktyki. Poniżej opisujemy dwa kroki niezbędne do uruchomienia klastra z trzema instancjami. Zaznaczyć tutaj musimy, że krok drugi jest w wersji A i B. Kolejno wersja podstawowa i bardziej rozbudowana. Czytelnik może wybrać, której użyje.

Krok 1. Instalacja Operatora CloudNativePG

Pierwszym i najważniejszym krokiem do uruchomienia PostgreSQL w Kubernetes za pomocą CloudNativePG jest instalacja samego operatora. Użyjemy do tego wersji v1.26.1, wydanej 25 lipca 2025 roku, której dokumentację można znaleźć pod adresem: https://cloudnative-pg.io/documentation/1.26/.

Warto zaznaczyć, że społeczność CloudNativePG działa niezwykle prężnie. Zaledwie kilka dni później, 29 lipca, pojawiła się wersja v1.27.0-rc1. Nowsza wersja wprowadza bardzo użyteczną funkcjonalność, której brakowało w poprzednich architekturach PostgreSQL – mianowicie synchronizację i migrację slotów używanych do replikacji logicznej. To znacząco ułatwia zarządzanie i utrzymanie baz danych w dynamicznym środowisku kontenerowym.

Instalacja operatora z użyciem manifestu:

kubectl apply --server-side -f \  
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.26/releas es/cnpg-1.26.1.yaml

Weryfikację poprawności instalacji przeprowadzamy za pomocą poniższej komendy:

kubectl rollout status deployment \ 
 -n cnpg-system cnpg-controller-manager 
deployment "cnpg-controller-manager" successfully rolled out 
➜ ~ kubectl get deployments -n cnpg-system

NAME READY UP-TO-DATE AVAILABLE AGE cnpg-controller-manager 1/1 1 1 20d

Dla bardziej dociekliwych, szczegółowy opis deploymentu cnpg-controller-manager jest dostępny po wpisaniu komendy:

kubectl describe deploy -n cnpg-system cnpg-controller-manager

Krok 2A. Deklaratywny deployment klastra PostgreSQL – prosta konfiguracja

Jedynie osiem wierszy (nie wliczając pustej linii) jest potrzebnych do utworzenia klastra z trzema węzłami, który w znakomity sposób chroniony jest mechanizmami HA przez CloudNativePG.

Deklaratywny deployment klastra PostgreSQL – prosta konfiguracja
Deklaratywny deployment klastra PostgreSQL – prosta konfiguracja

Krok 2B. Deklaratywny deployment klastra PostgreSQL – rozbudowana konfiguracja

Deklaratywny deployment klastra PostgreSQL – rozbudowana konfiguracja
Deklaratywny deployment klastra PostgreSQL – rozbudowana konfiguracja

Do konfiguracji, jaką wykonamy, dołożymy „kilka” dodatkowych, które pozwolą zachować porządek w naszych obiektach Kubernetesa oraz umożliwią nam bezpieczny dostęp do bazy danych.

PORZĄDEK: w pierwszej kolejności zadbajmy o to, aby nasze obiekty były rozłożone w zorganizowany sposób. Do tego celu służą przestrzenie nazw (namespace). Możemy to wykonać na dwa sposoby:

  • kubectl create namespace lp
  • konfiguracja w pliku YAML ( wiersz [1:4] )

BEZPIECZEŃSTWO: tworzymy użytkownika usrlp w namespace, gdzie będzie działał klaster cluster-linuxpolska ( wiersz[8:16] ). W sekcji bootstrap ( wiersz[29:34] ) uczynimy go właścicielem bazy danych db_app. Zakodowane ciągi znaków odpowiadające kolejno username i password kodujemy przy użyciu base 64. Ponieważ nazwa użytkownika i hasło są identyczne, zakodowane ciągi znaków są takie same. Zgodnie z konwencją przyjętą w K8s, tworzony obiekt będzie typu Secret.

➜ cluster-linuxpolska echo -n "usrlp" | base64
dXNybHA=

DOSTĘP: w celu umożliwienia dostępu musimy wykonać dwie czynności.

Pierwszą z nich odpowiednie ustawienie Host Base Access (wiersz[36:39]). Klasycznie wszystkie ustawienia konfigurowaliśmy w pliku pg_hba.conf. W naszym klastrze CNPG robi się to bardzo podobnie, a mianowicie poprzez deklarację w pliku YAML, co na dalszym etapie przepisywane jest do pliku pg_hba.conf w kontenerach. Nie zapominajmy, że w Kubernetes w dużym uproszczeniu znajduje się PostgreSQL, który zawiera tak samo zbudowany katalog PGDATA. Tam nadal znajdują się pliki postgresql.conf, pg_hba.conf oraz reszta wraz ze standardowymi katalogami. Poniżej output komendy ls -la zawartości katalogu w jednym z kontenerów.

➜ cluster-linuxpolska kubectl exec -it -n lp cluster-linuxpolska-1 -- bash 
Defaulted container "postgres" out of: postgres, bootstrap-controller (init) 
postgres@cluster-linuxpolska-1:/$ ls -la /var/lib/postgresql/data/pgdata 
total 144 
drwx------. 19 postgres tape 4096 Aug 1 12:16 . 
drwxrwsr-x. 4 root tape 4096 Aug 1 12:11 .. 
drwxrws---. 7 postgres tape 4096 Aug 1 12:12 base 
-rw-------. 1 postgres tape 36 Aug 1 12:16 current_logfiles 
-rw-r--r--. 1 postgres tape 1197 Aug 1 12:11 custom.conf 
drwxrws---. 2 postgres tape 4096 Aug 1 12:15 global 
-rw-rw----. 1 postgres tape 448 Aug 1 12:11 override.conf 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_commit_ts 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_dynshmem 
-rw-r--r--. 1 postgres tape 438 Aug 1 12:16 pg_hba.conf 
-rw-r--r--. 1 postgres tape 112 Aug 1 12:11 pg_ident.conf 
drwxrws---. 4 postgres tape 4096 Aug 1 12:17 pg_logical 
drwxrws---. 4 postgres tape 4096 Aug 1 12:11 pg_multixact 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_notify
drwxrws---. 4 postgres tape 4096 Aug 1 12:12 pg_replslot 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_serial 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_snapshots 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_stat 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_stat_tmp 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_subtrans 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_tblspc 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_twophase 
-rw-rw----. 1 postgres tape 3 Aug 1 12:11 PG_VERSION 
drwxrws---. 4 postgres tape 4096 Aug 1 12:17 pg_wal 
drwxrws---. 2 postgres tape 4096 Aug 1 12:11 pg_xact 
-rw-rw----. 1 postgres tape 88 Aug 1 12:11 postgresql.auto.conf 
-rw-rw----. 1 postgres tape 30921 Aug 1 12:11 postgresql.conf 
-rw-rw----. 1 postgres tape 75 Aug 1 12:11 postmaster.opts 
-rw-------. 1 postgres tape 98 Aug 1 12:11 postmaster.pid

Drugą czynnością jest „wystawienie” naszego klastra na zewnątrz. Tutaj mam na myśli uruchomienie interfejsu, po którym użytkownicy będą mogli się łączyć z bazą danych. W konfiguracji dodamy kilka linii, dzięki którym nasza baza będzie widoczna pod adresem IP (wiersz[43:50]). Można to wykonać na kilka sposobów, a mianowicie plik YAML lub też edycja utworzonego interfejsu i zmiana z typu ClusterIP na LoadBalancer. Chcąc uzyskać na koniec naszych prac jeden plik YAML, zdecydujemy się wpisać w niego konfigurację.

To koniec deklaratywnej konfiguracji naszego klastra. W pliku cluster-linuxpolska.yaml zapisaliśmy nasze wymagania, które możemy następnie zlecić do utworzenia. Pamiętajmy, że większość parametrów PostgreSQL może być nadal przez nas zmieniana, tak, jak to było z bazami na bare metal czy VM. Odbywa się to jednak inaczej, a mianowicie przez deklarację w pliku YAML i ponowne wykonanie komendy kubectl apply -f. Trzeba jednak być ostrożnym i świadomym ich działania. Na przykład parametr instances możemy skalować w górę i w dół, natomiast raz zwiększone miejsce storage nie pozwoli na operację shrinkowania tzn. zmniejszenia.

Poniżej komendy i output listujący komponenty utworzonego klastra:

➜ cluster-linuxpolska kubectl -n lp get pods 
NAME                     READY    STATUS     RESTARTS   AGE 
cluster-linuxpolska-1    1/1      Running    0          115m 
cluster-linuxpolska-2    1/1      Running    0          114m 
cluster-linuxpolska-3    1/1      Running    0          114m 
➜ cluster-linuxpolska kubectl -n lp get pvc 
NAME                     STATUS    VOLUME                                      CAPACITY    ACCESS    MODES              STORAGECLASS VOLUMEATTRIBUTESCLASS    AGE 
cluster-linuxpolska-1    Bound     pvc-398d33f9-3768-4166-b815-341254fe24f5    1Gi         RWO       vsphere-csi-sc     <unset>                               115m 
cluster-linuxpolska-2    Bound     pvc-480d1bff-3fc1-46ae-94ca-1d7fccf11765    1Gi         RWO       vsphere-csi-sc     <unset>                               115m 
cluster-linuxpolska-3    Bound     pvc-c3157404-aa72-472b-af05-49075debe177    1Gi         RWO       vsphere-csi-sc     <unset>                               114m 
➜ cluster-linuxpolska kubectl -n lp get services 
NAME                        TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE 
cluster-linuxpolska-r       ClusterIP      10.43.179.100   <none>         5432/TCP         115m 
cluster-linuxpolska-ro      ClusterIP      10.43.96.177    <none>         5432/TCP         115m 
cluster-linuxpolska-rw      ClusterIP      10.43.157.206   <none>         5432/TCP         115m 
cluster-linuxpolska-rw-lb   LoadBalancer   10.43.247.116   10.10.12.165   5432:32199/TCP   115m 

Podsumowanie i dalsze kroki

CloudNativePG to bardzo obszerny temat, a rozwiązanie to już teraz ma mnóstwo do zaoferowania. Może stać się następcą tradycyjnych rozwiązań bare metal oraz maszyn wirtualnych. W trakcie czytania artykułu z pewnością mogło nasunąć się kilka pytań. Na wszystkie można znaleźć odpowiedzi, jednak nie sposób omówić ich w jednym tekście. Dlatego tym artykułem rozpoczynamy serię poświęconą CloudNativePG.

Wdrożenie klastra PostgreSQL w Kubernetes jest teraz zaskakująco proste. Prawdziwa moc CloudNativePG tkwi jednak w jego zaawansowanych funkcjonalnościach, które automatyzują operacje i zapewniają wysoką dostępność, bezpieczeństwo oraz skalowalność. Poniżej kluczowe zalety CloudNativePG, które czynią to rozwiązanie liderem w swojej klasie:

  • High Availability (HA): zapewnia automatyczne przełączanie awaryjne oraz planowane przełączanie (switchover), minimalizując przestoje;
  • deklaratywne zarządzanie konfiguracją: zgodnie z filozofią „immutable infrastructure” możemy zarządzać konfiguracją PostgreSQL wprost z pliku YAML;
  • kompleksowe backupy i odzyskiwanie (DR): dzięki integracji z magazynami obiektów (np. S3) i wsparciu dla Point-In-Time Recovery (PITR), ciągły backup i odzyskiwanie danych są niezawodne;
  • zaawansowane topologie dystrybucyjne: możliwość tworzenia klastrów replik rozciągających się na wiele środowisk gwarantuje maksymalną odporność;
  • skalowalność i elastyczność: możliwość skalowania w górę i w dół liczby instancji oraz integracja z PgBouncer pozwalają optymalizować wydajność;
  • bezproblemowe aktualizacje: dzięki rolling updates i aktualizacjom in-place, aktualizacje operatora i wersji PostgreSQL są płynne i minimalizują przestoje;
  • observability: pełna integracja z Prometheus i Grafana zapewnia dogłębne monitorowanie Twojego klastra.

Zachęcamy do śledzenia kolejnych wpisów, w których będziemy szczegółowo omawiać wybrane przez nas funkcjonalności i możliwości tego rozwiązania.

Sprawdź, w czym możemy Ci pomóc w temacie konteneryzacji: https://linuxpolska.com/pl/oferta/konteneryzacja/.