Comment nous, chez TsIAN, avons dompté des téraoctets de journaux



Bonjour à tous, je m'appelle Alexander, je travaille comme ingénieur au CIAN et je suis engagé dans l'administration système et l'automatisation des processus d'infrastructure. Dans les commentaires d'un des articles précédents, on nous a demandé de dire où nous obtenons 4 To de journaux par jour et ce que nous en faisons. Oui, nous avons beaucoup de journaux et un cluster d'infrastructure distinct a été créé pour les traiter, ce qui nous permet de résoudre rapidement les problèmes. Dans cet article, je parlerai de la façon dont nous l'avons adapté au cours de l'année pour travailler avec un flux de données sans cesse croissant.

Par où avons-nous commencé




Au cours des dernières années, la charge sur cian.ru a augmenté très rapidement et, au troisième trimestre de 2018, le trafic de ressources a atteint 11,2 millions d'utilisateurs uniques par mois. À ce moment, à des moments critiques, nous avons perdu jusqu'à 40% des journaux, à cause desquels nous ne pouvions pas traiter rapidement les incidents et avons consacré beaucoup de temps et d'efforts à les résoudre. Souvent, nous ne pouvions pas trouver la cause du problème et il est réapparu après un certain temps. C'était l'enfer avec lequel tu devais faire quelque chose.

À cette époque, nous utilisions un cluster de 10 nœuds de données avec ElasticSearch version 5.5.2 avec des paramètres d'index typiques pour stocker les journaux. Il a été introduit il y a plus d'un an comme une solution populaire et abordable: alors le flux de journaux n'était pas si gros, il n'était pas logique de proposer des configurations non standard.

Logstash sur différents ports a fourni le traitement des journaux entrants sur cinq coordinateurs ElasticSearch. Un indice, quelle que soit sa taille, comprenait cinq fragments. Une rotation horaire et quotidienne a été organisée, en conséquence, environ 100 nouveaux fragments sont apparus dans le cluster toutes les heures. Bien qu'il n'y ait pas beaucoup de journaux, le cluster a réussi et personne n'a attiré l'attention sur ses paramètres.

Problèmes de croissance


Le volume des journaux générés a augmenté très rapidement, car deux processus se chevauchaient. D'une part, il y avait de plus en plus d'utilisateurs du service. D'autre part, nous avons commencé à passer activement à l'architecture de microservices, en sciant nos anciens monolithes en C # et Python. Plusieurs dizaines de nouveaux microservices qui ont remplacé des parties du monolithe ont généré beaucoup plus de journaux pour le cluster d'infrastructure.

C'est la mise à l'échelle qui nous a amenés au fait que le cluster est devenu pratiquement incontrôlable. Lorsque les journaux ont commencé à arriver à une vitesse de 20 000 messages par seconde, une rotation inutile fréquente a augmenté le nombre de fragments à 6 000, et un nœud représentait plus de 600 fragments.

Cela a entraîné des problèmes d'allocation de RAM et lorsqu'un nœud est tombé, le déplacement simultané de tous les fragments a commencé, multipliant le trafic et chargeant les nœuds restants, ce qui rendait presque impossible l'écriture de données dans le cluster. Et pendant cette période, nous nous sommes retrouvés sans journaux. Et avec un problème de serveur, nous avons en principe perdu 1/10 du cluster. Un grand nombre de petits index a ajouté de la complexité.

Sans journaux, nous ne comprenions pas les causes de l'incident et pouvions à nouveau tôt ou tard monter sur le même râteau, mais dans l'idéologie de notre équipe, c'était inacceptable, car tous les mécanismes de travail que nous avions étaient affûtés exactement à l'opposé - ne répétons jamais les mêmes problèmes. Pour ce faire, nous avions besoin d'un volume complet de journaux et de leur livraison en temps quasi réel, car une équipe d'ingénieurs de service surveillait les alertes non seulement à partir des métriques, mais également à partir des journaux. Pour comprendre l'étendue du problème - à cette époque, le volume total de journaux était d'environ 2 To par jour.

