Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience

De plus en plus de demandes de ce type sont reçues de la part des clients : « Nous le voulons comme Amazon RDS, mais moins cher » ; "Nous le voulons comme RDS, mais partout, dans n'importe quelle infrastructure." Pour mettre en œuvre une telle solution managée sur Kubernetes, nous avons examiné l'état actuel des opérateurs les plus populaires pour PostgreSQL (Stolon, opérateurs de Crunchy Data et Zalando) et avons fait notre choix.

Cet article est notre expérience tant d’un point de vue théorique (revue des solutions) que d’un point de vue pratique (ce qui a été choisi et ce qui en est ressorti). Mais d'abord, définissons quelles sont les exigences générales pour un remplacement potentiel du RDS...

Qu'est-ce que RDS

Lorsque les gens parlent de RDS, d'après notre expérience, ils font référence à un service de SGBD géré qui :

  1. facile à mettre en place;
  2. a la capacité de travailler avec des instantanés et de les restaurer (de préférence avec le support PITR);
  3. vous permet de créer des topologies maître-esclave ;
  4. a une riche liste d’extensions ;
  5. assure l’audit et la gestion des utilisateurs/accès.

D'une manière générale, les approches pour mettre en œuvre la tâche peuvent être très différentes, mais le chemin avec l'Ansible conditionnel n'est pas proche de nous. (Des collègues de 2GIS sont arrivés à une conclusion similaire à la suite de sa tentative créer un « outil de déploiement rapide du cluster de basculement basé sur Postgres ».)

Ce sont les opérateurs qui constituent l'approche généralement acceptée pour résoudre de tels problèmes dans l'écosystème Kubernetes. Plus en détail à leur sujet en ce qui concerne les bases de données exécutées dans Kubernetes, le directeur technique de Flant a déjà expliqué : distolerdans un de ses rapports.

NB: Pour créer rapidement des opérateurs simples, nous vous recommandons de faire attention à notre utilitaire Open Source opérateur shell. En l'utilisant, vous pouvez le faire sans connaissance de Go, mais de manière plus familière pour les administrateurs système : en Bash, Python, etc.

Il existe plusieurs opérateurs K8 populaires pour PostgreSQL :

  • Stolon;
  • Opérateur PostgreSQL de données croustillantes ;
  • Opérateur Zalando Postgres.

Regardons-les de plus près.

Sélection de l'opérateur

En plus des fonctionnalités importantes déjà mentionnées ci-dessus, nous - en tant qu'ingénieurs d'infrastructure chez Kubernetes - attendions également les éléments suivants de la part des opérateurs :

  • déployer depuis Git et avec Ressources personnalisées;
  • prise en charge de l'anti-affinité des pods ;
  • installer l'affinité de nœud ou le sélecteur de nœud ;
  • définir des tolérances ;
  • disponibilité des capacités de réglage ;
  • des technologies compréhensibles et même des commandes.

Sans entrer dans les détails de chacun des points (demandez dans les commentaires si vous avez encore des questions à leur sujet après avoir lu l'intégralité de l'article), je noterai de manière générale que ces paramètres sont nécessaires à une description plus subtile de la spécialisation des nœuds de cluster dans afin de les commander pour des applications spécifiques. De cette façon, nous pouvons atteindre l’équilibre optimal entre performances et coûts.

Maintenant - aux opérateurs PostgreSQL eux-mêmes.

1. Stolon

stolon de la société italienne Sorint.lab en rapport déjà mentionné était considéré comme une sorte de standard parmi les opérateurs de SGBD. Il s'agit d'un projet assez ancien : sa première version publique a eu lieu en novembre 2015 (!), et le référentiel GitHub compte près de 3000 40 étoiles et plus de XNUMX contributeurs.

En effet, Stolon est un excellent exemple d’architecture réfléchie :

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience
L'appareil de cet opérateur peut être trouvé en détail dans le rapport ou documentation du projet. De manière générale, il suffit de dire qu'il peut faire tout ce qui est décrit : basculement, proxy pour un accès client transparent, sauvegardes... De plus, les proxys fournissent un accès via un seul service de point de terminaison - contrairement aux deux autres solutions évoquées ci-dessous (ils disposent de deux services pour accéder base).

