0

Etude PaaS PostgreSQL 13 sur GCP

twitterlinkedinmail

Dans le même esprit que ce qui avait été fait pour MySQL dans cet épisode, nous allons balayer les possibilités qu’offre la solution Cloud SQL PostgreSQL du cloud de Moutain View.

Pour la revue du décor (briques de service, organisation territoriale des régions, tiers et stockage, etc…) se référer à l’article pré-cité. Ces notions s’appliquent aux 3 PaaS Cloud SQL que sont MySQL, PostgreSQL et le petit dernier SQL Server (la GA est sortie en février l’année dernière), donc on ne reviendra pas dessus. Dans cet article, nous allons surtout voir quelles peuvent être les différences notables d’utilisation de PostgreSQL entre une instance on-prem et une instance Cloud SQL.

Versions, limitations et extensions supportées:

Pour ce qui est des versions, Cloud SQL supporte PostgreSQL 13 depuis novembre 2020, et était le premier clouder majeur à adopter la dernière release PostgreSQL puisqu’Amazon n’a annoncé la disponibilité qu’en février de cette année, et Azure ne va pas au delà de la version 11 en Single Server encore aujourd’hui (toutefois 12 et 13 sont disponible en Flexible et Hyperscale).

47 extensions sont supportées parmi lesquelles les principales : Gin, GiST, hstore, intarray, pgaudit, pgcrypto, pgstattuple, l’incontournable pg_stat_statements et évidemment plpgsql. A noter que CREATE EXTENSION est la seule commande qui nécessite les privilèges SUPERUSER qui soit autorisée.

Pour avoir l’exhaustivité:

postgres=> select setting from pg_settings where name='cloudsql.supported_extensions' ;
-[ RECORD 1 ]---------------------------------------------------------------------------------------
setting | address_standardizer:3.0.2, address_standardizer_data_us:3.0.2, bloom:1.0, btree_gin:1.3, 
btree_gist:1.5, citext:1.6, cube:1.4, dblink:1.2, dict_int:1.0, dict_xsyn:1.0, earthdistance:1.1,
 fuzzystrmatch:1.1, hll:2.14, hstore:1.7, intagg:1.1, intarray:1.3, ip4r:2.4, isn:1.2, lo:1.1, 
ltree:1.2, pageinspect:1.8, pg_buffercache:1.3, pg_freespacemap:1.2, pg_partman:4.4.0, 
pg_prewarm:1.2, pg_repack:1.4.6, pg_similarity:1.0, pg_stat_statements:1.8, pg_trgm:1.5,
 pg_visibility:1.2, pgaudit:1.5, pgcrypto:1.3, pgfincore:1.2, pglogical:2.3.3, pgrowlocks:1.2, 
pgstattuple:1.5, pgtap:1.1.0, plpgsql:1.0, plproxy:2.10.0, postgis:3.0.2, postgis_raster:3.0.2,
 postgis_sfcgal:3.0.2, postgis_tiger_geocoder:3.0.2, postgis_topology:3.0.2, postgres_fdw:1.0,
 prefix:1.2.0, sslinfo:1.2, tablefunc:1.0, tsm_system_rows:1.0, tsm_system_time:1.0, 
unaccent:1.1, uuid-ossp:1.1

Pour activer une extension, par exemple pg_stat_statements:

postgres=> CREATE EXTENSION pg_stat_statements ;
CREATE EXTENSION

postgres=> select * from pg_extension ;
-[ RECORD 1 ]--+-------------------
oid            | 14026
extname        | plpgsql
extowner       | 10
extnamespace   | 11
extrelocatable | f
extversion     | 1.0
extconfig      |
extcondition   |
-[ RECORD 2 ]--+-------------------
oid            | 16444
extname        | pg_stat_statements
extowner       | 16389
extnamespace   | 2200
extrelocatable | t
extversion     | 1.8
extconfig      |
extcondition   |

