DevOps et Chaos: livraison de logiciels dans un monde décentralisé

Le fondateur et directeur d'Otomato Software, l'un des initiateurs et instructeurs de la première certification DevOps d'Israël, Anton Weiss, a parlé de la théorie du chaos et des principes de base de l'ingénierie chaotique à DevOpsDays Moscou l'année dernière, et a également expliqué comment l'organisation DevOps idéale des futurs travaux.

Nous avons préparé une version texte du rapport.



Bonjour

DevOpsDays à Moscou pour la deuxième année consécutive, je suis la deuxième fois sur cette scène, beaucoup d'entre vous sont la deuxième fois dans cette salle. Qu'est-ce que cela signifie? Cela signifie que le mouvement DevOps en Russie se développe, se multiplie et, plus important encore, cela signifie qu'il est temps de parler de ce qu'est le DevOps en 2018.

Levez la main ceux qui pensent qu'en 2018 DevOps est déjà un métier? Il y en a. Y a-t-il des ingénieurs DevOps dans la salle qui ont «Ingénieur DevOps» écrit dans la description de travail? Y a-t-il des responsables DevOps dans la salle? Il n'y en a pas. Architectes DevOps? Non non plus. Pas assez. Quoi, vraiment, personne n'a écrit qu'il était ingénieur DevOps?

Donc, la plupart d'entre vous pensent que c'est anti-modèle? Quelle ne devrait pas être une telle profession? Nous pouvons penser à tout, mais pour l'instant, nous pensons que l'industrie avance solennellement aux sons de la pipe DevOps.

Qui a entendu parler d'un nouveau sujet appelé DevDevOps? Il s'agit d'une nouvelle technique qui permet une coopération efficace entre les développeurs et les développeurs. Et pas si nouveau. À en juger par Twitter, il y a 4 ans, ils ont commencé à en parler. Et l'intérêt pour cela continue de croître, c'est-à-dire qu'il y a un problème. Le problème doit être résolu.



Nous sommes des gens créatifs, alors ne vous calmez pas. Nous disons: DevOps n'est pas un mot assez complet; il n'y a toujours pas assez de toutes sortes d'éléments différents et intéressants. Et nous allons dans nos laboratoires secrets et commençons à produire des mutations intéressantes: DevTestOps, GitOps, DevSecOps, BizDevOps, ProdOps.



La logique est le fer, non? Notre système de livraison n'est pas fonctionnel, nos systèmes sont instables et les utilisateurs sont insatisfaits, nous n'avons pas le temps de déployer le logiciel à temps, nous ne correspondons pas au budget. Comment allons-nous résoudre tout cela? Nous trouverons un nouveau mot! Il se terminera par Ops et le problème est résolu.

J'appelle donc cette approche - "Ops, et le problème est résolu."

Tout cela s'estompe à l'arrière-plan si nous nous rappelons pourquoi nous avons proposé tout cela. Nous avons mis au point tous ces DevOps pour rendre la livraison de logiciels et notre propre travail dans ce processus aussi dégagés, indolores, efficaces et, surtout, agréables.

DevOps est né de la douleur. Et nous sommes fatigués de souffrir. Et pour que cela se produise, nous nous appuyons sur des pratiques à feuilles persistantes: une collaboration efficace, des pratiques de flux et, surtout, une pensée systémique, car sans cela, aucun DevOps ne fonctionne.

Qu'est-ce qu'un système?


Et si nous parlons déjà de pensée systémique, rappelons-nous ce qu'est un système.



Si vous êtes un pirate informatique révolutionnaire, alors pour vous, le système est un mal évident. C'est un nuage qui plane sur vous et vous fait faire ce que vous ne voulez pas faire.



Du point de vue de la pensée systémique, un système est un tout composé de parties. En ce sens, chacun de nous est un système. Les organisations pour lesquelles nous travaillons sont des systèmes. Et ce que nous construisons, c'est ce qu'on appelle - le système.

Tout cela fait partie d'un grand système sociotechnologique. Et seulement si nous comprenons comment ce système sociotechnologique fonctionne ensemble, alors seulement nous pourrons vraiment optimiser quelque chose dans ce domaine.