Cependant, Stolon pas de ressources personnalisées, c’est pourquoi il ne peut pas être déployé de manière à ce qu’il soit facile et rapide – « comme des petits pains chauds » – de créer des instances de SGBD dans Kubernetes. La gestion est effectuée via l'utilitaire stolonctl, déploiement - via le graphique Helm, et les graphiques personnalisés sont définis dans ConfigMap.

D’une part, il s’avère que l’opérateur n’est pas vraiment un opérateur (car il n’utilise pas CRD). Mais d’un autre côté, c’est un système flexible qui vous permet de configurer les ressources du K8 comme vous le souhaitez.

En résumé, pour nous personnellement, cela ne semblait pas être la meilleure façon de créer un graphique distinct pour chaque base de données. Nous avons donc commencé à chercher des alternatives.

2. Opérateur PostgreSQL de données croustillantes

Opérateur de Crunchy Data, une jeune startup américaine, semblait être une alternative logique. Son histoire publique commence avec la première version en mars 2017, depuis lors, le référentiel GitHub a reçu un peu moins de 1300 50 étoiles et plus de 1.15 contributeurs. La dernière version de septembre a été testée pour fonctionner avec Kubernetes 1.18-3.11, OpenShift 4.4+ et 1.3+, GKE et VMware Enterprise PKS XNUMX+.

L'architecture Crunchy Data PostgreSQL Operator répond également aux exigences énoncées :

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience

La gestion s'effectue via l'utilitaire pgo, cependant, il génère à son tour des ressources personnalisées pour Kubernetes. Par conséquent, l'opérateur nous a plu en tant qu'utilisateurs potentiels :

  • il y a un contrôle via CRD ;
  • gestion pratique des utilisateurs (également via CRD) ;
  • intégration avec d'autres composants Suite de conteneurs de données croustillantes — une collection spécialisée d'images de conteneurs pour PostgreSQL et d'utilitaires pour travailler avec (y compris pgBackRest, pgAudit, extensions de contrib, etc.).

Cependant, les tentatives de démarrage de l'opérateur de Crunchy Data ont révélé plusieurs problèmes :

  • Il n'y avait aucune possibilité de tolérance - seul nodeSelector est fourni.
  • Les pods créés faisaient partie du déploiement, malgré le fait que nous ayons déployé une application avec état. Contrairement aux StatefulSets, les déploiements ne peuvent pas créer de disques.

