Aller au contenu principal

Administration Guides

Il se décline en 2 clusters :

  • cluster admin ;
  • cluster métier : Services aux applications ;
    • Ce moyen de stockage est protégé par le service BeC.

Une console d'administration est déployée sur le portail Admin : PgAdmin.

Localisation

Le service est déployé dans kubernetes :

  • namespace : kosmos-sql
    • pod : pgcluster-*
    • pod : pgadmin4-*
    • pod : postgresql-operator-cloudnative-pg-*
      • Pour le fonctionnement de la console PgAdmin
  • namespace : shared-sql
    • pod : pgcluster-*
  • namespace : kosmos-system-restricted
    • pod : iad-pg-shared-*

Configuration Initiale

Dimensionnement

Le cluster est composé de 2 replicas minimum.

Interfaces

Le service postgresql utilisable par les applications est exposé sur le cluster Kubernetes via le service Kubernetes :

$ kubectl -n kosmos-sql get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cnpg-webhook-service ClusterIP 10.43.171.114 <none> 443/TCP 21d
pgadmin4 ClusterIP 10.43.91.45 <none> 80/TCP 20d
pgcluster-pooler-ro ClusterIP 10.43.221.239 <none> 5432/TCP 5d2h
pgcluster-pooler-rw ClusterIP 10.43.66.164 <none> 5432/TCP 5d2h
pgcluster-r ClusterIP 10.43.176.20 <none> 5432/TCP 21d
pgcluster-ro ClusterIP 10.43.177.251 <none> 5432/TCP 21d
pgcluster-rw ClusterIP 10.43.204.83 <none> 5432/TCP 21d

$ kubectl -n shared-sql get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
pgcluster-pooler-ro ClusterIP 10.43.221.239 <none> 5432/TCP 5d2h
pgcluster-pooler-rw ClusterIP 10.43.66.164 <none> 5432/TCP 5d2h
pgcluster-r ClusterIP 10.43.76.128 <none> 5432/TCP 20d
pgcluster-ro ClusterIP 10.43.20.251 <none> 5432/TCP 20d
pgcluster-rw ClusterIP 10.43.242.118 <none> 5432/TCP 20d

Fichiers clés

Fichiers de configuration

NomPathDescription succincte
postgresql.conf/var/lib/postgresql/data/pgdata/Paramètres de configuration du serveur PostgreSQL

Logs

NomPathDescription succincte
pg_wal/var/lib/postgresql/data/pgdata/pg_wal/Répertoire contenant les journaux de transactions (WAL - Write-Ahead Logging)

Binaires

NomPathDescription succincte
psql/usr/bin/psqlCommande permettant d'executer les commandes SQL de PostgreSQL
postgres/usr/lib/postgresql/<version>/bin/postgresBinaire principal du serveur PostgreSQL

Combinaison de défaillance

Les données stockées dans le cluster PostgreSQL Technique peuvent être perdues dans certaines situations :

  • En cas de suppression/perte de tous les noeuds kubernetes constituant le cluster avec leurs disques attachés
  • En cas de nettoyage forcé (par exemple avec rm -rf ou destruction des pv) des volumes attachés aux pods postgresql

Statut du service Technique

Se connecter sur le portail d'Administration avec un Administrateur Système.

Cliquer sur la tuile Rancher.

Cliquer sur Kubectl Shell.

Exécuter les commandes suivantes:

kubectl -n kosmos-sql get pods -L role -l cnpg.io/cluster
kubectl -n kosmos-sql get svc
kubectl -n kosmos-sql get clusters.postgresql.cnpg.io

La commande retourne l'état des noeuds du cluster sous forme de tableau. Il faut avoir le statut Running. Le rôle de chaque pod est indiqué (primary ou replica).

kubectl -n kosmos-sql get pods -L role -l cnpg.io/cluster
NAME READY STATUS RESTARTS AGE ROLE
pgcluster-1 1/1 Running 0 19d primary
pgcluster-2 1/1 Running 0 19d replica <- si en mode HA
pgcluster-3 1/1 Running 0 19d replica <- si en mode HA

Les 3 services doivent être présents.

kubectl -n kosmos-sql get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cnpg-webhook-service ClusterIP 10.43.171.114 <none> 443/TCP 21d
pgadmin4 ClusterIP 10.43.91.45 <none> 80/TCP 21d
pgcluster-r ClusterIP 10.43.176.20 <none> 5432/TCP 21d
pgcluster-ro ClusterIP 10.43.177.251 <none> 5432/TCP 21d
pgcluster-rw ClusterIP 10.43.204.83 <none> 5432/TCP 21d

