Ajoutez simplement du sel

Comment nous avons migré plus de 700 serveurs vers Salt



Pendant longtemps, nous nous sommes contentés d'une configuration complexe et encombrante avec 2 référentiels Git, où une partie des données est stockée dans MySQL, et l'autre partie est Puppet 3.8. Mais nos besoins ont progressivement augmenté, le nombre de services a augmenté et les performances de configuration ont diminué. Ensuite, nous nous sommes donné pour mission d'améliorer la configuration, d'optimiser toutes les données et outils disponibles.



Notre équipe a sélectionné une configuration adaptée pour elle-même en 3 étapes. Nous partageons notre expérience de l'optimisation Salt, comment appliquer et personnaliser sans effort supplémentaire.



Note: Sur Habré, nous avons trouvé de super articles de nos confrères, nous ne nous attarderons donc pas sur les sujets déjà abordés. Nous vous recommandons vivement de lire:



Ce qui est bon à propos de SaltStack et quelles tâches peuvent être résolues avec - article desécurité, Technologies positives.



Installation, lancement, premières commandes et familiarité avec les fonctions - article de l'auteurzerghack007...


Salt est un système de gestion de configuration et d'exécution à distance. Un framework d'infrastructure open source écrit en Python.





Pourquoi du sel?



Salt, Ansible, Puppet et Chef sont des options décentes pour choisir un outil de gestion de la configuration. Nous avons choisi Salt parce que nous avons priorisé les avantages suivants:



  • ModularitĂ©, disponibilitĂ© de l'API dans la version gratuite, contrairement Ă  Ansible.
  • Python, ce qui signifie que vous pouvez facilement comprendre n'importe quel composant et Ă©crire vous-mĂŞme la fonctionnalitĂ© manquante.
  • Haute performance et Ă©volutivitĂ©. L'assistant Ă©tablit une connexion permanente avec les sbires Ă  l'aide de ZeroMQ pour des performances maximales.
  • Les rĂ©acteurs sont une sorte de dĂ©clencheurs qui sont exĂ©cutĂ©s lorsqu'un certain message apparaĂ®t dans le bus de messages.
  • Orchestration - la capacitĂ© de crĂ©er des relations complexes et d'exĂ©cuter des actions dans une sĂ©quence spĂ©cifique, par exemple, configurer d'abord l'Ă©quilibreur de charge, puis le cluster de serveurs Web.
  • Puppet et Chef sont Ă©crits en Ruby. Notre Ă©quipe n'a pas de spĂ©cialiste compĂ©tent pour travailler avec ce langage de programmation, mais Python est bien connu et est souvent utilisĂ© par nous.
  • Pour les Ă©quipes qui utilisaient auparavant Ansible, la possibilitĂ© d'utiliser des playbooks Ansible sera pertinente. Cela vous permettra de migrer vers Salt sans douleur.


Remarque:



nous utilisons Salt depuis près de deux ans maintenant et nous vous recommandons de faire attention aux points suivants:



  • Salt, , . , . , SaltStack .
  • SaltStack . , . : , . , cmd.run file.managed, .


Grafana .

, , , .



. .



Étant donné:



Notre configuration initiale est donc:



  • 2 rĂ©fĂ©rentiels Git (l'un pour les ingĂ©nieurs et les administrateurs; l'autre pour les serveurs hautement critiques, disponible uniquement pour les administrateurs);
  • un morceau de donnĂ©es dans MySQL;
  • l'autre partie - dans Puppet 3.8 (exagĂ©rĂ© avec l'hĂ©ritage, pratiquement pas en utilisant Hiera - stockage clĂ©-valeur).


Objectif: migrer le système de gestion de la configuration vers Salt, augmenter ses performances, rendre la gestion des serveurs plus pratique et plus compréhensible.



Solution:



tout d'abord, nous avons commencé à migrer la configuration d'origine vers Salt à partir de serveurs de service non critiques séparés, tout en éliminant le code obsolète.



Ensuite, nous avons préparé la configuration des serveurs VDS. Dans notre cas, il s'agit de profils pour les serveurs de service, les serveurs de développement et les serveurs clients.



Le principal problème lors du passage de Puppet à Salt était un système d'exploitation obsolète (en 2018, il y avait Ubuntu 12.04 et 14.04). Avant la migration, il était nécessaire de mettre à jour le système d'exploitation et de ne pas affecter le fonctionnement du service / serveur. Sinon, tout était assez simple: les collègues se sont progressivement impliqués dans le processus.



Parmi les principaux avantages, l'équipe a noté, par exemple, une syntaxe plus compréhensible. Mes collègues et moi avons accepté d'utiliser les conseils de Salt Best Practices , mais nous les avons complétés par nos propres recommandations qui reflètent nos particularités.



L'équipe a également évalué les méthodes de livraison de la configuration: push (le maître "pousse") et pull (le serviteur "tire"). Le mode Masterless est utile si vous avez besoin de tester quelque chose de simple et de ne pas gâcher le dépôt Git. L'exécution d'un minion en mode sans maître vous permet d'utiliser la gestion de la configuration Salt sur une machine sans avoir à accéder au maître Salt sur une autre machine. La configuration est complètement locale.