Et configurer le nombre max de requêtes retenues dans la vue:

C:\Program Files (x86)\Google\Cloud SDK>gcloud sql instances patch cloudpg13 \
  --database-flags pg_stat_statements.max=10000
The following message will be used for the patch API method.
{"name": "cloudpg13", "project": "paas-postgresql-mysql", "settings": {"databaseFlags": [{"name": "pg_stat_statements.max", "value": "10000"}]}}
WARNING: This patch modifies database flag values, which may require
your instance to be restarted. Check the list of supported flags -
https://cloud.google.com/sql/docs/postgres/flags - to see if your
instance will be restarted when this patch is submitted.

Do you want to continue (Y/n)?  Y

Patching Cloud SQL instance...done.
Updated [https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13].
postgres=> select query, total_plan_time, total_plan_time, total_exec_time, calls, shared_blks_hit
postgres-> from  pg_stat_statements order by  total_exec_time limit 10 ;
-[ RECORD 1 ]---+------------------------------------------------------------------------------------
query           | show max_connections
total_plan_time | 0
total_plan_time | 0
total_exec_time | 0.008291
calls           | 1
shared_blks_hit | 0
-[ RECORD 2 ]---+------------------------------------------------------------------------------------
query           | show max_wal_size
total_plan_time | 0
total_plan_time | 0
total_exec_time | 0.008558
calls           | 1
shared_blks_hit | 0
(...)

Quant aux limitations, on peut retrouver notamment:
– L’indisponibilité de LLVM/JiT et de la réplication logique pour les versions 12 et 13 pour l’instant.
– Toute commande nécessitant un accès aux privilèges SUPERUSER : ALTER SYSTEM, COPY (hors stdin), opérations sur les backends, pg_switch_wal(), pg_reload_conf(), opérations externes sur les fichiers, etc… la liste exhaustive se trouve dans la doc PostgreSQL.

Surface de paramétrage:

Les paramètres de configuration de PostgreSQL sont configurables via les Database Flags. Comme ALTER SYSTEM est désactivé il faudra passer soit par la console, soit la ligne de commande gloud, ou une API REST. Il existe 134 Database Flags en version POSTGRESQL_13:

$ gcloud sql flags list \
  --database-version=POSTGRES_13 \
  --sort-by=NAME
NAME                                           TYPE             DATABASE_VERSION                                              ALLOWED_VALUES
autovacuum                                     BOOLEAN          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
autovacuum_analyze_scale_factor                FLOAT            POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
autovacuum_analyze_threshold                   INTEGER          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
autovacuum_freeze_max_age                      INTEGER          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
(...)
vacuum_freeze_table_age                        INTEGER          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
vacuum_multixact_freeze_min_age                INTEGER          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
vacuum_multixact_freeze_table_age              INTEGER          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13
work_mem                                       INTEGER          POSTGRES_9_6,POSTGRES_10,POSTGRES_11,POSTGRES_12,POSTGRES_13

Attention à l’amalgame: un select sur pg_settings remontera nettement plus de paramètres que de flags configurables, ils ne seront tout simplement pas modifiables sur GCP. Par exemple s’il est possible de modifier work_mem :

$ gcloud sql instances patch cloudpg13 \
  --database-flags work_mem=128
The following message will be used for the patch API method.
{"name": "cloudpg13", "project": "paas-postgresql-mysql", "settings": {"databaseFlags": [{"name": "work_mem", "value": "128"}]}}
WARNING: This patch modifies database flag values, which may require
your instance to be restarted. Check the list of supported flags -
https://cloud.google.com/sql/docs/postgres/flags - to see if your
instance will be restarted when this patch is submitted.

Do you want to continue (Y/n)?  Y

Patching Cloud SQL instance...done.
Updated [https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13].

$ gcloud sql instances describe cloudpg13
(...)
  databaseFlags:
  - name: work_mem
    value: '128'