Le statut du shared-sql doit être Cluster in healthy state, l'ensemble des instances doivent être READY.

kubectl -n shared-sql get clusters.postgresql.cnpg.io
NAME AGE INSTANCES READY STATUS PRIMARY
pgcluster 21d 2 2 Cluster in healthy state pgcluster-1

Statut du service Métier

Se connecter sur le portail d'Administration avec un Administrateur Système.

Cliquer sur la tuile Rancher.

Cliquer sur Kubectl Shell.

Exécuter les commandes suivantes:

kubectl -n shared-sql get pods -L role -l cnpg.io/cluster
kubectl -n shared-sql get svc
kubectl -n shared-sql get clusters.postgresql.cnpg.io

La commande retourne l'état des noeuds du cluster sous forme de tableau. Il faut avoir le statut Running. Le rôle de chaque pod est indiqué (primary ou replica)

kubectl -n shared-sql get pods -L role -l cnpg.io/cluster
NAME READY STATUS RESTARTS AGE ROLE
pgcluster-1 1/1 Running 0 21d primary
pgcluster-2 1/1 Running 0 21d replica <- si en mode HA
pgcluster-3 1/1 Running 0 21d replica <- si en mode HA

Les 3 services doivent être présents.

kubectl -n shared-sql get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
pgcluster-r ClusterIP 10.43.76.128 <none> 5432/TCP 21d
pgcluster-ro ClusterIP 10.43.20.251 <none> 5432/TCP 21d
pgcluster-rw ClusterIP 10.43.242.118 <none> 5432/TCP 21d

Le statut du shared-sql doit être Cluster in healthy state, l'ensemble des instances doivent être READY.

kubectl -n shared-sql get clusters.postgresql.cnpg.io
NAME AGE INSTANCES READY STATUS PRIMARY
pgcluster 21d 2 2 Cluster in healthy state pgcluster-1

Se connecter

Cette procédure est valable pour tous les clusters Pg (Technique et Métier). Les exemples suivants utilisent la base Technique.

Une fois connecté, l'utilisateur peut effectuer toutes les commandes disponibles pour une base PostgreSQL en s'appuyant sur la documentation éditeur de postgreSQL.

Se connecter sur PostgreSQL via le pod

Se connecter sur le portail d'Administration avec un Administrateur Système.

Cliquer sur la tuile Rancher.

Cliquer sur Kubectl Shell.

Pour effectuer des mises à jour dans la base, il faut se connecter au pod "master". Pour effectuer des lectures seules, se connecter au pod "replica" est suffisant.

Pour identifier le pod master, utiliser la commande suivante :

kubectl -n kosmos-sql get pod -l cnpg.io/instanceRole=primary -o name

L'Administrateur peut lancer directement une invite de commandes psql sur le pod ayant le rôle master avec la commande suivante :

kubectl exec -it -n kosmos-sql $(kubectl -n kosmos-sql get pod -l cnpg.io/instanceRole=primary -o name) -- psql
Defaulted container "postgres" out of: postgres, bootstrap-controller (init)
psql (16.3 (Debian 16.3-1.pgdg110+1))
Type "help" for help.

postgres=#

Exemples de commandes

Les commandes psql standards sont disponibles :

lister les bases de données
postgres=# \l
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | ICU Locale | ICU Rules | Access privileges
-----------------------------------+--------------------+----------+-----------------+---------+-------+------------+-----------+-----------------------
coder | coder_zytkfyey | UTF8 | libc | C | C | | |
gitlab | gitlab_sfvsiiwr | UTF8 | libc | C | C | | |
iam | athea | UTF8 | libc | C | C | | |
kosmos_back | vstore_yfujhgog | UTF8 | libc | C | C | | |
labelstudioivvq | labelstudioivvq | UTF8 | libc | C | C | | |
labelstudioivvq2 | labelstudioivvq2 | UTF8 | libc | C | C | | |
lsivvq | lsivvq | UTF8 | libc | C | C | | |
metastore | metastore_puswmibn | UTF8 | libc | C | C | | |
mlflow_auth_mlflowivvq_ivvqmlflow | mlflow_pry92ked | UTF8 | libc | C | C | | |
mlflow_mlflowivvq_ivvqmlflow | mlflow_pry92ked | UTF8 | libc | C | C | | |
portalapi_user_tiles | postgres | UTF8 | libc | C | C | | |
postgres | postgres | UTF8 | libc | C | C | | |
sonarqube | sonarqube_ladvqzew | UTF8 | libc | C | C | | |
streamui | streamui_tnryvccn | UTF8 | libc | C | C | | |
superset | superset_edjkfgbn | UTF8 | libc | C | C | | |
synapse | matrix_setrkzlo | UTF8 | libc | C | C | | |
template0 | postgres | UTF8 | libc | C | C | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | libc | C | C | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
temporal | postgres | UTF8 | libc | C | C | | |
temporal_visibility | postgres | UTF8 | libc | C | C | | |
(20 rows)