Du point de vue de la pensée systémique, un système a diverses propriétés intéressantes. Premièrement, il se compose de pièces, ce qui signifie que son comportement dépend du comportement des pièces. De plus, toutes ses parties sont également interdépendantes. Il s'avère que plus le système comporte de pièces, plus il est difficile de comprendre ou de prédire son comportement.

En termes de comportement, il y a un autre fait intéressant. Le système peut faire quelque chose qu'aucune de ses parties individuelles ne peut faire.

Comme l'a dit le Dr Russell Akoff (l'un des fondateurs de la pensée systémique), cela est assez facile à prouver à l'aide d'une expérience de pensée. Par exemple, qui dans l'auditoire peut écrire du code? Beaucoup de mains, et c'est normal, car c'est une des exigences de base de notre métier. Pouvez-vous écrire et vos mains peuvent écrire du code séparément de vous? Il y a des gens qui disent: "Mes mains n'écrivent pas de code, mon cerveau écrit du code." Le cerveau peut-il écrire du code séparément de vous? Eh bien, très probablement pas.

Le cerveau est une machine incroyable, 10% d'entre nous ne savent pas comment cela fonctionne, mais il ne peut pas fonctionner séparément du système qu'est notre corps. Et c'est facile à prouver: ouvrez votre boîte de crâne, sortez votre cerveau, mettez-le devant l'ordinateur, laissez-le essayer d'écrire quelque chose de simple. "Bonjour, monde" en Python, par exemple.

Si un système peut faire quelque chose qu'aucune de ses parties ne peut faire individuellement, cela signifie que son comportement n'est pas déterminé par le comportement de ses parties. Et ensuite, par quoi est-il déterminé? Elle est déterminée par l'interaction entre ces parties. Et en conséquence, plus il y a de parties, plus l'interaction est difficile, plus il est difficile de comprendre et de prédire le comportement du système. Et cela rend un tel système chaotique, car tout changement, le plus petit, invisible à l'œil dans n'importe quelle partie du système peut conduire à des résultats complètement imprévisibles.

Cette sensibilité aux conditions initiales a été découverte et étudiée pour la première fois par le météorologue américain Ed Lorenz. Par la suite, il a été appelé «effet papillon» et a conduit au développement d'un tel mouvement de pensée scientifique appelé «théorie du chaos». Cette théorie est devenue l'un des principaux changements de paradigme dans la science du 20e siècle.

Théorie du chaos


Les gens qui étudient le chaos se disent chaosologistes.



En fait, la raison de ce rapport était que, en travaillant avec des systèmes distribués complexes et de grandes organisations internationales, à un moment donné, j'ai réalisé que c'était ce que je ressentais. Je suis chaosologue. En général, c'est une manière si ingénieuse de dire: "Je ne comprends pas ce qui se passe ici et je ne sais pas quoi en faire."

Je pense que beaucoup d'entre vous se sentent aussi souvent, donc vous êtes aussi des chaosologues. Je vous invite à la guilde des chaosologues. Les systèmes que nous, chers collègues des chaosologistes, étudierons, sont appelés «systèmes adaptatifs complexes».

Qu'est-ce que l'adaptabilité? L'adaptabilité signifie que le comportement individuel et collectif des pièces dans un tel système adaptatif change et s'auto-organise, répondant aux événements ou aux chaînes de micro-événements dans le système. Autrement dit, le système s'adapte aux changements grâce à l'auto-organisation. Et cette capacité d'auto-organisation repose sur la coopération volontaire et totalement décentralisée d'agents autonomes libres.

Une autre propriété intéressante de ces systèmes est qu'ils sont librement évolutifs. Que nous, en tant qu'ingénieurs chaosologistes, devrions sans aucun doute nous intéresser. Donc, si nous disions que le comportement d'un système complexe est déterminé par l'interaction de ses parties, alors qu'est-ce qui devrait nous intéresser? Interaction.

Il y a deux conclusions plus intéressantes.


Premièrement, nous comprenons qu'un système complexe ne peut pas être simplifié en simplifiant ses parties. Deuxièmement, la seule façon de simplifier un système complexe est de simplifier les interactions entre ses parties.

Comment interagissons-nous? Nous faisons tous partie d'un grand système d'information appelé la société humaine. Nous interagissons à travers un langage commun, si nous l'avons, si nous le trouvons.



