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
| Nom | Path | Description succincte |
|---|---|---|
| postgresql.conf | /var/lib/postgresql/data/pgdata/ | Paramètres de configuration du serveur PostgreSQL |
Logs
| Nom | Path | Description succincte |
|---|---|---|
| pg_wal | /var/lib/postgresql/data/pgdata/pg_wal/ | Répertoire contenant les journaux de transactions (WAL - Write-Ahead Logging) |
Binaires
| Nom | Path | Description succincte |
|---|---|---|
| psql | /usr/bin/psql | Commande permettant d'executer les commandes SQL de PostgreSQL |
| postgres | /usr/lib/postgresql/<version>/bin/postgres | Binaire 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 -rfou 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.

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ù :
endpointURLets3correspondent à l'URL et informations de connexion au cluster S3 ciblescheduledBackups.schedulecorrespond à 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).
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
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-nodeavec 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.volumeNameavec 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:
- modifier
-
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-