Déconnexion

La commande pour quitter l'utilitaire psql est :

postgres=#\q

Se connecter via PgAdmin

Se connecter sur le portail d'Administration avec un Administrateur Système.

Cliquer sur la tuile pgAdmin.

Cliquer sur le bouton de connexion Login with Keycloak pour bénéficier du SSO.

PostgreSQL - IHM PGAdmin

Une fois connecté, depuis la fenêtre Object Explorer, il est possible d'ouvrir les deux moteurs postgres Technique (Kosmos/Kosmos) et Métier (Kosmos/Shared) après avoir paramétré dans l'onglet Connection le username puis dans la fenêtre Connect to Server le password de leur compte superuser.

Les paramètres d'accès des comptes superuser peuvent être récupérés avec les commandes suivantes :

echo "Technique username: $(kubectl -n kosmos-sql get secrets pgcluster-superuser -o jsonpath={.data.username} | base64 -d)"
echo "Technique password: $(kubectl -n kosmos-sql get secrets pgcluster-superuser -o jsonpath={.data.password} | base64 -d)"
echo "Métier username: $(kubectl -n shared-sql get secrets pgcluster-superuser -o jsonpath={.data.username} | base64 -d)"
echo "Métier password: $(kubectl -n shared-sql get secrets pgcluster-superuser -o jsonpath={.data.password} | base64 -d)"

Sauvegarde des données PostgreSQL

Le cluster PostgreSQL est sauvegardé par les mécanismes standards basés sur les CRD de backups.postgresql.cnpg.io et scheduledbackups.postgresql.cnpg.io. L'ensemble des databases du cluster PostgreSQL est sauvegardé.

Les ressources Kubernetes associés (secrets des comptes de services, etc ...) sont sauvegardées par les mécanismes standard de Véléro (CRD backups.velero.io, backupstoragelocations.velero.io et schedules.velero.io)

Pour configurer le mécanisme de sauvegarde, mettre à jour le fichier de /data/apps/platform-provisioner/values/postgresql/values-cluster-kosmos-backup.yaml

{{ if .StateValues.postgresql.kosmos.backup.enabled }}
backups:
enabled: true
endpointURL: "http://s3-cluster-hl.kosmos-s3.svc.cluster.local:9000"
s3:
bucket: kosmos-sql-backup
path: ""
accessKey: ref+k8s://v1/Secret/kosmos-s3/postgresql-inits3-secret/app_bucket_user
secretKey: ref+k8s://v1/Secret/kosmos-s3/postgresql-inits3-secret/app_bucket_password
wal:
compression: gzip
encryption: ""
maxParallel: 1
data:
compression: gzip
encryption: ""
jobs: 2
scheduledBackups:
- name: kosmos-daily-backup
schedule: "0 0 4 * * *"
{{ end }}

Où :

  • endpointURL et s3correspondent à l'URL et informations de connexion au cluster S3 cible
  • scheduledBackups.schedule correspond à la config d'ordonnancement (tous les jours à 4h00 par défaut).

Pour activer le mécanisme de sauvegarde (activé par défaut sur les configurations Autonome), passer l'attribut postgresql.kosmos.backup.enabled à true dans le fichier d'environnement /data/apps/platform-provisioner/environments/${ENV}.yaml (les autres attributs ne sont pas indiqués et ils ne doivent pas etre modifiés)

postgresql:
kosmos:
backup:
enabled: true

Puis, réinstaller la release pgcluster

cd /data/apps/platform-provisioner
helmfile -e $ENV -l name=pgcluster sync

Controler la présence du ScheduledBackups et l'ordonnancement

kubectl -n kosmos-sql get scheduledbackups.postgresql.cnpg.io pgcluster-kosmos-daily-backup -o jsonpath='{.spec.schedule}'

Le ScheduledBackups génère les ressources Backups qu'il convient de controler (Phase à completed)

kubectl -n kosmos-sql get backups.postgresql.cnpg.io  

Controller l'état d'une sauvegarde