Mais la langue elle-même est un système adaptatif complexe. En conséquence, afin d'interagir plus efficacement et simplement, nous devons créer une sorte de protocoles. C'est-à-dire une séquence de symboles et d'actions qui rendra l'échange d'informations entre nous plus simple, plus prévisible et plus compréhensible.

Je veux dire que les tendances à la complication, à l'adaptabilité, à la décentralisation, au hasard se retrouvent dans tout. Et dans les systèmes que nous construisons, et dans les systèmes dont nous faisons partie.

Et pour ne pas être infondé, regardons comment les systèmes que nous créons évoluent.



Vous attendiez ce mot, je comprends. Nous sommes à la conférence DevOps, aujourd'hui ce mot retentira quelque cent mille fois et ensuite nous rêverons la nuit.

Les microservices sont la première architecture logicielle née en réaction aux pratiques DevOps, conçue pour rendre nos systèmes plus flexibles, plus évolutifs et garantir une livraison continue. Comment fait-elle cela? En réduisant le volume de services, en réduisant les limites des problèmes que ces services traitent, en réduisant les délais de livraison. Autrement dit, nous réduisons, simplifions les parties du système, augmentons leur nombre et, par conséquent, la complexité des interactions entre ces parties augmente constamment, c'est-à-dire que de nouveaux problèmes surgissent que vous et moi devons résoudre.



Les microservices ne sont pas la fin, les microservices sont, en général, déjà hier, car Serverless arrive. Tous les serveurs ont grillé, pas de serveurs, pas de systèmes d'exploitation, seulement du code exécutable propre. La configuration est séparée, l'état est séparé, tout est piloté par les événements. Beauté, pureté, silence, aucun événement, rien ne se passe, ordre complet.

Où est la difficulté? Complexité, bien sûr, dans les interactions. Que peut faire une fonction seule? Comment interagit-il avec d'autres fonctions? Files d'attente de messages, bases de données, équilibreurs. Comment recréer un événement en cas de panne? Un tas de questions et peu de réponses.

Les microservices et Serverless sont tous ce que nous, les hipsters informatiques, appelons Cloud Native. Tout tourne autour du cloud. Mais le cloud est également essentiellement évolutif. Nous sommes habitués à le considérer comme un système distribué. En fait, où vivent les serveurs des fournisseurs de cloud? Dans les centres de données. Autrement dit, nous avons ici un certain modèle centralisé, très limité, distribué.

Aujourd'hui, nous comprenons que l'Internet des objets n'est plus seulement de grands mots qui, même selon des prévisions modestes, des milliards d'appareils connectés à Internet nous attendent dans les cinq à dix prochaines années. Une énorme quantité de données utiles et inutiles qui fusionneront dans le cloud et envahiront le cloud.

Le cloud ne résistera pas, nous parlons donc de plus en plus de ce qu'on appelle "l'informatique périphérique". Ou j'aime aussi la merveilleuse définition de l'informatique de brouillard. Il est en lambeaux avec le mysticisme du romantisme et du mystère.



Informatique brumeuse. Le fait est que les nuages ​​sont des caillots d'eau, de vapeur, de glace et de pierres centralisés. Et le brouillard, ce sont des gouttelettes d'eau qui sont dispersées autour de nous dans l'atmosphère.

Dans un paradigme brumeux, la plupart du travail est effectué par ces gouttelettes de manière totalement autonome ou en collaboration avec d'autres gouttelettes. Et ils ne se tournent vers le cloud que lorsqu'ils le font vraiment.

C'est, encore une fois, la décentralisation, l'autonomie et, bien sûr, beaucoup d'entre vous comprennent déjà de quoi il s'agit, car vous ne pouvez pas parler de décentralisation et ne pas mentionner la blockchain.



Il y a ceux qui croient, ce sont ceux qui ont investi dans la crypto-monnaie. Il y a ceux qui croient, mais qui ont peur, comme moi, par exemple. Et il y a ceux qui ne croient pas. Ici, vous pouvez interagir différemment. Il y a la technologie, une nouvelle entreprise incompréhensible, il y a des problèmes. Comme toute nouvelle technologie, elle soulève plus de questions que de réponses.

Le battage médiatique autour de la blockchain est compréhensible. Même si vous mettez de côté la ruée vers l'or, la technologie elle-même fait de merveilleuses promesses d'un avenir meilleur: plus de liberté, plus d'autonomie, une confiance mondiale distribuée. Qu'y a-t-il à ne pas vouloir?

