Kubernetes dans l'esprit du piratage: notre chemin vers les microservices et un modèle prêt à l'emploi pour la mise en œuvre



Bonjour, je suis Yuri Buylov, je développe chez CarPrice, et je mets également en œuvre des pratiques DevOps, des microservices et Kubernetes. Je veux parler de Kubernetes dans un esprit de piraterie - pas seulement de la gestion d'un grand et beau bateau à voile, mais plutôt d'une flotte de petits bateaux de pêche disgracieux, parfois rouillés, mais très rapides, agiles et dangereux.

Il sera intéressant pour ceux qui développent ou transfèrent l'infrastructure vers des microservices, implémentent DevOps au-dessus de Kubernetes et optent pour le cloud natif dans tous les sens. Je vais vous parler de notre chemin, à la fin de l'article, je partagerai nos bases pour l'environnement des microservices - je donnerai un lien vers un modèle qui sera pratique pour les développeurs et les testeurs.

Cet article est basé sur une présentation vidéo à la conférence @Kubernetes par Mail.ru Cloud SolutionsSi vous ne voulez pas lire, vous pouvez voir .

Comment nous vivions avant Kubernetes: serveurs de développement, bare metal et Ansible


Nous vivions et vivions dans un mode de changements et d'expériences constants: tests AV, tests d'hypothèses diverses. Nous lançons de nouveaux services, puis, si quelque chose ne fonctionne pas, nous le coupons.

Une fois, nous avions un monolithe dans le PHP, ce qui a apporté beaucoup de douleur et de souffrance. Pour fournir un délai de mise sur le marché acceptable, nous avons suivi la voie habituelle: nous avons commencé à voir ce monolithe pour les microservices. En conséquence, il s'est avéré qu'un grand monolithe s'est transformé en de nombreux petits monolithes. C'est normal, c'est le cas pour tous ceux qui ont fait face à une tâche similaire.

Ensuite, nous avons commencé à essayer d'autres technologies, en particulier, Golang est apparu dans notre entreprise, il est devenu plus tard le principal langage de développement. Il y avait des questions: comment développer, tester et déployer tout cela? La réponse était évidente: vous avez besoin d'un serveur de développement. Chaque développeur doit avoir un serveur de développement, où il peut se connecter pour y écrire du code de haute qualité et hautes performances.

En conséquence, les gars ont écrit un serveur de développement. Le résultat a été une interface Web qui contrôlait la composition de docker sur les serveurs. Il y avait aussi un conteneur avec le code source, qui était monté en docker-compose. Le développeur pourrait se connecter via SSH et programme. Les testeurs y travaillaient également, tout fonctionnait parfaitement.



Mais avec l'augmentation du nombre de services, il est devenu impossible de travailler. Le moment est venu où il fallait déployer quelque chose, pas déballer les conteneurs. Nous avons pris du métal nu, roulé Docker là-bas. Puis ils ont pris Ansible, écrit plusieurs rôles. Chaque rôle est un service où se trouvent des dockers-composites, qui «arrivent» à l'une des voitures.



Nous avons donc vécu: dans nginx, nous nous sommes inscrits en amont de nos mains, ils ont dit vers quel port nous devrions aller, où ce service réside. Il y avait même un fichier yaml où tous les ports étaient répertoriés afin que les applications ne soient pas en concurrence pour eux.

Comment nous sommes arrivés à Kubernetes et y avons construit l'infrastructure


Évidemment, on ne peut pas vivre comme ça, l'orchestration est nécessaire. Nous l'avons compris en 2017-2018, alors il n'était pas clair où trouver cet orchestre. Kubernetes ne faisait que commencer, il y avait HashiCorp Nomad, Rancher, OpenShift. Nous avons essayé Nomad, ce n'était pas mal, mais nous ne voulions pas réécrire le docker-compose dans les configurations Nomad.

Concernant Kubernetes, nous avons immédiatement réalisé que des collègues étrangers essayaient de le faire, ils n'y réussissaient pas toujours. Et nous n'avions pas d'administrateurs barbus qui pourraient faire de nous une grappe. Ils ont commencé à réfléchir à la façon de mettre cela en œuvre. Même alors, Kubernetes était, par exemple, en Amazonie, mais nous nous souvenons des serrures, après quoi ils se sont déplacés de toute urgence. Par conséquent, cette option a été immédiatement rejetée, tout le trafic y étant plus cher.

