Lab 22 – Operátor: PostgreSQL

Lab 22 – Operátor: PostgreSQL

Cíl: nainstalovat skutečný operátor, vytvořit databázový cluster jedním malým manifestem a sledovat, jak ho operátor sám opraví. Kapitola: CRD a operátory

Použijete CloudNativePG, operátor pro PostgreSQL. Všechno dosud probrané platí: operátor vytváří pody podobné StatefulSetu, Services, Secrety a PVC – objekty, které už umíte číst.

Nejdřív úložiště

Cluster nemá dynamické provisioning, takže PV musí existovat dřív, než si o ně databáze řekne. Použijte NFS PV z labu 18:

# 1 –
kubectl get pv
for p in pv-storage1 pv-storage2 pv-storage3; do
  kubectl patch pv $p -p '{"spec":{"claimRef":null}}' 2>/dev/null
done
kubectl get pv          # všechny tři Available
Tip

Pokud jste v labu 18 nainstalovali NFS CSI driver, můžete statické PV úplně vynechat: nastavte v Cluster specifikaci níže storageClass: nfs-csi a nechte driver vytvořit jeden volume na instanci. Takhle by to vypadalo ve skutečném clusteru.

Instalace operátoru

# 2 –
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo update
helm install cnpg cnpg/cloudnative-pg -n cnpg-system --create-namespace
kubectl get pods -n cnpg-system -w        # Ctrl-C až bude Running
# 3 – co operátor do clusteru přidal?
kubectl get crd | grep cnpg
kubectl api-resources --api-group=postgresql.cnpg.io
kubectl get deploy -n cnpg-system

Přibyly dvě věci: nové druhy objektů (clusters, backups, scheduledbackups, poolers) a jeden Deployment s kontrolerem, který je sleduje. To je celý vzor operátoru – CRD naučí API server podstatné jméno, kontroler mu dodá sloveso.

# 4 – nové druhy se chovají přesně jako vestavěné
kubectl explain cluster.spec | head -30
kubectl explain cluster.spec.storage

kubectl explain na CRD funguje, protože schéma je zaregistrované u API serveru. Stejně tak RBAC, describe, labely a všechno ostatní.

Vytvoření databáze

# 5 – celý požadavek
cd ~
cat > pgcluster.yaml <<'YAML'
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pgtest
spec:
  instances: 2
  storage:
    size: 500Mi
    storageClass: ""
  postgresql:
    parameters:
      shared_buffers: "32MB"
YAML
kubectl apply -f pgcluster.yaml
kubectl get cluster pgtest -w             # Ctrl-C až ohlásí healthy

Patnáct řádků. A teď se podívejte, co z nich operátor postavil:

# 6 –
kubectl get pods -l cnpg.io/cluster=pgtest -o wide
kubectl get pvc
kubectl get svc | grep pgtest
kubectl get secret | grep pgtest
kubectl describe cluster pgtest | tail -25
  • jeden pod na instanci, s labelem role: jeden primární, jeden replika
  • jeden PVC na instanci, navázaný na vaše NFS PV
  • tři Services: -rw (primární), -ro (repliky), -r (kterýkoli)
  • vygenerované Secrety s údaji superuživatele a aplikace

Napsat tohle ručně je práce na odpoledne. Důležitější je, že to operátor bude dál udržovat správné.

# 7 – připojte se a použijte to
kubectl exec -it pgtest-1 -- psql -c 'select version();'
kubectl exec -it pgtest-1 -- psql -c 'create table demo(id int); insert into demo values (1),(2);'
kubectl exec -it pgtest-1 -- psql -c 'select count(*) from demo;'

Sledujte, jak provozuje

# 8 – který pod je primární?
kubectl get pods -l cnpg.io/cluster=pgtest -L role
# 9 – zabijte primární a sledujte failover
kubectl delete pod "$(kubectl get pods -l cnpg.io/cluster=pgtest,role=primary -o name)"
kubectl get pods -l cnpg.io/cluster=pgtest -L role -w    # Ctrl-C po přepnutí
kubectl describe cluster pgtest | tail -15

Replika byla povýšena, Service -rw míří na ni a starý primár se připojí zpět jako replika. Tohle by žádný kontroler Kubernetes neuměl – je k tomu potřeba znalost PostgreSQL. A právě tu operátor balí.

# 10 – data přežila
kubectl exec -it "$(kubectl get pods -l cnpg.io/cluster=pgtest,role=primary -o name | head -1 | cut -d/ -f2)" -- psql -c 'select count(*) from demo;'

Objevovací část

Infodiscovery

Úkol A. Najděte heslo aplikačního uživatele, které operátor vygeneroval, aniž byste četli jakýkoli soubor, který jste vytvořili.

kubectl get secret | grep pgtest
kubectl get secret pgtest-app -o jsonpath='{.data.password}' | base64 -d; echo
kubectl get secret pgtest-app -o jsonpath='{.data.username}' | base64 -d; echo

Úkol B. Naškálujte databázi na tři instance úpravou jediného objektu. Očekávaný výsledek: přibude třetí pod a třetí PVC.

kubectl patch cluster pgtest --type merge -p '{"spec":{"instances":3}}'
kubectl get pods -l cnpg.io/cluster=pgtest -w
kubectl get pvc

Upravili jste jedno pole jednoho objektu. Zbytek udělal operátor – v tom je rozdíl mezi chartem a operátorem.

Úkol C. Zobrazte všechny události, které operátor pro tenhle cluster vyprodukoval, nejnovější naposled.

kubectl get events --sort-by=.lastTimestamp | grep -i pgtest
kubectl describe cluster pgtest | tail -30
kubectl logs -n cnpg-system deploy/cnpg-cloudnative-pg --tail=30

Úkol D. Smažte objekt Cluster. Nejdřív předpovězte: co se stane s pody a co s daty?

kubectl delete cluster pgtest
kubectl get pods -l cnpg.io/cluster=pgtest
kubectl get pvc

Pody a Services zmizí, protože je operátor vlastní. PVC zůstanou – stejný princip jako u StatefulSetu. Vaše data nejsou vedlejší škoda.

Úklid

kubectl delete cluster pgtest --ignore-not-found
kubectl delete pvc --all
helm uninstall cnpg -n cnpg-system
kubectl delete ns cnpg-system
for p in pv-storage1 pv-storage2 pv-storage3; do
  kubectl patch pv $p -p '{"spec":{"claimRef":null}}' 2>/dev/null
done
Poznámka

Smazání operátoru nesmaže vaše objekty Cluster ani jejich data – CRD a custom resources přežijí, jen je nikdo nereconciluje. To je dobré vědět, než budete operátor upgradovat.