En conséquence, de plus en plus d'ingénieurs dans le monde commencent à développer des applications décentralisées. Et c'est une force qui ne peut pas être écartée en disant simplement: "Ahh, la blockchain n'est qu'une base de données distribuée mal implémentée." Ou comment les sceptiques aiment dire: "Il n'y a pas de véritable utilité pour la blockchain." Si vous y réfléchissez, il y a 150 ans, ils disaient la même chose de l'électricité. Et même à certains égards, ils avaient raison, car ce que l'électricité rend possible aujourd'hui au XIXe siècle était complètement irréaliste.

Au fait, qui sait quel type de logo est à l'écran? Voici Hyperledger. Il s'agit d'un projet développé sous les auspices de la Linux Foundation, il comprend un ensemble de technologies blockchain. C'est vraiment le pouvoir de notre communauté open source.

Ingénierie du chaos




Ainsi, le système que nous développons devient plus complexe, plus chaotique, plus adaptatif. Netflix - pionniers des systèmes de microservices. Ils ont été parmi les premiers à comprendre cela, ils ont développé une trousse à outils appelée l'armée simienne, dont la plus célèbre était Chaos Monkey . Il a défini ce que l'on a appelé les «principes de l'ingénierie du chaos» .

Soit dit en passant, dans le processus de travail sur le rapport, nous avons même traduit ce texte en russe, alors allez sur le lien , lisez, commentez, grondez.

En bref, les principes de l'ingénierie du chaos indiquent ce qui suit. Les systèmes distribués complexes sont intrinsèquement imprévisibles et comportent intrinsèquement des erreurs. Les erreurs sont inévitables, ce qui signifie que nous devons accepter ces erreurs et travailler avec ces systèmes d'une manière complètement différente.

Nous devons nous-mêmes essayer d'introduire ces erreurs dans nos systèmes de production afin de tester nos systèmes pour cette adaptabilité même, pour cette capacité même à s'auto-organiser, pour survivre.

Et cela change tout. Non seulement comment nous gérons le système en production, mais aussi comment nous les développons, comment nous les testons. Il n'y a pas de processus de stabilisation, de gel de code, au contraire, il y a un processus constant de déstabilisation. Nous essayons de tuer le système et de voir qu'il continue de survivre.

Protocoles d'intégration de système distribués




En conséquence, cela nécessite que nos systèmes changent également d'une manière ou d'une autre. Pour qu'ils deviennent plus stables, ils ont besoin de nouveaux protocoles d'interaction entre leurs parties. Pour que ces parties puissent négocier et parvenir à une sorte d'auto-organisation. Et il y a toutes sortes de nouveaux outils, de nouveaux protocoles, que j'appelle des «protocoles pour l'interaction des systèmes distribués».



De quoi je parle? Tout d'abord, le projet Opentracing . Certains tentent de créer un protocole commun pour le suivi distribué, qui est un outil absolument indispensable pour déboguer des systèmes distribués complexes.



Vient ensuite l' Open Policy Agent . Nous disons que nous ne pouvons pas prédire ce qui va arriver au système, c'est-à-dire que nous devons augmenter son observabilité, son observabilité. L'Opentracing est une famille d'outils qui donnent une observabilité à nos systèmes. Mais nous avons besoin d'observabilité pour déterminer si le système se comporte comme nous l'attendons ou non. Comment déterminons-nous le comportement attendu? En y définissant une sorte de politique, une sorte d'ensemble de règles. Le projet Open Policy Agent définit cet ensemble de règles sur un large éventail: de l'accès à l'allocation des ressources.



Comme nous l'avons dit, nos systèmes sont de plus en plus pilotés par les événements. Sans serveur est un excellent exemple de systèmes pilotés par les événements. Pour pouvoir transmettre des événements entre les systèmes et les suivre, nous avons besoin d'un langage commun, d'un protocole commun sur la façon dont nous parlons des événements, comment nous les transmettons les uns aux autres. Il s'agit d'un projet appelé Cloudevents .



Le flux continu de changements qui lave nos systèmes, les déstabilisant constamment, est un flux continu d'artefacts logiciels. Pour que nous puissions maintenir ce flux constant de changements, nous avons besoin d'un protocole général avec lequel nous pouvons parler de ce qu'est un artefact logiciel, comment il est vérifié, quelle vérification il a réussi. Il s'agit d'un projet appelé Grafeas . C'est-à-dire un protocole de métadonnées d'artefact logiciel commun.