Et puis Kubernetes est apparu sur la plateforme Mail.ru Cloud Solutions en tant que service Mail.ru Cloud Containers. Nous y avons déjà déplacé notre stockage S3 d'Amazon, nous avons également décidé d'essayer les K8. Nous avons déployé un cluster dans le cloud, tout a fonctionné.

Pour les tests, nous avons décidé d'y déployer un service sans état. A pris une API pour les applications mobiles, déployée - cela fonctionne. Envoyé 50% du trafic - ça marche. Oui, quelque chose tombait périodiquement, mais les gars l'ont réparé, tout allait bien. En conséquence, toute l'infrastructure a été transférée, maintenant elle est construite autour de Kubernetes, principalement des serveurs de développement et de scène.



Chaque développeur a son propre Minikube dans VMware, avec lequel il travaille. Nous lançons de nouveaux projets dans Kubernetes dans le cloud MCS, nous déployons également Managed MySQL, qui arrive immédiatement avec tous les esclaves, réplications et sauvegardes dans S3.

Nous avons toujours de l'héritage sur le métal nu, y compris un cluster de dockers exécutant Ansible, mais un jour nous le découvrirons.

Comment vivre avec un zoo technologique et ne pas souffrir


Le zoo technologique n'est plus aussi effrayant qu'il l'était, disons, en 2011. Il est même normal que vous puissiez emporter des outils et des technologies spécialisés de différents endroits et les utiliser à votre guise. Par exemple, nous utilisons Golang pour certaines choses, mais Data Scientist fonctionne en Python, vous ne pouvez pas les forcer à écrire en GO ou PHP.

En général, nous avons deux règles:

  • dockerize: il doit y avoir des conteneurs;
  • observabilité: ces conteneurs doivent être observables.

Pour continuer l'analogie avec le zoo: il y a des cellules, et ce n'est pas si important qui s'assoit dans ces cellules. L'essentiel est que l'eau et la nourriture arrivent régulièrement, automatiquement et uniformément, et les «produits vitaux» des services, c'est-à-dire les grumes, sont expédiés quelque part de manière centralisée.

Pour l'observabilité, nous avons une pile standard: chaque application écrit des journaux sur stdout, d'où tout est transféré de manière centralisée vers EFK. Autrement dit, le développeur peut venir voir les journaux dans Kibana. Les mesures d'application que nous déposons dans Prometheus, les tableaux de bord et les alertes en standard dans Grafana. Jaeger est une histoire d'Opentracing qui montre qui accède à quel service si nous ne le savons pas ou si nous ne voulons pas le traiter autrement.



Comment développer et tester avec tout cela


Disons qu'un nouveau développeur vient à nous, il voit 100 services et 100 référentiels. Il a immédiatement des questions. Comment déployer ces 100 services et comment configurer? Où sont les bases de données? Quels comptes existe-t-il? Et il y a beaucoup de telles questions. Pour cette raison, la sortie du nouveau développeur a pris un temps indécent, il pouvait s'asseoir pendant une semaine et tout configurer.

En conséquence, nous avons développé un environnement de développement en 1 clic. Chaque développeur a son propre Minikube avec des cœurs et une mémoire conditionnellement infinis, déployés dans le cloud VMware. Plus une base de données - elle provient quotidiennement de la production, est obscurcie, compressée et mise sur ZFS. Il s'agit d'un développement personnel de notre administrateur. Nous avons été engagés dans la réduction des coûts depuis longtemps, nous devions donner une base à tous les développeurs et en même temps ne pas faire faillite.

Il y a des instantanés dans ZFS, un développeur d'API peut rouler la base de données directement depuis la production en deux secondes. Avec les autotests, même histoire: on commence par l'API, et tout fonctionne.



Voici à quoi ressemble le flux de développement aujourd'hui: le



développeur est heureux, les DevOps et les administrateurs sont heureux parce que tous les processus sont uniformes, reproductibles et unifiés. Mais il y a une chose.

Système de couches en couches


Comme l'a dit Linus Torvalds: «Parler n'est pas cher. Montrez-moi le code. " Nous utilisons donc un système de couches à plusieurs niveaux. Il y a des couches triviales: dev, stage, prod, qui viennent à l'esprit pour tous ceux qui vont faire du CI / CD.

Mais il y a encore des développeurs, ils ont besoin de certains de leurs domaines, de quelques histoires spécifiques aux utilisateurs, nous avons donc une couche de valeurs utilisateurs. Mais cela ne suffit pas - vous devez toujours tester. Supposons que nous ayons créé une branche, peut-être plusieurs services, et que nous devons la transmettre au testeur pour qu'elle se répète. Pour cela, nous avons une couche avec des valeurs pour les tâches, c'est-à-dire des valeurs de tâches.