On ne peut en revanche pas toucher à d’autres paramètres comme shared_buffers

postgres=> show shared_buffers;
 shared_buffers
----------------
 1229MB
(1 row)

postgres=> alter system set shared_buffers to '1400MB' ;
ERROR:  must be superuser to execute ALTER SYSTEM command

…ou max_connections qui sont directement associés au type de tiers disponible:

Connectivité:

Google recommande d’utilisation cloud SQL Proxy pour se connecter de manière sécurisée sur les PaaS Cloud SQL. Il s’agit d’un middleware exécuté du côté applicatif, qui s’interconnecte avec une autre couche middleware côté PaaS:

Il faudra récupérer le programme client en fonction du type de client (Linux, windows,etc…).

Cloud SQL Proxy se connecte au PaaS avec un compte de service déclaré dans la partie IAM de gestion des identités de GCP, et ce compte doit disposer au moins du privilège cloudsql.instances.connect, qui peut être obtenu via les rôles Cloud SQL Admin, Editor ou Client selon ce qui est requis pour l’application. Une clé au format JSON (-credential_file) est générée et doit être déposée sur la machine cliente depuis laquelle le programme Cloud SQL Proxy sera exécuté:

$ cloud_sql_proxy_x64 \
  -credential_file=paas-postgresql-mysql-0a7b74d61a31.json \
  -instances="paas-postgresql-mysql:europe-west1:cloudpg13=tcp:5432"
2021/06/05 15:39:12 using credential file for authentication; email=xxxxxxxxxxxx@paas-postgresql-mysql.iam.gserviceaccount.com
2021/06/05 15:39:13 Listening on 127.0.0.1:5432 for paas-postgresql-mysql:europe-west1:cloudpg13
2021/06/05 15:39:13 Ready for new connections
2021/06/05 15:39:24 New connection for "paas-postgresql-mysql:europe-west1:cloudpg13"

Une fois le proxy lancé (il est conseillé de l’intégrer dans un service type systemd, ou dans un container), on peut ensuite lancer la connexion via un psql classique ou un autre programme client, redirigé vers le proxy qui tourne en localhost:

$ psql "host=127.0.0.1 sslmode=disable dbname=postgres user=postgres"
Password for user postgres:
psql (13.3, server 13.2)
postgres=> select version() ;
                                         version
------------------------------------------------------------------------------------------
 PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by Debian clang version 10.0.1 , 64-bit
(1 row)

Ca peut paraître lourd, mais cela permet de centraliser les accès aux PaaS Cloud SQL d’un même Project avec un seul service Cloud SQL Proxy. Evidemment ce mode supporte l’utilisation de certificats SSL ce qui sera conseillé si les accès clients sont initiés depuis l’extérieur et sans VPN.

Sauvegarde et restauration:

Deux types de sauvegardes disponibles, automatiques et à la demande ou manuels.

Sauvegardes automatiques

Les backups automatiques sont activés au niveau du PaaS, soit à la création soit plus tard via une modification de paramètre instance. Ils sont exécutés lors de fenêtres de maintenance de 4 heures, et sont conservés soit sur une période soit en fonction d’un nombre de backups (7 par défaut, max 365):

A noter que leur localisation est également paramétrable, si on souhaite favoriser une région plutôt qu’une autre en fonction de contraintes légales. L’activation de la restauration en Point-In-Time active la sauvegarde des WALs en plus, avec une rétention en jours (7 par défaut). Les journaux antérieurs au dernier backup complet effectué sont automatiquement supprimés.

Sauvegardes à la demande

Il est aussi possible d’effectuer des backups à la demande avec gcloud (ou la console ou API REST):

$ gcloud sql backups create --instance=cloudpg13 --location=europe-west1 --description=MANUAL
Backing up Cloud SQL instance...done.
[https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13] backed up.