Le dernier inconvénient conduit à des moments amusants : sur l'environnement de test, nous avons réussi à exécuter 3 répliques avec un seul disque stockage local, à la suite de quoi l'opérateur a signalé que 3 répliques fonctionnaient (même si ce n'était pas le cas).

Une autre caractéristique de cet opérateur est son intégration prête à l'emploi avec divers systèmes auxiliaires. Par exemple, il est facile d'installer pgAdmin et pgBounce, et dans documentation Grafana et Prometheus préconfigurés sont pris en compte. Dans un récent version 4.5.0-bêta1 noté séparément une meilleure intégration avec le projet pgMoniteur, grâce à quoi l'opérateur propose une visualisation visuelle des métriques PgSQL prête à l'emploi.

Cependant, le choix étrange des ressources générées par Kubernetes nous a conduit à la nécessité de trouver une solution différente.

3. Opérateur Zalando Postgres

Les produits Zalando nous sont connus depuis longtemps : nous avons de l'expérience avec Zalenium et, bien sûr, nous avons essayé patroni est leur solution HA populaire pour PostgreSQL. À propos de l'approche de l'entreprise en matière de création Opérateur PostgreSQL a déclaré à l'antenne l'un de ses auteurs - Alexei Klyukin Postgres-mardi #5et nous avons aimé.

Il s'agit de la solution la plus récente évoquée dans l'article : la première version a eu lieu en août 2018. Cependant, malgré le petit nombre de versions officielles, le projet a parcouru un long chemin, dépassant déjà la popularité de la solution de Crunchy Data avec plus de 1300 70 étoiles sur GitHub et le nombre maximum de contributeurs (XNUMX+).

« Sous le capot » de cet opérateur, des solutions éprouvées sont utilisées :

  • Patroni et Jeu Pour la conduite,
  • WAL-E - pour les sauvegardes,
  • PgBouncer - comme pool de connexions.

Voici comment se présente l’architecture opérateur de Zalando :

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience

L'opérateur est entièrement géré via des ressources personnalisées, crée automatiquement un StatefulSet à partir de conteneurs, qui peut ensuite être personnalisé en ajoutant divers side-cars au pod. Tout cela est un plus non négligeable par rapport à l'opérateur de Crunchy Data.

Puisque nous avons choisi la solution de Zalando parmi les 3 options envisagées, une description plus détaillée de ses capacités sera présentée ci-dessous, immédiatement accompagnée de la pratique d'application.

Entraînez-vous avec Postgres Operator par Zalando

Le déploiement de l'opérateur est très simple : il suffit de télécharger la dernière version depuis GitHub et d'appliquer les fichiers YAML depuis le répertoire manifestes. Alternativement, vous pouvez également utiliser OpérateurHub.

Après l'installation, vous devez prendre soin des paramètres stockage des journaux et des sauvegardes. Cela se fait via ConfigMap postgres-operator dans l'espace de noms où vous définissez l'opérateur. Une fois les référentiels configurés, vous pouvez déployer votre premier cluster PostgreSQL.

Par exemple, notre déploiement standard ressemble à ceci :

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
 name: staging-db
spec:
 numberOfInstances: 3
 patroni:
   synchronous_mode: true
 postgresql:
   version: "12"
 resources:
   limits:
     cpu: 100m
     memory: 1Gi
   requests:
     cpu: 100m
     memory: 1Gi
 sidecars:
 - env:
   - name: DATA_SOURCE_URI
     value: 127.0.0.1:5432
   - name: DATA_SOURCE_PASS
     valueFrom:
       secretKeyRef:
         key: password
         name: postgres.staging-db.credentials
   - name: DATA_SOURCE_USER
     value: postgres
   image: wrouesnel/postgres_exporter
   name: prometheus-exporter
   resources:
     limits:
       cpu: 500m
       memory: 100Mi
     requests:
       cpu: 100m
       memory: 100Mi
 teamId: staging
 volume:
   size: 2Gi

Ce manifeste déploie un cluster de 3 instances avec un side-car du formulaire postgres_exporter, à partir duquel nous collectons les métriques des applications. Comme vous pouvez le constater, tout est très simple, et si vous le souhaitez, vous pouvez créer un nombre littéralement illimité de clusters.

Cela vaut la peine de faire attention panneau Web pour l'administration - postgres-opérateur-ui. Il est fourni avec l'opérateur et vous permet de créer et de supprimer des clusters, ainsi que de travailler avec les sauvegardes effectuées par l'opérateur.

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience
Liste des clusters PostgreSQL

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience
Gestion des sauvegardes

Une autre fonctionnalité intéressante est le support API des équipes. Ce mécanisme crée automatiquement rôles dans PostgreSQL, sur la base de la liste de noms d'utilisateur résultante. L'API permet ensuite de renvoyer une liste d'utilisateurs pour lesquels des rôles sont automatiquement créés.

Problèmes et solutions

Cependant, l’utilisation de l’opérateur a rapidement révélé plusieurs inconvénients importants :

  1. manque de prise en charge de nodeSelector ;
  2. impossibilité de désactiver les sauvegardes ;
  3. lors de l'utilisation de la fonction de création de bases, les privilèges par défaut n'apparaissent pas ;
  4. il arrive parfois qu'il n'y ait pas suffisamment de documentation ou qu'elle soit obsolète.

Heureusement, bon nombre d’entre eux peuvent être résolus. Commençons par la fin - problèmes avec Documentation.

Très probablement, vous constaterez qu'il n'est pas toujours clair comment enregistrer une sauvegarde et comment connecter le compartiment de sauvegarde à l'interface utilisateur de l'opérateur. La documentation en parle en passant, mais la vraie description est dans PR:

  1. vous devez faire un secret ;
  2. passez-le à l'opérateur en paramètre pod_environment_secret_name dans CRD avec les paramètres de l'opérateur ou dans ConfigMap (selon la manière dont vous choisissez d'installer l'opérateur).

Cependant, il s’est avéré que cela n’est pas possible pour le moment. C'est pourquoi nous avons collecté votre version de l'opérateur avec quelques développements tiers supplémentaires. Pour en savoir plus, voir ci-dessous.

Si vous transmettez les paramètres de sauvegarde à l'opérateur, à savoir - wal_s3_bucket et accédez aux clés dans AWS S3, puis il je sauvegarderai tout: non seulement des bases en production, mais aussi en mise en scène. Cela ne nous convenait pas.

Dans la description des paramètres de Spilo, qui est le wrapper Docker de base pour PgSQL lors de l'utilisation de l'opérateur, il s'est avéré que vous pouvez passer un paramètre WAL_S3_BUCKET vide, désactivant ainsi les sauvegardes. De plus, avec une grande joie, j'ai découvert PR prêt, que nous avons immédiatement accepté dans notre fourchette. Maintenant, c'est assez simple d'ajouter enableWALArchiving: false à une ressource de cluster PostgreSQL.

Oui, il était possible de faire différemment en faisant tourner 2 opérateurs : un pour le staging (sans sauvegardes), et le second pour la production. Mais nous avons pu nous en sortir avec un.

Ok, nous avons appris comment transférer l'accès de S3 aux bases de données et les sauvegardes ont commencé à entrer dans le stockage. Comment faire fonctionner les pages de sauvegarde dans l'interface utilisateur de l'opérateur ?

Un bref aperçu des instructions PostgreSQL pour Kubernetes, nos choix et notre expérience

Dans l'interface utilisateur de l'opérateur, vous devrez ajouter 3 variables :

  • SPILO_S3_BACKUP_BUCKET
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

Après cela, la gestion des sauvegardes deviendra disponible, ce qui dans notre cas simplifiera le travail de mise en scène, nous permettant d'y livrer des tranches de production sans scripts supplémentaires.

Un autre avantage est le travail avec l'API Teams et de larges opportunités de création de bases de données et de rôles à l'aide des outils de l'opérateur. Cependant, émergeant les rôles n'avaient pas d'autorisations par défaut. Par conséquent, un utilisateur disposant de droits de lecture ne pouvait pas lire de nouvelles tables.

Pourquoi donc? Même si dans le code il est nécessaire GRANTils ne sont pas toujours appliqués. Il existe 2 méthodes : syncPreparedDatabases и syncDatabases. la syncPreparedDatabases - malgré le fait que dans la section preparedDatabases il est il y a une condition defaultRoles и defaultUsers pour créer des rôles, les droits par défaut ne sont pas appliqués. Nous sommes en train de préparer un patch pour que ces droits soient automatiquement appliqués.

Et le dernier moment des améliorations qui nous concernent - patchA qui ajoute une affinité de nœud au StatefulSet généré. Nos clients préfèrent souvent réduire leurs coûts en utilisant des instances ponctuelles, qui ne valent clairement pas la peine d'héberger des services de bases de données. Ce problème pourrait être résolu grâce à des tolérances, mais la présence de Node Affinity donne plus de confiance.

Qu'est-il arrivé?

Après avoir résolu les problèmes ci-dessus, nous avons intégré l'opérateur Postgres de Zalando dans votre référentiel, où il est collecté avec des correctifs aussi utiles. Et pour plus de commodité, nous avons également collecté Image Docker.

Liste des PR acceptés dans le fork :

Ce serait formidable si la communauté supportait ces PR afin qu'ils arrivent en amont avec la prochaine version de l'opérateur (1.6).

Prime! Histoire de réussite en matière de migration de production

Si vous utilisez Patroni, la production en direct peut être migrée vers l'opérateur avec un temps d'arrêt minimal.

Spilo vous permet de créer des clusters de secours via le stockage S3 avec Wal-Elorsque le journal binaire PgSQL est d'abord stocké dans S3 puis pompé par la réplique. Mais et si tu as aucun utilisé par Wal-E sur des infrastructures anciennes ? La solution à ce problème est déjà il a été suggéré sur le moyeu.

La réplication logique PostgreSQL vient à la rescousse. Cependant, nous n’entrerons pas dans les détails sur la manière de créer des publications et des abonnements, car… notre projet a été un fiasco.

Le fait est que la base de données contenait plusieurs tables chargées contenant des millions de lignes, qui, de plus, étaient constamment reconstituées et supprimées. Abonnement simple с copy_data, lorsque la nouvelle réplique copie tout le contenu du maître, elle ne peut tout simplement pas suivre le maître. La copie de contenu a fonctionné pendant une semaine, mais n'a jamais rattrapé le maître. Au final, cela a aidé à résoudre le problème article collègues d'Avito : vous pouvez transférer des données en utilisant pg_dump. Je vais décrire notre version (légèrement modifiée) de cet algorithme.

L'idée est que vous pouvez créer un abonnement désactivé lié à un emplacement de réplication spécifique, puis corriger le numéro de transaction. Il y avait des répliques pour le travail de production. Ceci est important car la réplique aidera à créer un vidage cohérent et continuera à recevoir les modifications du maître.

Les commandes suivantes décrivant le processus de migration utiliseront la notation suivante pour les hôtes :

  1. maître — serveur source ;
  2. réplique1 - réplique en streaming sur l'ancienne production ;
  3. réplique2 - une nouvelle réplique logique.

Projet de migration

1. Créez un abonnement à toutes les tables du schéma sur l'assistant public bases dbname:

psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"

2. Créez un emplacement de réplication sur le maître :

psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"

3. Arrêtez la réplication sur l'ancienne réplique :

psql -h replica1 -c "select pg_wal_replay_pause();"

4. Obtenez le numéro de transaction auprès du maître :

psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"

5. Videz l'ancienne réplique. Nous le ferons dans plusieurs fils de discussion, ce qui contribuera à accélérer le processus :

pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname

6. Téléchargez le dump sur le nouveau serveur :

pg_restore -h replica2 -F d -j 8 -d dbname dump/

7. Après avoir téléchargé le dump, vous pouvez démarrer la réplication sur la réplique en streaming :

psql -h replica1 -c "select pg_wal_replay_resume();"

7. Créez un abonnement sur une nouvelle réplique logique :

psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"

8. Obtenez oid abonnements :

psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"

9. Disons qu'il a été reçu oid=1000. Appliquons le numéro de transaction à l'abonnement :

psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"

10. Commençons la réplication :

psql -h replica2 -d dbname -c "alter subscription oldprod enable;"

11. Vérifiez l'état de l'abonnement, la réplication devrait fonctionner :

psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"
psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"

12. Une fois la réplication démarrée et les bases de données synchronisées, vous pouvez basculer.

13. Après avoir désactivé la réplication, vous devez corriger les séquences. C'est bien décrit dans l'article sur wiki.postgresql.org.

Grâce à ce plan, le basculement s’est déroulé dans des délais minimes.

Conclusion

Les opérateurs Kubernetes permettent de simplifier diverses actions en les réduisant à la création de ressources K8s. Cependant, après avoir réalisé une automatisation remarquable grâce à leur aide, il convient de rappeler que cela peut également apporter un certain nombre de nuances inattendues, alors choisissez judicieusement vos opérateurs.

Après avoir examiné les trois opérateurs Kubernetes les plus populaires pour PostgreSQL, nous avons choisi le projet de Zalando. Et nous avons dû surmonter quelques difficultés, mais le résultat était vraiment satisfaisant, nous prévoyons donc d'étendre cette expérience à d'autres installations de PgSQL. Si vous avez de l'expérience avec des solutions similaires, nous serons heureux de voir les détails dans les commentaires !

PS

A lire aussi sur notre blog :

Source: habr.com

Ajouter un commentaire