Et enfin, si nous voulons que nos systèmes soient complètement indépendants, adaptatifs, auto-organisés, nous devons leur donner le droit à l'auto-identification. Un projet appelé spiffe fait exactement cela. Il s'agit également d'un projet parrainé par la Cloud Native Computing Foundation.

Tous ces projets sont jeunes, ils ont tous besoin de notre amour, de notre test. Tout cela est open source, nos tests, notre implémentation. Ils nous montrent dans quelle direction la technologie évolue.

Mais DevOps n'a jamais été principalement axé sur la technologie, mais principalement sur la collaboration entre les personnes. Et, en conséquence, si nous voulons que les systèmes que nous développons changent, nous devons nous changer nous-mêmes. En fait, nous changeons déjà, nous n'avons pas de choix particulier.



Il y a un merveilleux livre de l'écrivaine britannique Rachel Botsman dans lequel elle écrit sur l'évolution de la confiance à travers l'histoire humaine. Elle dit qu'au départ, dans les sociétés primitives, la confiance était locale, c'est-à-dire que nous ne faisions confiance qu'à ceux que nous connaissons personnellement.

Ensuite, il y a eu une très longue période - une période sombre, où la confiance était centralisée, lorsque nous avons commencé à faire confiance à des personnes que nous ne connaissons pas en raison de notre appartenance à la même institution publique ou étatique.

Et voici ce que nous voyons dans notre monde moderne: la confiance devient de plus en plus distribuée et décentralisée, et elle est basée sur la liberté des flux d'information, sur la disponibilité de l'information.

Si vous y réfléchissez, cette accessibilité même qui rend cette confiance possible est ce que nous mettons en œuvre.Cela signifie que la façon dont nous travaillons et la façon dont nous le faisons doivent changer, car les organisations informatiques hiérarchisées centralisées de l'ancien type cessent de fonctionner. Ils commencent à mourir.

Bases de l'organisation DevOps


L'organisation DevOps idéale du futur est un système adaptatif décentralisé composé d'équipes autonomes, chacune composée d'individus autonomes. Ces équipes sont dispersées dans le monde, elles coopèrent efficacement les unes avec les autres en utilisant une communication asynchrone, en utilisant des protocoles de communication hautement transparents. Très beau, non? Un très bel avenir.

Bien sûr, tout cela est impossible sans changement culturel. Nous devons avoir un leadership transformationnel, une responsabilité personnelle, une motivation interne.



C'est la base des organisations DevOps: transparence de l'information, communications asynchrones, leadership transformationnel, décentralisation.

Burnout


Les systèmes dont nous faisons partie et ceux que nous construisons sont de plus en plus chaotiques et il est difficile pour nous, les gens, de faire face à cette idée et de renoncer à l'illusion du contrôle. Nous essayons de continuer à les contrôler, ce qui conduit souvent à l'épuisement professionnel. Je dis cela de ma propre expérience, je me suis également brûlé, également désactivé dans des échecs de production imprévus.



L'épuisement professionnel se produit lorsque nous essayons de contrôler quelque chose qui, par essence, ne peut pas être contrôlé. Lorsque nous nous épuisons, alors tout perd son sens, parce que nous perdons le désir de faire quelque chose de nouveau, nous prenons une position défensive et commençons à défendre ce qui est.

La profession d'ingénieur, comme je me souviens souvent, est avant tout une profession créative. Si nous perdons le désir de créer quelque chose, alors nous nous transformons en cendres, nous nous transformons en cendres. Les gens s'épuisent, des organisations entières s'épuisent.

À mon avis, ce n'est qu'en acceptant le pouvoir créateur du chaos, en ne construisant la coopération que sur ses principes, que nous ne perdons pas le bien qui est dans notre profession.

Ce que je veux pour vous: aimer mon travail, aimer ce que nous faisons. Ce monde se nourrit d'informations, nous avons l'honneur de le nourrir. Alors étudions le chaos, nous serons chaosologues, nous apporterons de la valeur, créerons quelque chose de nouveau, eh bien, et les problèmes, comme nous l'avons déjà découvert, sont inévitables, et quand ils apparaîtront, nous dirons simplement "Ops!", Et le problème est résolu.