$ gcloud sql backups list --instance=cloudpg13
ID             WINDOW_START_TIME              ERROR  STATUS      INSTANCE
1623055883991  2021-06-07T08:51:23.991+00:00  -      SUCCESSFUL  cloudpg13
1623055751008  2021-06-07T08:49:11.008+00:00  -      SUCCESSFUL  cloudpg13
1622640837128  2021-06-02T13:33:57.128+00:00  -      SUCCESSFUL  cloudpg13

$ gcloud sql backups list --instance=cloudpg13 --filter="type=AUTOMATED"
ID             WINDOW_START_TIME              ERROR  STATUS      INSTANCE
1622640837128  2021-06-02T13:33:57.128+00:00  -      SUCCESSFUL  cloudpg13

$ gcloud sql backups list --instance=cloudpg13 --filter="type=ON_DEMAND"
ID             WINDOW_START_TIME              ERROR  STATUS      INSTANCE
1623055883991  2021-06-07T08:51:23.991+00:00  -      SUCCESSFUL  cloudpg13
1623055751008  2021-06-07T08:49:11.008+00:00  -      SUCCESSFUL  cloudpg13

Sinon, un DESCRIBE sur chaque BACKUP_ID permettra de faire la distinction :

$ gcloud sql backups describe 1623055883991 --instance=cloudpg13
backupKind: SNAPSHOT
description: MANUAL
endTime: '2021-06-07T08:52:04.569Z'
enqueuedTime: '2021-06-07T08:51:23.991Z'
id: '1623055883991'
instance: cloudpg13
kind: sql#backupRun
location: europe-west1
selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13/backupRuns/1623055883991
startTime: '2021-06-07T08:51:23.992Z'
status: SUCCESSFUL
type: ON_DEMAND
windowStartTime: '2021-06-07T08:51:23.991Z'

$ gcloud sql backups describe 1622640837128 --instance=cloudpg13
backupKind: SNAPSHOT
endTime: '2021-06-02T13:35:18.283Z'
enqueuedTime: '2021-06-02T13:33:57.128Z'
id: '1622640837128'
instance: cloudpg13
kind: sql#backupRun
location: eu
selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13/backupRuns/1622640837128
startTime: '2021-06-02T13:33:57.136Z'
status: SUCCESSFUL
type: AUTOMATED
windowStartTime: '2021-06-02T13:33:57.128Z'

Exports de données

Mais qu’ils soient automatiques ou manuels, ils ne sont pas exportables, c’est à dire que l’on ne peut pas récupérer les fichiers résultants d’un backup. Et comme lorsque l’on supprime un PaaS, tous les backups sont supprimés, il faudra pouvoir exporter les données pour se donner une solution de retour arrière en cas de problème, soit via un client pg_dump classique :

$ pg_dump --host=127.0.0.1 --username=postgres --dbname=dvdrental > backup.dmp
Password:

… soit via gcloud dans un bucket GS (qui ne sortira ni fonction, ni procédure stockée, ni trigger contrairement à pg_dump), le compte de service du PaaS devra disposer des privilèges storage.legacyBucketWriter et storage.legacyObjectReader sur le bucket en question:

# Creation du bucket
$ gsutil mb -c NEARLINE -l europe-west1 -b on gs://cloudpg13backups
Creating gs://cloudpg13backups/...

$ gsutil ls
gs://cloudpg13backups/

# Attribution des droits au compte de service
$ gsutil iam ch serviceAccount:xxxxxxxxxxx-xxxxxxxx@gcp-sa-cloud-sql.iam.gserviceaccount.com:legacyBucketWriter,legacyObjectReader gs://cloudpg13backups

# Export des données dans le bucket
$ gcloud sql export sql cloudpg13 gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz --database=dvdrental
Exporting Cloud SQL instance...done.
Exported [https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13] to [gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz].

$ gsutil ls gs://cloudpg13backups
gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz

# Et récupération en local ...
$ gsutil cp gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz cloudpg13.dvdrental.dmp.gz
Copying gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz...
- [1 files][  8.3 KiB/  8.3 KiB]
Operation completed over 1 objects/8.3 KiB.

