web-dev-qa-db-fra.com

Gestion des migrations de base de données sur le cluster Kubernetes

J'ai une application basée sur Kubernetes consistant en plusieurs services (et pods) gérés avec un graphique de barre.

Postgres est utilisé comme base de données pour tous les services.

Lorsque l'application est mise à niveau vers une version plus récente, j'exécute un script de migration de base de données via initContainers.

Le problème se produit lorsque les scripts de migration nécessitent un accès exclusif à la base de données (toutes les autres connexions doivent être terminées), sinon le script est bloqué.

La solution idéale serait d’arrêter tous les pods, d’effectuer la migration et de les recréer. Mais je ne sais pas comment y parvenir correctement avec Kubernetes.

Tnx

3
Miro

La solution idéale serait d’arrêter tous les pods, d’effectuer la migration et de Les recréer. Mais je ne sais pas comment y parvenir correctement avec Kubernetes.

Dans l'un des commentaires, je vois que vous utilisez Helm. J'aimerais donc proposer une solution utilisant les crochets de Helm:

Helm fournit un mécanisme de raccordement permettant aux développeurs de graphiques d'intervenir À certains moments du cycle de vie d'une publication. Par exemple, vous pouvez utiliser les crochets Pour:

  • Chargez un ConfigMap ou un secret lors de l’installation avant que tous les autres graphiques ne soient chargés. 

  • Exécutez un travail pour sauvegarder une base de données avant d'installer un nouveau graphique , Puis exécutez un deuxième travail après la mise à niveau afin de restaurer les données. 

  • Exécutez un Job avant de supprimer une version pour supprimer gracieusement un service Avant de le supprimer. 

https://github.com/kubernetes/helm/blob/master/docs/charts_hooks.md

Vous pouvez créer un package pour votre migration sous la forme k8s Job et utiliser le pointeur pre-install ou pre-upgrade pour exécuter le travail. Ces points d'ancrage sont exécutés après le rendu des modèles, mais avant la création de nouvelles ressources dans Kubernetes. Ainsi, vos migrations seront exécutées avant le déploiement de vos pods. 

Pour supprimer les déploiements avant d'exécuter vos migrations, créez un deuxième hook de pré-installation/pré-mise à niveau avec un helm.sh/hook-weight inférieur qui supprime les déploiements cibles:

apiVersion: batch/v1
kind: Job
metadata:
  name: "pre-upgrade-hook1"
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-1"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "pre-upgrade-hook1"
    spec:
      restartPolicy: Never
      serviceAccountName: "<an SA with delete RBAC permissions>"
      containers:
      - name: kubectl
        image: "lachlanevenson/k8s-kubectl:latest"
        command: ["delete","deployment","deploy1","deploy2"]

Le poids de crochet inférieur garantit que ce travail est exécuté avant le travail de migration. Cela assurera la série d'événements suivante:

  1. Vous exécutez helm upgrade
  2. Le crochet de barre avec le plus bas poids de crochet court et supprime les déploiements pertinents
  3. Le deuxième crochet exécute et exécute vos migrations
  4. Votre graphique s’installera avec de nouveaux déploiements, pods, etc.

Assurez-vous simplement de conserver tous les déploiements pertinents dans le même graphique.

5
ericstaples

Du point de vue de l’automatisation/orchestration, j’ai le sentiment que de tels problèmes doivent être résolus avec des opérateurs, à l’aide de la version récemment publiée de l’opérateur:

https://github.com/operator-framework

L'idée est qu'il y aurait un opérateur Postgres Migrations - qui, à ma connaissance, n'existe pas encore - et qui resterait inactif dans l'attente d'une définition de ressource personnalisée décrivant la migration à publier dans le cluster/espace de noms. 

L'opérateur se réveillerait, comprendrait les implications de la migration envisagée, effectuerait une analyse sur le cluster pour élaborer un plan de migration, puis suivrait les étapes décrites. 

  • mettre l'application en mode de maintenance visible par l'utilisateur
  • enlever les cosses existantes
  • lancer la migration
  • vérifier
  • recréer les pods d'application
  • tester
  • sortir l'application du mode maintenance

Cela ne vous aide pas maintenant, cependant.

1
Jonah Benton

La solution idéale serait d’arrêter tous les pods, d’effectuer la migration et de Les recréer. Mais je ne sais pas comment y parvenir correctement avec Kubernetes.

Cela dépend en grande partie de votre approche, en particulier de vos outils CI/CD. Vous pouvez appliquer plusieurs stratégies, mais à titre d’exemple, en supposant que vous disposiez d’un pipeline Gitlab (Jenkins pourrait faire de même, la terminologie est différente, etc.), voici les étapes:

  • Faites les étapes suivantes dans gitlab-ci.yaml:
    • Build (où vous créez toutes les images nécessaires et préparez les migrations avant tout déploiement)
    • Arrêtez tout actifs affectés - déploiement, services, statefulsets (cela peut être fait comme un simple kubectl delete -f all_required_assets.yaml, où vous avez défini toutes les ressources que vous voulez arrêter complètement. Vous pouvez définir la grâce Vous devez également noter que pour arrêter les pods, vous devez supprimer leur ressource de création de niveau supérieur, qu’il s’agisse du pod, du déploiement, du contrôleur de réplication ou de l’état pour les arrêter. complètement, pas simplement redémarrer)
    • Migrate implémenté sous forme de tâche ou de pod gérant les migrations avec une base de données (par exemple, kubectl create -f migrate_job.yaml). Travail préférable pour le suivi des erreurs une fois le travail terminé.
    • Start all assets (même fichier manifeste avec les définitions de ressources concernées que pour l’étape d’arrêt, disons, kubectl create -f all_required_assets.yaml, et toutes les ressources de démarrage/arrêt sont gérées par un seul fichier. Si l’ordre de démarrage est important pour quelle que soit la raison, un fichier séparé est requis, mais avec des considérations minutieuses, un fichier devrait suffire dans la plupart des scénarios)

Ce même principe peut également être appliqué à d'autres outils d'orchestration/de déploiement, et vous pouvez même créer un simple script pour exécuter ces commandes kubectl directement en une fois si la précédente a abouti.

0
Const