Nous nous sommes fixé un objectif - éliminer complètement la perte de journaux et réduire le temps de leur livraison au cluster ELK à un maximum de 15 minutes en cas de force majeure (nous nous sommes basés sur ce chiffre à l'avenir comme un KPI interne).

Nouveau mécanisme de rotation et nœuds chauds et chauds




Nous avons commencé la transformation du cluster en mettant à jour la version d'ElasticSearch de 5.5.2 à 6.4.3. Encore une fois, un cluster de la version 5 nous est parvenu, et nous avons décidé de le rembourser et de le mettre à jour complètement - il n'y a toujours pas de journaux. Nous avons donc effectué cette transition en quelques heures seulement.

La transformation la plus ambitieuse à ce stade a été l'introduction de trois nœuds avec le coordinateur comme tampon intermédiaire Apache Kafka. Le courtier de messages nous a évité de perdre des journaux lors de problèmes avec ElasticSearch. Dans le même temps, nous avons ajouté 2 nœuds au cluster et basculé vers une architecture chaude-chaude avec trois nœuds «chauds» disposés dans différents racks du centre de données. Nous leur avons redirigé des journaux qui ne devraient en aucun cas être perdus - nginx, ainsi que des journaux d'erreurs d'application. Les journaux mineurs - débogage, avertissement, etc., sont allés à d'autres nœuds et, après 24 heures, les journaux «importants» ont quitté les nœuds «chauds».

Afin de ne pas augmenter le nombre de petits index, nous sommes passés de la rotation temporelle au mécanisme de retournement. Il y avait beaucoup d'informations sur les forums que la rotation par taille d'index est très peu fiable, nous avons donc décidé d'utiliser la rotation par le nombre de documents dans l'index. Nous avons analysé chaque index et enregistré le nombre de documents après lesquels la rotation devrait fonctionner. Ainsi, nous avons atteint la taille optimale du fragment - pas plus de 50 Go.

Optimisation de cluster




Cependant, nous ne nous sommes pas complètement débarrassés des problèmes. Malheureusement, de petits indices sont apparus tout de même: ils n'ont pas atteint le volume défini, n'ont pas tourné et ont été supprimés par un nettoyage global des indices de plus de trois jours, car nous avons supprimé la rotation par date. Cela a entraîné une perte de données du fait que l'index du cluster a complètement disparu et une tentative d'écriture dans un index inexistant a brisé la logique du conservateur que nous avons utilisée pour le contrôle. L'alias pour l'enregistrement a été converti en index et a rompu la logique du rollover, provoquant une croissance incontrôlée de certains indices à 600 Go.

Par exemple, pour configurer la rotation:

urator-elk-rollover.yaml --- actions:   1:     action: rollover     options:       name: "nginx_write"       conditions:         max_docs: 100000000   2:     action: rollover     options:       name: "python_error_write"       conditions:         max_docs: 10000000 


En l'absence d'alias de survol, une erreur s'est produite:

 ERROR   alias "nginx_write" not found. ERROR   Failed to complete action: rollover. <type 'exceptions.ValueError'>: Unable to perform index rollover with alias "nginx_write". 


Nous avons laissé la solution à ce problème pour la prochaine itération et avons pris une autre question: nous sommes passés à la logique de Logstash, qui gère les journaux entrants (supprimant les informations inutiles et les enrichissant). Nous l'avons placé dans docker, que nous lançons via docker-compose, et au même endroit, nous avons placé logstash-exporter, qui fournit des mesures à Prometheus pour la surveillance opérationnelle du flux de journaux. Nous nous sommes donc donné l'opportunité de modifier en douceur le nombre d'instances de logstash responsables du traitement de chaque type de journal.

Pendant que nous améliorions le cluster, le trafic cian.ru est passé à 12,8 millions d'utilisateurs uniques par mois. En conséquence, il s'est avéré que nos conversions n'ont pas suivi un peu les changements sur la production, et nous étions confrontés au fait que les nœuds "chauds" ne pouvaient pas faire face à la charge et ralentissaient la livraison complète des journaux. Nous avons reçu les données "à chaud" sans échecs, mais nous avons dû intervenir dans la livraison du reste et faire un rollover manuel afin de répartir uniformément les indices.

Dans le même temps, la mise à l'échelle et la modification des paramètres des instances de logstash dans le cluster étaient compliquées par le fait qu'il s'agissait d'un docker-compose local et que toutes les actions étaient effectuées à la main (pour ajouter de nouvelles extrémités, vous deviez passer par tous les serveurs avec vos mains et faire docker-composer up -d partout).

Redistribution des journaux


En septembre de cette année, nous avons continué à voir le monolithe, la charge sur le cluster a augmenté et le flux de journaux approchait 30 000 messages par seconde.



Nous avons commencé la prochaine itération avec la mise à jour du fer. Nous sommes passés de cinq coordinateurs à trois, avons remplacé les nœuds de données et avons gagné en termes d'argent et de volume de stockage. Pour les nœuds, nous utilisons deux configurations:

  • Pour les nĹ“uds actifs: E3-1270 v6 / SSD 960 Go / 32 Go x 3 x 2 (3 pour Hot1 et 3 pour Hot2).
  • Pour les nĹ“uds chauds: E3-1230 v6 / SSD 4 To / 32 Go x 4.

À cette itération, nous avons retiré l'index avec les journaux d'accès au microservice, qui prend autant d'espace que les journaux nginx frontaux, dans le deuxième groupe de trois nœuds actifs. Nous stockons maintenant les données sur des nœuds chauds pendant 20 heures, puis les transférons pour les réchauffer dans d'autres journaux.

Nous avons résolu le problème de la disparition des petits indices en reconfigurant leur rotation. Les index sont maintenant tournés de toute façon toutes les 23 heures, même s'il y a peu de données. Cela a légèrement augmenté le nombre de fragments (ils sont devenus environ 800), mais du point de vue des performances du cluster, cela est tolérable.

En conséquence, six nœuds «chauds» et seulement quatre «chauds» se sont révélés dans le cluster. Cela entraîne un léger retard dans les demandes sur de longs intervalles de temps, mais l'augmentation du nombre de nœuds à l'avenir résoudra ce problème.

Dans cette itération, le problème de l'absence de mise à l'échelle semi-automatique a également été résolu. Pour ce faire, nous avons déployé une grappe Nomad d'infrastructure - similaire à ce que nous avons déjà déployé pour la production. Bien que le nombre de Logstash ne change pas automatiquement en fonction de la charge, mais nous y arriverons.



Plans futurs


La configuration implémentée évolue bien et maintenant nous stockons 13,3 To de données - tous les journaux en 4 jours, ce qui est nécessaire pour l'analyse d'urgence des alertes. Nous convertissons une partie des journaux en métriques, que nous ajoutons à Graphite. Pour faciliter le travail des ingénieurs, nous avons des métriques pour le cluster d'infrastructure et des scripts pour la correction semi-automatique des problèmes typiques. Après avoir augmenté le nombre de nœuds de données, ce qui est prévu pour l'année prochaine, nous passerons au stockage de données de 4 à 7 jours. Ce sera suffisant pour le travail opérationnel, car nous essayons toujours d'enquêter sur les incidents dès que possible, et les données de télémétrie sont disponibles pour des enquêtes à long terme.

En octobre 2019, le trafic cian.ru est passé à 15,3 millions d'utilisateurs uniques par mois. Il s'agissait d'un test sérieux de la solution architecturale pour la livraison des journaux.

Nous nous préparons maintenant à mettre à niveau ElasticSearch vers la version 7. Cependant, pour cela, nous devrons mettre à jour le mappage de nombreux index dans ElasticSearch, car ils sont passés de la version 5.5 et ont été déclarés obsolètes dans la version 6 (ils n'existent tout simplement pas dans la version 7). Et cela signifie que dans le processus de mise à jour, il y aura certainement un cas de force majeure qui nous laissera sans journaux pour le moment. Des 7 versions, nous attendons avec impatience Kibana avec une interface améliorée et de nouveaux filtres.

Nous avons atteint l'objectif principal: nous avons cessé de perdre des journaux et réduit le temps d'arrêt du cluster d'infrastructure de 2 à 3 gouttes par semaine à quelques heures de service par mois. Tout ce travail sur la production est presque invisible. Cependant, maintenant nous pouvons déterminer avec précision ce qui se passe avec notre service, nous pouvons le faire rapidement en mode silencieux et ne pas craindre que les journaux soient perdus. En général, nous sommes satisfaits, heureux et nous nous préparons à de nouveaux exploits, dont nous parlerons plus tard.

Source: https://habr.com/ru/post/fr478564/


All Articles