Restauration:

On peut restaurer sur le PaaS courant ou créer un autre PaaS avec un backup. Pour la restauration d’un backup complet :

$ gcloud sql backups describe 1623083406184 --instance=cloudpg13
backupKind: SNAPSHOT
description: 2021-06-07 18:31
endTime: '2021-06-07T16:30:46.801Z'
enqueuedTime: '2021-06-07T16:30:06.184Z'
id: '1623083406184'
instance: cloudpg13
kind: sql#backupRun
location: europe-west1
selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13/backupRuns/1623083406184
startTime: '2021-06-07T16:30:06.185Z'
status: SUCCESSFUL
type: ON_DEMAND
windowStartTime: '2021-06-07T16:30:06.184Z'

$ gcloud sql backups restore 1623083406184 --restore-instance=cloudpg13 --backup-instance=cloudpg13
All current data on the instance will be lost when the backup is
restored.

Do you want to continue (Y/n)?  Y

Restoring Cloud SQL instance...done.
Restored [https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13].

Par contre si on veut restaurer en Point-in-Time, il faudra restaurer sur une nouvelle instance que l’on va cloner:

$ gcloud sql instances clone  cloudpg13 cloudpg13-202106071200 --point-in-time 2021-06-07T17:00:00.000Z
Cloning Cloud SQL instance...\
Created [https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13-202106071200].
NAME                    DATABASE_VERSION  LOCATION        TIER              PRIMARY_ADDRESS  PRIVATE_ADDRESS  STATUS
cloudpg13-202106071200  POSTGRES_13       europe-west1-b  db-custom-1-3840  35.187.59.124    -                RUNNABLE

L’ancienne instance reste accessible.

Quant aux exports, soit rejouer avec pg_restore ou psql selon le format de sortie (custom ou plain text respectivement), ou réimporter la sauvegarde avec gcloud:

Avec psql :

postgres=> create database dvdrental ;
CREATE DATABASE
postgres=> \c dvdrental
psql (13.3, server 13.2)
You are now connected to database "dvdrental" as user "postgres".
dvdrental=> \i backup.dmp
CREATE TABLE
ALTER TABLE
COPY 200
COPY 603
COPY 16
COPY 600
COPY 109
COPY 599
COPY 1000
(...)

Avec gcloud:

$ gcloud sql import sql cloudpg13 gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz \
  --database=dvdrental --user=postgres
Data from [gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz] will be
imported to [cloudpg13].

Do you want to continue (Y/n)?  Y