Jusqu'à 300 minions avec une telle solution, nous n'avons eu aucun problème sérieux. La configuration principale à ce moment-là est un VDS avec 6 cœurs et 4 Go de mémoire.



Cependant, dès que le nombre de serviteurs a atteint 300, la charge moyenne (charge moyenne du système) a augmenté à 3,5-4, et le système a beaucoup ralenti. Auparavant, la commande state.apply prenait 30 à 40 secondes, mais maintenant cela prend 18 minutes!



Un tel résultat, bien entendu, nous était inacceptable. De plus, des experts d'autres entreprises ont écrit sur des histoires à succès avec 10 000 sbires. Nous avons commencé à comprendre quel était le problème.



Les observations du capitaine n'ont pas donné une réponse claire à la question. Il y avait suffisamment de mémoire, le réseau n'était pas chargé, le disque était utilisé à 10%. Nous pensions que GitLab était à blâmer, mais ce n'était pas non plus à blâmer.



Il semble que la puissance du processeur ne soit pas suffisante: lors de l'ajout de cœurs, la moyenne de charge a naturellement chuté et la commande state.apply a été exécutée, bien que plus rapidement, environ 5-7 minutes, mais pas aussi vite que nous le souhaitions.



L'ajout de travailleurs a partiellement résolu le problème, mais a considérablement augmenté la consommation de mémoire.



Ensuite, nous avons décidé d'optimiser la configuration elle-même.



Étape 1



Les piliers étant un stockage sécurisé, l'accès au stockage est associé aux opérations de chiffrement et vous devez payer pour y accéder avec du temps CPU. Nous avons donc réduit le nombre d'appels aux piliers: les mêmes données n'ont été prises qu'une seule fois; s'ils étaient nécessaires ailleurs, ils étaient accessibles via l'importation ({% - à partir du profil d'importation 'defaults / pillar.sls'%}).



La configuration est appliquée une fois par heure, l'heure d'exécution est choisie au hasard. Après avoir analysé le nombre de tâches effectuées par minute et leur répartition uniforme sur une heure, nous avons découvert: au début de l'heure, de la 1ère à la 8e minute, la plupart des tâches passent, et à la 34e minute, aucune! Nous avons écrit un coureur qui a parcouru tous les sbires une fois par semaine et réparti uniformément les tâches. Grâce à cette approche, la charge est devenue uniforme, sans sauts.



Il y avait des suggestions pour passer à un serveur de fer, mais à ce moment-là, il n'était pas là et ... nous avons résolu le problème d'une manière différente. Nous avons ajouté de la mémoire et y avons placé tout le cache. En regardant le tableau de bord Grafana, nous avons d'abord pensé que le salt-master ne fonctionnait pas, puisque la moyenne de charge est tombée à 0,5. Nous avons vérifié le temps d'exécution de state.apply et avons également été surpris - 20-30 secondes. C'était une victoire!



Étape 2



Six mois plus tard, le nombre de serviteurs est passé à 650, et… les performances se sont à nouveau dégradées. Le graphique Charge moyenne augmente avec le nombre de serviteurs.



La première chose que nous avons faite: activer le cache de pillar, définir la durée de vie à 1 heure (pillar_cache_ttl: 3600). Nous avons réalisé que maintenant nos commits ne seraient pas instantanés et devraient attendre que le maître mette à jour le cache.



Comme nous ne voulions pas du tout attendre, nous avons créé des hooks dans GitLab. Cela a permis dans le commit d'indiquer pour quel serviteur vous devez mettre à jour le cache. Le cache de Pillars a considérablement réduit la charge et réduit le temps d'application de la configuration.



Étape 3



Nous avons médité un peu sur les logs de débogage et émis une hypothèse: et si nous augmentions l'intervalle de mise à jour du backend de fichiers et du cache de la liste de fichiers (gitfs_update_interval, fileserver_list_cache_time)? La mise à jour avait lieu une fois par minute et prenait parfois jusqu'à 15 secondes. En augmentant l'intervalle de mise à jour de 1 minute à 10 minutes, nous avons encore gagné en vitesse! L'indicateur LA est passé de 1,5 à 0,5. Le temps d'application de la configuration a été réduit aux 20 secondes souhaitées. Malgré le fait que LA a de nouveau augmenté après un certain temps, la vitesse d'exécution de state.apply n'a pas changé de manière significative. Une mise à jour forcée de ces caches a été ajoutée aux hooks sur git push.





Nous avons ajouté des analyses à Elasticsearch: nous avons réécrit le elasticsearch_return intégré et nous pouvons maintenant surveiller les résultats de state.apply (temps d'exécution moyen, état le plus long et nombre d'erreurs).



résultats



Nous sommes maintenant entièrement satisfaits des performances de Salt. Il est prévu de doubler le nombre de serviteurs. Comment notre maître va faire face à une telle charge est encore difficile à dire. Peut-être allons-nous passer à la mise à l'échelle horizontale ou trouver un paramètre magique. Le temps nous le dira!



Si vous utilisez gitfs comme backend, donnez-lui un cinq! Il y a de fortes chances que vous traversiez les mêmes problèmes que nous. Nous serons donc heureux de discuter de ce sujet dans les commentaires.



Ressources utiles






All Articles