Un autre moment, un peu holivarny - nous n'utilisons pas Tiller, installé sur Helm, mais nous l'utilisons en fait comme moteur de modèle. Autrement dit, nous utilisons uniquement un modèle de barre, il donne un fichier yaml à la sortie, qui peut être attribué à Minikube ou à un cluster, et rien d'autre n'est nécessaire.



Fonctionnement du référentiel K8s-helm


Comme je l'ai dit, nous avons des couches évidentes de dev, prod et stage, il y a un fichier yaml de chaque service, quand nous avons vu un nouveau service, ajoutez le fichier.

De plus, il y a un papa dev.server avec le plus intéressant. Il existe des scripts bash qui aident, par exemple, à créer un nouvel utilisateur: ne créez pas 100 services avec vos mains et ne remplissez pas les fichiers yaml, mais exécutez simplement une seule commande. C'est là que tous ces fichiers yaml sont générés.



Dans le même dossier, il y a un sous-dossier tâches. Si nous devons créer des valeurs spécifiques pour notre déploiement, nous créons simplement un dossier avec les numéros de tâche à l'intérieur, validons la branche. Ensuite, nous disons au testeur: "Une telle branche se trouve dans le référentiel, prenez-la et exécutez-la." Il démarre, tire la commande qui se trouve dans le papa bin, et tout fonctionne - pas besoin de configurer à la main. Le miracle de DevOps est une infrastructure en tant que code.

En conséquence, le processus se résume à trois équipes:



Lorsqu'un nouveau développeur arrive, ils lui donnent Minikube, un dossier d'archives avec certificats et un domaine. En général, il n'a besoin que de kubectl et de Helm. Il clone le référentiel pour lui-même, montre à kubectl le chemin vers sa configuration, exécute la commande make_user avec son nom. Et pour tous les services, des copies sont créées pour lui. De plus, ils ne sont pas simplement créés - il y a une base de données qui lui a été donnée, le développeur lui a prescrit des informations d'identification, et toutes ces informations d'identification vont à d'autres services.

L'utilisateur a été créé. Comment puis-je le déployer maintenant? Rien de compliqué ici non plus - nous exécutons deploy.sh avec son nom, et tout vient au développeur dans l'espace de noms par défaut de son Minikube, tout est immédiatement disponible sur son domaine.

Si le développeur a programmé quelque chose, il prend l'ID du problème et le donne au testeur. Le testeur copie cette branche, lance un déploiement et un environnement avec une nouvelle fonctionnalité apparaît dans son cluster.

Ensemble barre K8s


Le référentiel lui-même est en outre compilé et intégré aux processus CI / CD. Rien de spécial ici - juste kubectl avec certificats et Helm.



Dans le projet, cela ressemble à ceci:



Supposons que vous soyez déployé et qu'il y ait une étape où vous devez d'abord organiser l'étape, puis exécuter les tests à l'aide de Jenkins. Depuis le référentiel, vous avez une image compilée avec Helm. Nous exécutons la commande deploy namespace service_stage run et tout décolle.

Vient ensuite CI, ici .drone.yml, mais à peu près la même chose se produira dans GitLab ou ailleurs.

Ensuite, Jenkins démarre, qui exécute les tests sur scène. Si tout va bien, alors il démarre presque le même déploiement, mais déjà sur la prod. Autrement dit, ce mécanisme facilite non seulement la vie des développeurs et des testeurs, mais il est également utilisé pour fournir des fonctionnalités aux produits.

Nous aimons l'open source, nous voulons investir dans le développement de DevOps, nous avons donc créé un modèle que vous pouvez utiliser et le télécharger sur le github . Il y a tout ce dont j'ai parlé: vous pouvez prendre, regarder, tester et appliquer. Il sera utile à tous ceux qui implémentent des microservices, ou souffrent du fait que l'équipe implémente des microservices, ou souhaite construire des processus DevOps autour de cela.

Nos autres articles associés:

  1. 25 outils Kubernetes utiles: déploiement et gestion .
  2. Facturation secondaire, place de marché et bacs à sable pour le Big Data: ce que les environnements de test dans le cloud peuvent faire .
  3. Comment migrer vers le cloud en deux heures grâce à Kubernetes et à l'automatisation

Cette conférence a été faite pour la première fois lors de la conférence @Kubernetes par Mail.ru Cloud Solutions. Regardez une vidéo d' autres performances et inscrivez-vous aux annonces d'événements Telegram Autour de Kubernetes chez Mail.ru Group .

All Articles