Importing data into Cloud SQL instance...done.
Imported data from [gs://cloudpg13backups/cloudpg13.dvdrental.dmp.gz] into [https://sqladmin.googleapis.com/sql/v1beta4/projects/paas-postgresql-mysql/instances/cloudpg13].

Note: Pour les imports et les exports customs de données dans des fichiers plats ou CSV, noter que la commande COPY nécessite le privilège SUPERUSER donc elle n’est pas utilisable dans un script. Elle fonctionnera seulement si les données sont fournies sur l’entrée standard (stdin). Pour contourner ce problème sous le prompt psql, il est possible d’utiliser la méta-commande \copy :

dvdrental=> COPY public.actor (actor_id, first_name, last_name, last_update) FROM '3057.dat';
ERROR:  must be superuser or a member of the pg_read_server_files role to COPY from a file
HINT:  Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.

dvdrental=> \copy public.actor (actor_id, first_name, last_name, last_update) FROM '3057.dat';
COPY 200

Mise à jour et maintenance:

Comme les autres services managés chez les concurrents, il existe une fenêtre de maintenance imposée en quelque sorte qui permet de faire passer les mises à jour. Durant cette période l’accès au PaaS est coupé, le doc indique une coupure de 60 secondes en moyenne, mais la vraie difficulté est de pouvoir prévoir cette coupure, d’autant que les instances réplicas ne peuvent être sollicités sur cette période car ils sont coupés eux-aussi.

Comme sur RDS, il est possible de planifier les fenêtres de maintenance sur des périodes attendues pour éviter qu’elles n’arrivent de manière aléatoire.

$ gcloud sql instances patch cloudpg13 \
        --maintenance-window-day=SUN \
        --maintenance-window-hour=04

Il est également possible de planifier une période durant laquelle la maintenance ne peut pas s’appliquer avec un maximum de 90 jours, par exemple pour couvrir une période d’activité de vente particulièrement importante pour votre chiffre d’affaires (ventes privées, soldes, période de fêtes, etc…). La période d’exclusion peut être récurrente tous les ans si on n’indique pas l’année dans les paramètres mais seulement une date au format mm-dd:

$ gcloud sql instances patch cloudpg13 \
 --deny-maintenance-period-start-date 06-01 \
 --deny-maintenance-period-end-date 06-30 \
 --deny-maintenance-period-time 00:00:00

On peut enfin s’abonner à des notifications pour être prévenu d’une coupure prochaine, via email, dans les préférences de l’utilisateur :

Supervision :

  • Journaux d’erreur:

L’accès aux journaux de PostgreSQL peut se faire soit via la console soit via gcloud loggging :

$ gcloud logging read resource.type="cloudsql_database" --project=paas-postgresql-mysql  --limit=1 --format=json
[
  {
    "insertId": "s=4a2d092448f2442196dbf937d53aa2f3;i=11b17e;b=8d370594a8c64ab6bf7936578969b58d;m=2f32331f4e;t=5c50feb23e9aa;x=56218d300d4ea42d-0-0@a1",
    "logName": "projects/paas-postgresql-mysql/logs/cloudsql.googleapis.com%2Fpostgres.log",
    "receiveTimestamp": "2021-06-18T20:10:45.252620488Z",
    "resource": {
      "labels": {
        "database_id": "paas-postgresql-mysql:cloudpg13",
        "project_id": "paas-postgresql-mysql",
        "region": "europe"
      },
      "type": "cloudsql_database"
    },
    "severity": "INFO",
    "textPayload": "2021-06-18 20:10:43.733 UTC [52719]: [2-1] db=,user= LOG:  
       automatic analyze of table \"cloudsqladmin.public.heartbeat\" system usage: 
       CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s",
    "timestamp": "2021-06-18T20:10:43.733930Z"
  }
]

Avec un outil comme jq, il devient possible de récupérer précisément des informations contenues dans le blob JSON. Une autre solution peut consister à exporter les logs sur un autre stockage (Cloud Storage, BigTable ou Elastic Cloud par exemple) via des sinks.

  • Compteurs de performance de base:

La console permet d’accéder à 8 compteurs de base:

  • Monitoring:

La brique Cloud Monitoring permet d’aller un peu plus loin et se créer des dashboards plus complets avec davantage de métriques:

Ainsi que se créer des alertes avec notification.

  • Optimisation SQL:

Query Insights donne une première vision des requêtes en exécution si l’instance est activée avec la trace Insight :

$ gcloud sql instances create ... --insights-config-query-insights-enabled

Elle est non payante si on y accède via la console, et avec une semaine de rétention. Elle présente les requêtes avec leur temps d’exécution, le nombre de calls et le nombre moyen de lignes retournées. Deux choses à noter cependant:
– Elle est capable de normaliser les requêtes et de générer un queryid (query_hash pour gcloud) comme peut le faire pg_stat_statements:

dvdrental=> select count(1) from inventory where film_id = 995 ;
 count
-------
     6
(1 row)

dvdrental=> select count(1) from inventory where film_id = 1000 ;
 count
-------
     8
(1 row)


– La deuxième il peut afficher un plan type avec le détail des opérateurs:


L’autre bonne nouvelle c’est que pg_stat_statements est également disponible et que les actions SUPERUSER-only sont autorisées (modifier les paramètres GUC de PGSS ou appeler pg_stat_statements_reset()). On peut donc se construire un outil ou porter un existant sur des PaaS GCP sans trop de problèmes à priori.

MCO hors backups : vacuums, gestion des partitions, etc…

Pour planifier des tâches hors backups type vacuum full, etc… on pourra utiliser la brique Cloud Scheduler qui permet via des Cloud Functions serverless et des jobs de lancer des tâches planifiées.

Haute disponibilité:

On ne rentrera pas dans les détails, là encore ça pourra faire l’objet d’un post dédié, mais globalement lorsque l’on déploie un PaaS PostgreSQL, il est possible d’activer une haute disponibilité au niveau régional. Une instance standby sera créé dans une autre zone de la même région, et la synchronisation sera assurée au niveau blocs disques.

Cloud SQL étant une ressource régionale, il n’est pas possible de crééer une standby dans une autre région, donc pour se prémunir d’une indisponibilité de toute une région, la solution est de créer un read-replica dans une autre région, mais qui sera répliqué de manière asynchrone:


(source : https://cloud.google.com/architecture/intro-to-cloud-sql-disaster-recovery)

Dans le cas d’une indisponibilité de zone, l’utilisation de cloud_sql_proxy permettra une bascule transparente vers la standby. Toutefois en cas de perte de la région, la bascule vers le read réplica devra se faire manuellement via une procédure, qui consistera globalement à :
1) Détacher le read-replica de son primaire en échec.
2) Faire un promote sur le réplica pour qu’il devienne primaire
3) S’assurer qu’aucune application ne peut plus de connecter à l’ancien primaire ou standby dans la région initiale, car il n’y a aucun garde-fou contre le split-brain
4) Faire pointer les applications sur le nouveau primaire dans la deuxième région.
5) Potentiellement ré-implémenter une standby régionale dans la deuxième région, et un read réplica dans une troisième région pour se prémunir d’une nouvelle perte de la région 2.
Evidemment tout cela pourra être automatisé via gcloud ou Terraform mais personnellement je ne suis pas un grand fan des solutions qui basculent toutes seules, même on-premise. Il vaut mieux avoir une procédure robuste, que chaque étape soit scriptée mais garder la main sur l’enchaînement me paraît plus rassurant.

