Installation PostgreSQL Operator en mode Namespace-Scoped
Guide d'installation du PostgreSQL Operator sans permissions cluster-admin, limitée à un namespace spécifique.
Contexte
Cette installation est adaptée pour les environnements OpenShift où vous n'avez pas les droits cluster-admin pour créer des ClusterRole et ClusterRoleBinding.
Limitations
⚠️ Limitations importantes de cette approche :
L'opérateur ne peut gérer que les clusters PostgreSQL dans le même namespace
Pas de gestion multi-namespace
Certaines fonctionnalités avancées peuvent être limitées
Les pods PostgreSQL utilisent un ServiceAccount du même namespace
Avantages
✅ Avantages :
Pas besoin de droits cluster-admin
Installation self-service
Isolation complète par namespace
Sécurité renforcée (principe du moindre privilège)
Prérequis
Permissions nécessaires dans le namespace
Vous devez avoir les permissions suivantes dans votre namespace :
Bonjour,
Je souhaite déployer le PostgreSQL Operator dans mon namespace "postgres-operator"
sans nécessiter de permissions cluster-admin.
Pourriez-vous créer la CustomResourceDefinition nécessaire avec la commande suivante ?
oc create -f crd-request.yaml
Cette CRD permettra de créer des ressources PostgreSQL de manière scopée à mon namespace.
Merci,
Installation
Étape 1 : Créer le namespace
oc new-project postgres-operator
Étape 2 : Attendre la création de la CRD par l'admin
# Vérifier que la CRD est créée
oc get crd postgresqls.acid.zalan.do
# Devrait afficher :# NAME CREATED AT# postgresqls.acid.zalan.do 2025-01-08T...
Étape 3 : Créer le RBAC namespace-scoped
oc create -f rbac-namespace-scoped.yaml
Vérifier :
oc get sa -n postgres-operator
# Devrait afficher postgres-operator et postgres-pod
oc get role -n postgres-operator
# Devrait afficher postgres-operator et postgres-pod
oc get rolebinding -n postgres-operator
# Devrait afficher postgres-operator et postgres-pod
Étape 4 : Créer la ConfigMap
Créer le fichier configmap-namespace-scoped.yaml :
apiVersion:v1kind:ConfigMapmetadata:name:postgres-operatornamespace:postgres-operatordata:# Configuration spécifique OpenShiftkubernetes_use_configmaps:"true"# IMPORTANT : Limiter l'opérateur à ce namespace uniquementwatched_namespace:"postgres-operator"# Imagesdocker_image:registry.opensource.zalan.do/acid/spilo-16:3.2-p3sidecar_docker_image:registry.opensource.zalan.do/acid/pgbouncer:master-32# Ressources par défautmin_cpu_limit:"250m"max_cpu_request:"2"min_memory_limit:"250Mi"max_memory_request:"4Gi"# Configuration des podspod_management_policy:"ordered_ready"pod_terminate_grace_period:"5m"# ServiceAccount pour les pods PostgreSQLservice_account_name:"postgres-pod"# Configuration du stockageenable_pod_antiaffinity:"true"pod_antiaffinity_preferred_during_scheduling:"false"# Monitoringenable_pod_disruption_budget:"true"# Workersworkers:"4"# Désactiver les features nécessitant cluster-level permissionsenable_cross_namespace_secret:"false"
# Vérifier que le pod démarre
oc get pods -l name=postgres-operator
# Devrait afficher :# NAME READY STATUS RESTARTS AGE# postgres-operator-xxxxxxxxxx-xxxxx 1/1 Running 0 30s# Vérifier les logs
oc logs -l name=postgres-operator -f
Déploiement d'un cluster PostgreSQL
Créer un cluster de test
Créer le fichier test-cluster.yaml :
apiVersion:"acid.zalan.do/v1"kind:postgresqlmetadata:name:test-clusternamespace:postgres-operatorspec:teamId:"myteam"numberOfInstances:2postgresql:version:"16"parameters:shared_buffers:"128MB"max_connections:"100"volume:size:10GistorageClass:"standard"users:admin:-superuser-createdbapp_user: []
databases:testdb:adminresources:requests:cpu:"500m"memory:"1Gi"limits:cpu:"1"memory:"2Gi"# IMPORTANT : Utiliser le ServiceAccount du namespaceserviceAccountName:postgres-podpodAntiAffinity:true
Déployer :
oc apply -f test-cluster.yaml
# Observer la création
oc get postgresql
oc get pods -l cluster-name=test-cluster -w
Vérifier le cluster
# Vérifier l'état
oc get postgresql test-cluster
# Vérifier les pods
oc get pods -l cluster-name=test-cluster
# Vérifier les services
oc get svc -l cluster-name=test-cluster
# Vérifier les secrets
oc get secrets -l cluster-name=test-cluster
Test de connexion
# Récupérer le mot de passeexport PGPASSWORD=$(oc get secret admin.test-cluster.credentials.postgresql.acid.zalan.do \
-o jsonpath='{.data.password}' | base64 -d)
# Se connecter
oc run psql-client --rm -it --restart=Never --image=postgres:16 -- \
psql -h test-cluster.postgres-operator.svc.cluster.local -U admin -d testdb
Limitations détaillées
Ce qui fonctionne ✅
Création de clusters PostgreSQL dans le namespace
Haute disponibilité (réplication Patroni)
Backups logiques
Connection pooling (PgBouncer)
Monitoring
Scaling horizontal (ajout de replicas)
Failover automatique
Rolling upgrades
Ce qui ne fonctionne PAS ❌
Multi-namespace : L'opérateur ne peut gérer que les clusters dans postgres-operator
Secrets partagés : Pas d'accès aux secrets d'autres namespaces
Node labeling : Pas de possibilité de créer/modifier des labels sur les nodes
StorageClass management : Pas de création de StorageClass
PV provisioning : Pas de contrôle sur les PersistentVolumes (niveau cluster)
Workarounds
Pour avoir plusieurs environnements :
Option 1 : Tout dans le même namespace avec préfixes
Option 2 : Déployer un opérateur par namespace (plus de ressources)
oc new-project postgres-dev
oc new-project postgres-staging
oc new-project postgres-prod
# Déployer l'opérateur dans chaque namespace
Troubleshooting
L'opérateur ne démarre pas
# Vérifier les logs
oc logs -l name=postgres-operator --tail=100
# Vérifier le ServiceAccount
oc get sa postgres-operator -o yaml
# Vérifier les RoleBindings
oc describe rolebinding postgres-operator
Le cluster ne se crée pas
# Vérifier que la CRD existe
oc get crd postgresqls.acid.zalan.do
# Vérifier l'état du cluster
oc describe postgresql test-cluster
# Vérifier les events
oc get events --sort-by='.lastTimestamp' | grep postgres
Erreur "forbidden" dans les logs
# L'opérateur essaie d'accéder à des ressources hors namespace# Vérifier que watched_namespace est bien configuré
oc get configmap postgres-operator -o yaml | grep watched_namespace
# Si vide ou "*", corriger :
oc patch configmap postgres-operator -p '{"data":{"watched_namespace":"postgres-operator"}}'# Redémarrer l'opérateur
oc rollout restart deployment postgres-operator
Migration vers cluster-scoped (si droits admin obtenus)
Si vous obtenez les droits cluster-admin plus tard :
# 1. Supprimer l'installation namespace-scoped
oc delete deployment postgres-operator -n postgres-operator
oc delete -f rbac-namespace-scoped.yaml
# 2. Installer en mode cluster-scoped
git clone https://github.com/zalando/postgres-operator.git
cd postgres-operator
# 3. Créer le RBAC cluster-level
oc create -f manifests/operator-service-account-rbac-openshift.yaml
# 4. Mettre à jour la ConfigMap pour surveiller tous les namespaces
oc patch configmap postgres-operator -p '{"data":{"watched_namespace":"*"}}'# 5. Redéployer l'opérateur
oc create -f manifests/postgres-operator.yaml
# Les clusters existants continueront de fonctionner
Sécurité
Principes appliqués
Principe du moindre privilège : Permissions limitées au strict nécessaire
# Dans vos manifests PostgreSQL, toujours spécifier :spec:serviceAccountName:postgres-pod# Limiter les ressourcesresources:requests:cpu:"500m"memory:"1Gi"limits:cpu:"2"memory:"2Gi"# Activer Pod Security StandardspodSecurityContext:runAsNonRoot:truefsGroup:103seccompProfile:type:RuntimeDefault
Récapitulatif des fichiers
postgres-operator/
├── crd-request.yaml # À faire créer par l'admin
├── rbac-namespace-scoped.yaml # RBAC limité au namespace
├── configmap-namespace-scoped.yaml # Configuration de l'opérateur
├── operator-deployment.yaml # Déploiement de l'opérateur
└── test-cluster.yaml # Exemple de cluster
Commandes de référence
# Status de l'opérateur
oc get pods -l name=postgres-operator
oc logs -l name=postgres-operator -f
# Liste des clusters
oc get postgresql
# Détails d'un cluster
oc describe postgresql test-cluster
# Pods PostgreSQL
oc get pods -l application=spilo
# Services
oc get svc -l application=spilo
# Secrets
oc get secrets -l cluster-name=test-cluster
# PVCs
oc get pvc -l cluster-name=test-cluster
# Supprimer un cluster (ATTENTION)
oc delete postgresql test-cluster
Version du document : 1.0
Dernière mise à jour : 2025-01-08
Testé avec : OpenShift 4.14+, PostgreSQL Operator v1.14.0