Quoi de plus que Chaos Monkey?

En fait, tous ces outils, ils sont si jeunes. Ces outils créés par Netflix pour eux-mêmes. Créez des outils pour vous-même. Lisez les principes de l'ingénierie du chaos et respectez-les, et n'essayez pas de chercher d'autres outils que quelqu'un d'autre a déjà construits.

Essayez de comprendre comment vos systèmes se brisent et commencez à les briser et observez comment ils résistent aux impacts. C’est d’abord et avant tout. Et vous pouvez rechercher des outils. Il y a toutes sortes de projets.

Je n'ai pas bien compris le moment où vous avez dit que le système ne pouvait pas être simplifié en simplifiant ses composants, et je suis immédiatement passé aux microservices, qui simplifient simplement le système en simplifiant les composants eux-mêmes et en compliquant les interactions. Ce sont essentiellement deux parties qui se contredisent.

C'est vrai, les microservices sont un sujet très controversé en général. En fait, la simplification des pièces augmente la flexibilité. Que donnent les microservices? Ils nous donnent de la flexibilité et de la vitesse, mais ils ne nous donnent certainement aucune simplicité. Ils augmentent la complexité.

Autrement dit, dans la philosophie DevOps, les microservices ne sont pas une telle bénédiction?

Tout bien a un mauvais côté. Il y a un avantage: cela augmente la flexibilité, nous donne la possibilité d'apporter des modifications plus rapidement, mais augmente la complexité et, par conséquent, la fragilité de l'ensemble du système.

Quoi de plus important: la simplification de l'interaction ou la simplification des pièces?

L'accent est sans aucun doute mis sur la simplification de l'interaction, car si nous la considérons du point de vue de la façon dont nous travaillons avec vous, nous devons, tout d'abord, faire attention à la simplification des interactions, et non pas simplifier le travail de chacun de nous séparément. Parce que la simplification du travail se transforme en robots. Mais chez McDonald's ça marche bien quand il vous est prescrit: ici vous mettez le burger, ici vous versez la sauce dessus. Cela dans notre travail créatif ne fonctionne pas du tout.

Est-il vrai que tout ce que vous avez dit vit dans un monde sans compétition, et le chaos est si bon, et il n'y a pas de contradictions dans ce chaos, personne ne veut manger, tuer quelqu'un? Comment la concurrence et DevOps devraient-ils vivre?

Eh bien, cela dépend du type de compétition dont nous parlons. Concurrence sur le lieu de travail ou concurrence entre entreprises?

À propos de la concurrence des services qui existent, car les services ne sont pas quelques entreprises. Nous créons un nouveau type d'environnement d'information, et aucun environnement ne peut vivre sans concurrence. Partout il y a de la concurrence.

Le même Netflix, nous les prenons pour un modèle. Pourquoi ont-ils trouvé ça? Parce qu'ils devaient être compétitifs. Cette flexibilité et cette rapidité de mouvement, c'est précisément cette exigence très compétitive, elle introduit l'aléatoire dans nos systèmes. Autrement dit, le chaos n'est pas ce que nous faisons consciemment, parce que nous le voulons, c'est ce qui se produit parce que le monde l'exige. Nous devons juste nous adapter. Et le chaos, c'est juste le résultat de la compétition.

Est-ce à dire que le chaos est un manque d'objectifs? Ou ces objectifs que nous ne voulons pas voir? Nous sommes dans la maison et ne comprenons pas les objectifs des autres. La concurrence, en fait, est due au fait que nous avons des objectifs clairs, et nous savons où nous allons venir à chaque instant. En cela, de mon point de vue, l'essence de DevOps.

Regardez également la question. Je pense que nous avons tous un objectif: survivre et le faire avec le
plus grand plaisir. Et l'objectif concurrentiel de toute organisation est le même. La survie est souvent en compétition, il n'y a rien à faire.

Cette année, la conférence DevOpsDays Moscou se tiendra le 7 décembre à Technopolis. Jusqu'au 11 novembre, nous acceptons les demandes de rapports. Écrivez- nous si vous souhaitez parler.

L'inscription des participants est ouverte, un billet coûte 7 000 roubles. Rejoignez-nous maintenant!

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


All Articles