kubectl -n shared-sql describe backups.postgresql.cnpg.io postgresql-cluster-shared-daily-backup-20260202173623

Restauration des données PostgreSQL

L'ensemble des databases du cluster PostgreSQL est restauré.

Le cluster PostgreSQL est récréé directement à partir d'une sauvegarde (mode: recovery).

info

Dans le cadre d'un PRA, les ressources utilisées par la restauration du cluster PostgreSQL tels que les Secrets et backups.postgresql.cnpg.io doivent etre restaurées en pré-requis (cf Restauration des pré-requis).

Lister les sauvegardes disponibles:

kubectl -n kosmos-sql get backups.postgresql.cnpg.io

Rechercher le backupName de la sauvegarde souhaitée (ex:backup-20251113040000):

kubectl -n kosmos-sql get backups.postgresql.cnpg.io pgcluster-kosmos-daily-backup-20251113040000 -o jsonpath='{.status.backupName}' ; echo

Indiquer ce backupName dans le fichier de valeurs ./values/postgresql/values-cluster-kosmos-restore.yaml

mode: recovery

recovery:
method: object_store

pitrTarget:
# -- Time in RFC3339 format
time: ""

backupName: "backup-20251113040000" # <------------- ICI

# -- The original cluster name when used in backups. Also known as serverName.
clusterName: "pgcluster" #

endpointURL: "http://s3-cluster-hl.kosmos-s3.svc.cluster.local:9000"
endpointCA:
create: false

destinationPath: ""
provider: s3
s3:
bucket: "kosmos-sql-backup" # Le nom du bucket S3 utilisé pour stocker les sauvegardes
path: ""
accessKey: ref+k8s://v1/Secret/kosmos-s3/postgresql-inits3-secret/app_bucket_user
secretKey: ref+k8s://v1/Secret/kosmos-s3/postgresql-inits3-secret/app_bucket_password
secret:
# -- Whether to create a secret for the backup credentials
create: true
# -- Name of the backup credentials secret
name: ""

Ajouter ce fichier de values à la liste des fichiers de values deja référencés par la release pgcluster rq: l'option --state-values-file ne fonctionne pas d'où la mise à jour directe du fichier helmfile.

  - name: pgcluster
namespace: kosmos-sql
labels:
app: postgresql
component: storage
resources: postgresql
...
values:
...
- values/postgresql/values-cluster-kosmos-restore.yaml
deleteWait: true

Installer le cluster PostgreSQL

helmfile -e $ENV -l app=postgresql,shared!=true --state-values-set postgresql.kosmos.backup.enabled=false sync
remarque

ATTENTION, la fonctionnalité backup doit impérativement être désactivée afin d'éviter l'erreur ERROR: WAL archive check failed for server postgresql-cluster: Expected empty archive

Suivre la progression de la restauration sur les logs du pod pgcluster-1-full-recovery-xxx

kubectl -n kosmos-sql logs pgcluster-1-full-recovery-gpnfn -f

Le pod pgcluster-1-full-recovery-xx doit passer au status Completed, et les noeuds du cluster doivent ensuite se lancer.

Le cluster PostgreSQL doit etre au status healthy

kubectl -n ${NS} get clusters.postgresql.cnpg.io

NAME AGE INSTANCES READY STATUS PRIMARY
pgcluster 7m7s 3 3 Cluster in healthy state pgcluster-1

Réactiver les sauvegardes du cluster

helmfile -e $ENV -l app=postgresql,shared!=true sync

Si les composants dépendant de postgresql sont toujours présents, il convient de les relancer.

kubectl -n kosmos-iam rollout restart  sts keycloak-cluster
kubectl -n kosmos-portal delete pod -l app.kubernetes.io/instance=gda
kubectl -n kosmos-portal delete pod -l app.kubernetes.io/instance=portal-front-shared
kubectl -n kosmos-system-restricted delete pod -l app.kubernetes.io/instance=portal-back
kubectl -n kosmos-system-restricted delete pod -l app.kubernetes.io/instance=portal-front-kosmos
kubectl -n kosmos-system-restricted delete pod -l app.kubernetes.io/instance=sap-back
kubectl -n kosmos-system-restricted delete pod -l app.kubernetes.io/instance=sap-front
kubectl -n kosmos-system-restricted delete pod -l app.kubernetes.io/instance=eds-back
kubectl -n kosmos-system-restricted delete pod -l app.kubernetes.io/instance=eds-front

Recreation d'un cluster à partir d'un PV

Dans le cas où le cluster ne dispose pas de Backups (ex:shared-sql), et qu'il aurait été détruit par inadvertance (helmfile destroy), cette procédure permet de recréer un cluster à partir d'un PV conservé.