Migration on-prem vers Cloud SQL:

Contrairement à Cloud SQL pour MySQL, Cloud SQL pour PostgreSQL ne supporte pas la réplication depuis une source externe, donc l’option de migrer un cluster PostgreSQL on-prem via la réplicaiton est exclu. Il reste la solution d’importer directement un pg_dump dans une instance PaaS mais cela supposera une indisponibilité plus grande et qui sera fonction du volume à manipuler.
Attention à la valeur de temp_file_limit lors de la recréation des indexes. La valeur par défaut pour mon PaaS en 13 est à environ 2Gb alors qu’on-prem il n’y a pas de limitation.

Autre solution, utiliser le Cloud Migration Service mais dont l’étendue des fonctionnalités dépasse largement le scope de cet article.

Bilan :

Lorsque j’avais évalué la première génération de PaaS PostgreSQL sur GCP en 2018, j’avais trouvé pas mal de lacunes, presque rien pour monitorer, une faible surface de configuration.

Le moins qu’on puisse dire c’est que depuis des efforts ont été faits pour réduire la fracture entre les capacités on-prem et les capacités d’un PaaS équivalent: extensions, interfaces, versions, paramètres GUC, tout y passe. Le seul couac qui reste encore c’est de franchir la première marche (la migration vers le PaaS) surtout si l’on a une grande quantité de données à migrer. Il faudra tester l’assistant de migration, peut être dans un prochain épisode !

A+ ~David

Continuez votre lecture sur le blog :

twitterlinkedinmail

David Baffaleuf

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.