Le cluster shared-sql est constitué de 3 pods et 3 PV.

  • lister les PV du Cluster supprimé (ils doivent etre à l'état Released)
kubectl get pv | grep shared-sql | grep Released
  • marquer les PV afin qu'ils redeviennent disponibles (Available) mais pas réaffectable par au cluster
kubectl patch pv pvc-5ae34f53-0894-4e62-b560-d22b9e991d9d -p '{"spec":{"claimRef": null}}'
kubectl patch pv pvc-cad153dd-ecca-4084-82e4-2d9e7bf47b92 -p '{"spec":{"claimRef": null}}'
kubectl patch pv pvc-6d69ed63-db10-4720-9fe6-02651531a5b9 -p '{"spec":{"claimRef": null}}'

kubectl patch pv pvc-5ae34f53-0894-4e62-b560-d22b9e991d9d -p '{"spec":{"claimRef": {"name":"postgresql-cluster-X","namespace":"shared-sql"}}}'
kubectl patch pv pvc-cad153dd-ecca-4084-82e4-2d9e7bf47b92 -p '{"spec":{"claimRef": {"name":"postgresql-cluster-1","namespace":"shared-sql"}}}'
kubectl patch pv pvc-6d69ed63-db10-4720-9fe6-02651531a5b9 -p '{"spec":{"claimRef": {"name":"postgresql-cluster-X","namespace":"shared-sql"}}}'
  • création du cluster
helmfile -e $ENV -l name=postgresql-cluster,shared=true sync
  • passer le cluster à une seule instance
kubectl -n shared-sql patch  clusters.postgresql.cnpg.io postgresql-cluster -p '{"spec":{"instances":"1"}}'
  • arreter le pod (hibernate)
kubectl -n shared-sql annotate clusters.postgresql.cnpg.io postgresql-cluster cnpg.io/hibernation=on
  • attendre l'arret du pod
kubectl -n shared-sql get pod
  • création du fichier manifest YAML du PVC
kubectl -n shared-sql get pvc postgresql-cluster-1 -o yaml > postgresql-cluster-1.yaml
  • suppression du PVC
kubectl delete -f postgresql-cluster-1.yaml
  • suppression des PV 1/2/3 du cluster (Release)
kubectl -n shared-sql get pv | grep shared-sql | grep Released


kubectl delete pv pvc-45325997-4cb0-4b17-88cf-940dec94f0aa
kubectl delete pv pvc-9e4c0d12-de73-49c6-a9ee-8bfa4bbb9f81
kubectl delete pv pvc-ffccd2f5-d366-4f2a-966b-b0e941523511

Rq: laisser le PV choisit pour la restauration (ex: pvc-6d69ed63-db10-4720-9fe6-02651531a5b9)

  • modifier le fichier manifest YAML du PVC (vi postgresql-cluster-1.yaml)

    • modifier metadata.annotations.volume.kubernetes.io/selected-node avec le host du PV choisit pour la restauration (ex: kubectl get pv pvc-6d69ed63-db10-4720-9fe6-02651531a5b9 -o jsonpath='{.spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].values[0]}' )
    • modifier update spec.volumeName avec le nom du PV choit pour la restauration (ex: pvc-6d69ed63-db10-4720-9fe6-02651531a5b9)
    • supprimer metadata.resourceVersion
    • supprimer metadata.uid
    • supprimer metadata.annotations."pv.kubernetes.io/bind-completed"
    • supprimer metadata.annotations."pv.kubernetes.io/bound-by-controller"
    • supprimer finalizers:
    • supprimer status:
  • patcher le PV pour qu'il soit lié au future PVC

kubectl patch pv pvc-6d69ed63-db10-4720-9fe6-02651531a5b9 -p '{"spec":{"claimRef": null}}'
kubectl patch pv pvc-6d69ed63-db10-4720-9fe6-02651531a5b9 -p '{"spec":{"claimRef": {"name":"postgresql-cluster-1","namespace":"shared-sql"}}}'
  • créer le PVC
kubectl apply -f postgresql-cluster-1.yaml
  • Vérifier que le PVC et le PV soient bien Bound
kubectl get pv pvc-6d69ed63-db10-4720-9fe6-02651531a5b9  
kubectl -n shared-sql get pvc postgresql-cluster-1
  • start the cluster (remove the annotation)
kubectl -n shared-sql annotate clusters.postgresql.cnpg.io postgresql-cluster cnpg.io/hibernation-