Nous acceptons 10000 événements dans Yandex.Cloud. Partie 1

Bonjour Ă  tous, mes amis!



* Cet article est écrit sur la base de l'atelier ouvert REBRAIN & Yandex.Cloud, si vous aimez regarder la vidéo, vous pouvez le trouver sur ce lien - https://youtu.be/cZLezUm0ekE



Récemment, nous avons eu l'occasion de toucher Yandex.Cloud en direct. Comme nous voulions le ressentir pendant longtemps et fermement, nous avons immédiatement abandonné l'idée de lancer un simple blog wordpress avec une base cloud - c'est trop ennuyeux. AprÚs quelques délibérations, nous avons décidé de déployer quelque chose de similaire à l'architecture de production d'un service de réception et d'analyse d'événements en temps quasi réel.



Je suis absolument sûr que la grande majorité des entreprises en ligne (et pas seulement) d'une maniÚre ou d'une autre collectent une montagne d'informations sur leurs utilisateurs et leurs actions. Au minimum, cela est nécessaire pour prendre certaines décisions - par exemple, si vous gérez un jeu en ligne - vous pouvez voir des statistiques à quel niveau les utilisateurs sont les plus susceptibles de rester bloqués et de supprimer votre jouet. Ou pourquoi les utilisateurs quittent votre site sans rien acheter (bonjour, Yandex.Metrica).



Donc, notre histoire: comment nous avons écrit une application en golang, testé kafka vs rabbitmq vs yqs, écrit des données en streaming vers un cluster Clickhouse et visualisé des données à l'aide de datalens yandex. Naturellement, tout cela a été épicé avec des délices d'infrastructure sous la forme de docker, de terraform, de gitlab ci et, bien sûr, de prometheus. Allons-y!



Je voudrais faire une réserve tout de suite que nous ne pouvons pas tout configurer en une seule séance - pour cela, nous avons besoin de plusieurs articles dans la série. Un peu sur la structure:



Partie 1 (vous la lisez). Nous définirons la spécification technique et l'architecture de la solution, et rédigerons également une application en golang.

Partie 2. Nous mettons notre application en production, la rendons Ă©volutive et testons la charge.

Partie 3. Essayons de comprendre pourquoi nous devons stocker les messages dans un tampon, et non dans des fichiers, et comparons Ă©galement les services de file d'attente kafka, rabbitmq et yandex entre eux.

Partie 4. Nous allons déployer le cluster Clickhouse, écrire le streaming pour y transférer les données de la mémoire tampon, configurer la visualisation dans les datalens.

Partie 5. Mettons toute l'infrastructure en forme - configurez ci / cd à l'aide de gitlab ci, connectez la surveillance et la découverte de services à l'aide de prometheus et consul.



TK



Tout d'abord, nous formulerons les termes de référence - ce que nous voulons exactement obtenir à la sortie.



  1. Nous voulons avoir un point de terminaison de la forme events.kis.im (kis.im est le domaine de test que nous utiliserons dans tous les articles), qui devrait accepter les événements utilisant HTTPS.
  2. Les événements sont un simple json de la forme: {"event": "view", "os": "linux", "browser": "chrome"}. Au stade final, nous ajouterons un peu plus de champs, mais cela ne jouera pas un grand rÎle. Si vous le souhaitez, vous pouvez passer à protobuf.
  3. Le service doit pouvoir traiter 10 000 événements par seconde.
  4. Il devrait pouvoir évoluer horizontalement en ajoutant simplement de nouvelles instances à notre solution. Et ce sera bien si nous pouvons déplacer le front-end vers différentes géolocalisations pour réduire la latence des demandes des clients.
  5. TolĂ©rance aux pannes. La solution doit ĂȘtre suffisamment stable et pouvoir survivre lorsque des piĂšces tombent (jusqu'Ă  une certaine quantitĂ©, bien sĂ»r).


Architecture



En général, pour ce type de tùches, des architectures classiques ont longtemps été inventées qui vous permettent d'évoluer efficacement. La figure montre un exemple de notre solution.







Donc, ce que nous avons:



1. Sur la gauche sont représentés nos appareils qui génÚrent divers événements, qu'il s'agisse de passer le niveau des joueurs dans un jouet sur un smartphone ou de créer une commande dans une boutique en ligne via un navigateur classique. L'événement, comme indiqué dans le TOR, est un simple json qui est envoyé à notre point de terminaison - events.kis.im.



2. Les deux premiers serveurs sont de simples Ă©quilibreurs, leurs principales tĂąches sont:



  • . , , keepalived, IP .
  • TLS. , TLS . -, , -, , backend .
  • backend . — . , , load balancer’ .


3. DerriĂšre les Ă©quilibreurs, nous avons des serveurs d'applications exĂ©cutant une application assez simple. Il devrait ĂȘtre capable d'accepter les requĂȘtes HTTP entrantes, de valider le json envoyĂ© et de stocker les donnĂ©es dans un tampon.



4. Le diagramme montre kafka comme un tampon, bien que, bien sĂ»r, d'autres services similaires puissent ĂȘtre utilisĂ©s Ă  ce niveau. Nous comparerons Kafka, rabbitmq et yqs dans le troisiĂšme article.



5. L'avant-dernier point de notre architecture est Clickhouse - une base de donnĂ©es en colonnes qui vous permet de stocker et de traiter une Ă©norme quantitĂ© de donnĂ©es. À ce niveau, nous devons transfĂ©rer les donnĂ©es de la mĂ©moire tampon vers, en fait, le systĂšme de stockage (Ă  ce sujet - dans l'article 4).



Ce schĂ©ma nous permet de mettre Ă  l'Ă©chelle indĂ©pendamment chaque couche horizontalement. Les serveurs backend ne font pas face - ajoutons-en plus - car ce sont des applications sans Ă©tat, et par consĂ©quent, cela peut ĂȘtre fait mĂȘme en mode automatique. Il ne tire pas de tampon sous la forme d'un kafka - nous ajouterons plus de serveurs et leur transfĂ©rerons certaines des partitions de notre sujet. Le clickhouse Ă©choue - c'est impossible :) En fait, nous allons Ă©galement supprimer les serveurs et partager les donnĂ©es.



Au fait, si vous souhaitez implémenter la partie optionnelle de notre spécification technique et effectuer une mise à l'échelle dans différentes géolocalisations, rien de plus simple:







Dans chaque gĂ©olocalisation, nous dĂ©ployons un Ă©quilibreur de charge avec application et kafka. En gĂ©nĂ©ral, 2 serveurs d'application, 3 nƓuds kafka et un Ă©quilibreur cloud, par exemple cloudflare, suffisent, qui vĂ©rifieront la disponibilitĂ© des nƓuds d'application et Ă©quilibreront les demandes par gĂ©olocalisation en fonction de l'adresse IP d'origine du client. Ainsi, les donnĂ©es envoyĂ©es par le client amĂ©ricain atterriront sur les serveurs amĂ©ricains. Et les donnĂ©es de l'Afrique - sur l'Afrique.



Ensuite, tout est assez simple - nous utilisons l'outil miroir de l'ensemble kafka et copions toutes les donnĂ©es de tous les emplacements vers notre centre de donnĂ©es central situĂ© en Russie. À l'intĂ©rieur, nous analysons les donnĂ©es et les Ă©crivons dans Clickhouse pour une visualisation ultĂ©rieure.



Donc, nous avons compris l'architecture - commençons à secouer Yandex.Cloud!



RĂ©daction d'une candidature



Avant le Cloud, il faut encore endurer un peu et écrire un service assez simple pour traiter les événements entrants. Nous utiliserons le golang, car il a fait ses preuves en tant que langage pour l'écriture d'applications réseau.



AprĂšs avoir passĂ© une heure (peut-ĂȘtre quelques heures), nous obtenons quelque chose comme ceci: https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/main.go .



Quels sont les points principaux ici que je voudrais noter:



1. Au dĂ©marrage de l'application, vous pouvez spĂ©cifier deux indicateurs. L'un est responsable du port sur lequel nous Ă©couterons les requĂȘtes http entrantes (-addr). Le second est pour l'adresse du serveur kafka oĂč nous enregistrerons nos Ă©vĂ©nements (-kafka):



addr     = flag.String("addr", ":8080", "TCP address to listen to")
kafka    = flag.String("kafka", "127.0.0.1:9092", "Kafka endpoints”)


2. L'application utilise la bibliothÚque sarama ( [] github.com/Shopify/sarama ) pour envoyer des messages au cluster kafka. Nous avons immédiatement défini les paramÚtres axés sur la vitesse de traitement maximale:



config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForLocal
config.Producer.Compression = sarama.CompressionSnappy
config.Producer.Return.Successes = true


3. De plus, notre application dispose d'un client prometheus intégré qui collecte diverses métriques, telles que:



  • le nombre de demandes Ă  notre application;
  • le nombre d'erreurs lors de l'exĂ©cution de la requĂȘte (il est impossible de lire la requĂȘte de publication, json cassĂ©, il est impossible d'Ă©crire dans le kafka);
  • temps de traitement d'une demande d'un client, y compris l'heure d'Ă©criture d'un message Ă  kafka.


4. Trois points de terminaison traités par notre application:



  • / status - retourne simplement ok pour montrer que nous sommes vivants. Bien que vous puissiez ajouter des vĂ©rifications, telles que la disponibilitĂ© du cluster kafka.
  • / metrics - selon cette URL, le client prometheus retournera les mĂ©triques qu'il a collectĂ©es.
  • /post — endpoint, POST json . json — -.


Je ferai une rĂ©serve que le code n'est pas parfait - il peut (et devrait!) Être terminĂ©. Par exemple, vous pouvez arrĂȘter d'utiliser le net / http intĂ©grĂ© et passer Ă  plus rapide fasthttp. Ou vous pouvez gagner du temps de traitement et des ressources CPU en prenant le contrĂŽle de validation json Ă  une Ă©tape ultĂ©rieure - lorsque les donnĂ©es seront transfĂ©rĂ©es du tampon vers le cluster Clickhouse.



Outre l'aspect développement du problÚme, nous avons tout de suite pensé à notre future infrastructure et décidé de déployer notre application via docker. Le Dockerfile final pour la création de l'application est https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/Dockerfile . En général, c'est assez simple, le seul point sur lequel je veux attirer l'attention est l'assemblage en plusieurs étapes, qui nous permet de réduire l'image finale de notre contenant.



Premiers pas dans le cloud



Tout d'abord, nous nous inscrivons sur cloud.yandex.ru . AprĂšs avoir rempli tous les champs obligatoires, nous crĂ©erons un compte et accorderons une subvention d'un certain montant pouvant ĂȘtre utilisĂ© pour tester les services cloud. Si vous souhaitez rĂ©pĂ©ter toutes les Ă©tapes de notre article, cette subvention devrait vous suffire.



AprÚs l'enregistrement, un cloud séparé et un répertoire par défaut seront créés pour vous, dans lesquels vous pourrez commencer à créer des ressources cloud. En général, dans Yandex.Cloud, la relation des ressources est la suivante:







Vous pouvez crĂ©er plusieurs clouds pour un compte. Et dans le cloud, crĂ©ez diffĂ©rents rĂ©pertoires pour diffĂ©rents projets d'entreprise. Vous pouvez en savoir plus Ă  ce sujet dans la documentation - https://cloud.yandex.ru/docs/resource-manager/concepts/resources-hierarchy... À propos, ci-dessous dans le texte, je vais souvent y faire rĂ©fĂ©rence. Lorsque j'ai mis en place toute l'infrastructure Ă  partir de zĂ©ro, la documentation m'a aidĂ© plus d'une fois, je vous conseille donc d'Ă©tudier.



Pour gérer le cloud, vous pouvez utiliser à la fois l'interface Web et l'utilitaire de console - yc. L'installation est effectuée avec une seule commande (pour Linux et Mac OS):



curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bash


Si un responsable de la sécurité interne faisait rage à propos de l'exécution de scripts à partir d'Internet, vous pouvez tout d'abord ouvrir le script et le lire, et deuxiÚmement, nous l'exécuter sous notre utilisateur - sans droits root.



Si vous souhaitez installer le client pour Windows, vous pouvez utiliser les instructions ici , puis suivre yc initpour le configurer complĂštement:



vozerov@mba:~ $ yc init
Welcome! This command will take you through the configuration process.
Please go to https://oauth.yandex.ru/authorize?response_type=token&client_id= in order to obtain OAuth token.

Please enter OAuth token:
Please select cloud to use:
 [1] cloud-b1gv67ihgfu3bp (id = b1gv67ihgfu3bpt24o0q)
 [2] fevlake-cloud (id = b1g6bvup3toribomnh30)
Please enter your numeric choice: 2
Your current cloud has been set to 'fevlake-cloud' (id = b1g6bvup3toribomnh30).
Please choose folder to use:
 [1] default (id = b1g5r6h11knotfr8vjp7)
 [2] Create a new folder
Please enter your numeric choice: 1
Your current folder has been set to 'default' (id = b1g5r6h11knotfr8vjp7).
Do you want to configure a default Compute zone? [Y/n]
Which zone do you want to use as a profile default?
 [1] ru-central1-a
 [2] ru-central1-b
 [3] ru-central1-c
 [4] Don't set default zone
Please enter your numeric choice: 1
Your profile default Compute zone has been set to 'ru-central1-a'.
vozerov@mba:~ $


En principe, le processus est simple - vous devez d'abord obtenir le jeton oauth pour la gestion du cloud, sélectionnez le cloud et le dossier que vous utiliserez.



Si vous avez plusieurs comptes ou dossiers dans le mĂȘme cloud, vous pouvez crĂ©er des profils supplĂ©mentaires avec des paramĂštres distincts via yc config profile create et basculer entre eux.



En plus des mĂ©thodes ci-dessus, l'Ă©quipe Yandex.Cloud a Ă©crit un trĂšs bon plugin terraform pour la gestion des ressources cloud. Pour ma part, j'ai prĂ©parĂ© un rĂ©fĂ©rentiel git, oĂč j'ai dĂ©crit toutes les ressources qui seront crĂ©Ă©es dans le cadre de l'article - https://github.com/rebrainme/yandex-cloud-events/ . Nous sommes intĂ©ressĂ©s par la branche master, clonons-la localement:




vozerov@mba:~ $ git clone https://github.com/rebrainme/yandex-cloud-events/ events
Cloning into 'events'...
remote: Enumerating objects: 100, done.
remote: Counting objects: 100% (100/100), done.
remote: Compressing objects: 100% (68/68), done.
remote: Total 100 (delta 37), reused 89 (delta 26), pack-reused 0
Receiving objects: 100% (100/100), 25.65 KiB | 168.00 KiB/s, done.
Resolving deltas: 100% (37/37), done.
vozerov@mba:~ $ cd events/terraform/


Toutes les principales variables utilisées dans terraform sont écrites dans le fichier main.tf. Pour commencer, créez un fichier private.auto.tfvars dans le dossier terraform avec le contenu suivant:



# Yandex Cloud Oauth token
yc_token = ""
# Yandex Cloud ID
yc_cloud_id = ""
# Yandex Cloud folder ID
yc_folder_id = ""
# Default Yandex Cloud Region
yc_region = "ru-central1-a"
# Cloudflare email
cf_email = ""
# Cloudflare token
cf_token = ""
# Cloudflare zone id
cf_zone_id = ""


Toutes les variables peuvent ĂȘtre extraites de la liste de configuration yc, puisque nous avons dĂ©jĂ  configurĂ© l'utilitaire de console. Je vous conseille d'ajouter immĂ©diatement private.auto.tfvars Ă  .gitignore afin de ne pas publier par inadvertance des donnĂ©es privĂ©es.



Dans private.auto.tfvars, nous avons également spécifié des données de Cloudflare - pour créer des enregistrements DNS et transmettre par proxy le domaine principal events.kis.im à nos serveurs. Si vous ne souhaitez pas utiliser cloudflare, supprimez l'initialisation du fournisseur cloudflare dans main.tf et le fichier dns.tf, qui est responsable de la création des enregistrements DNS nécessaires.



Dans notre travail, nous combinerons les trois méthodes - l'interface Web, l'utilitaire de console et terraform.



RĂ©seaux virtuels



HonnĂȘtement, cette Ă©tape peut ĂȘtre ignorĂ©e, car lorsque vous crĂ©ez un nouveau cloud, vous aurez automatiquement un rĂ©seau sĂ©parĂ© et 3 sous-rĂ©seaux - un pour chaque zone de disponibilitĂ©. NĂ©anmoins, je voudrais crĂ©er un rĂ©seau sĂ©parĂ© pour notre projet avec son propre adressage. Le schĂ©ma gĂ©nĂ©ral de fonctionnement du rĂ©seau dans Yandex.Cloud est illustrĂ© dans la figure ci-dessous (honnĂȘtement tirĂ© de https://cloud.yandex.ru/docs/vpc/concepts/ )







Ainsi, vous crĂ©ez un rĂ©seau commun au sein duquel les ressources peuvent communiquer entre elles. Pour chaque zone de disponibilitĂ©, un sous-rĂ©seau est constituĂ© avec son propre adressage et connectĂ© au rĂ©seau public. En consĂ©quence, toutes les ressources cloud qu'il contient peuvent communiquer, mĂȘme dans des zones de disponibilitĂ© diffĂ©rentes. Les ressources connectĂ©es Ă  diffĂ©rents rĂ©seaux cloud ne peuvent se voir que via des adresses externes. Au fait, comment cette magie fonctionne Ă  l'intĂ©rieur a Ă©tĂ© bien dĂ©crite sur HabrĂ© .



La création de réseau est décrite dans le fichier network.tf du référentiel. Là, nous créons un réseau privé commun interne et y connectons trois sous-réseaux dans différentes zones de disponibilité - interne-a (172.16.1.0/24), interne-b (172.16.2.0/24), interne-c (172.16.3.0/24 ).



Nous initialisons terraform et créons des réseaux:



vozerov@mba:~/events/terraform (master) $ terraform init
... skipped ..

vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_vpc_subnet.internal-a -target yandex_vpc_subnet.internal-b -target yandex_vpc_subnet.internal-c

... skipped ...

Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

yandex_vpc_network.internal: Creating...
yandex_vpc_network.internal: Creation complete after 3s [id=enp2g2rhile7gbqlbrkr]
yandex_vpc_subnet.internal-a: Creating...
yandex_vpc_subnet.internal-b: Creating...
yandex_vpc_subnet.internal-c: Creating...
yandex_vpc_subnet.internal-a: Creation complete after 6s [id=e9b1dad6mgoj2v4funog]
yandex_vpc_subnet.internal-b: Creation complete after 7s [id=e2liv5i4amu52p64ac9p]
yandex_vpc_subnet.internal-c: Still creating... [10s elapsed]
yandex_vpc_subnet.internal-c: Creation complete after 10s [id=b0c2qhsj2vranoc9vhcq]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.


Excellent! Nous avons fait notre rĂ©seau et sommes maintenant prĂȘts Ă  crĂ©er nos services internes.



Créer des machines virtuelles



Pour tester l'application, il nous suffira de créer deux machines virtuelles - nous aurons besoin de la premiÚre pour construire et exécuter l'application, la seconde - pour exécuter kafka, que nous utiliserons pour stocker les messages entrants. Et nous allons créer une autre machine, sur laquelle nous configurerons prometheus pour surveiller l'application.



Les machines virtuelles seront configurées à l'aide d'ansible, assurez-vous donc de disposer de l'une des derniÚres versions d'ansible avant de démarrer terraform. Et installez les rÎles requis avec ansible galaxy:



vozerov@mba:~/events/terraform (master) $ cd ../ansible/
vozerov@mba:~/events/ansible (master) $ ansible-galaxy install -r requirements.yml
- cloudalchemy-prometheus (master) is already installed, skipping.
- cloudalchemy-grafana (master) is already installed, skipping.
- sansible.kafka (master) is already installed, skipping.
- sansible.zookeeper (master) is already installed, skipping.
- geerlingguy.docker (master) is already installed, skipping.
vozerov@mba:~/events/ansible (master) $


Dans le dossier ansible, il y a un exemple de fichier de configuration .ansible.cfg que j'utilise. Peut-ĂȘtre utile.



Avant de créer des machines virtuelles, assurez-vous que ssh-agent est en cours d'exécution et qu'une clé ssh a été ajoutée, sinon terraform ne pourra pas se connecter aux machines créées. Je suis tombé sur un bug dans os x bien sûr: https://github.com/ansible/ansible/issues/32499#issuecomment-341578864 . Pour éviter de répéter cette histoire, ajoutez une petite variable à l'environnement avant de démarrer Terraform:



vozerov@mba:~/events/terraform (master) $ export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES


Créez les ressources nécessaires dans le dossier terraform:



vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_compute_instance.build -target yandex_compute_instance.monitoring -target yandex_compute_instance.kafka
yandex_vpc_network.internal: Refreshing state... [id=enp2g2rhile7gbqlbrkr]
data.yandex_compute_image.ubuntu_image: Refreshing state...
yandex_vpc_subnet.internal-a: Refreshing state... [id=e9b1dad6mgoj2v4funog]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

... skipped ...

Plan: 3 to add, 0 to change, 0 to destroy.

... skipped ...


Si tout s'est bien terminĂ© (et ça devrait l'ĂȘtre), alors nous aurons trois machines virtuelles:



  1. build - une machine pour tester et créer une application. Docker a été installé automatiquement par ansible.
  2. monitoring - machine de monitoring - prometheus & grafana y est installé. Le login / mot de passe est standard: admin / admin
  3. kafka est une petite voiture avec kafka installé, disponible sur le port 9092.


Assurons-nous qu'ils sont tous en place:



vozerov@mba:~/events (master) $ yc compute instance list
+----------------------+------------+---------------+---------+---------------+-------------+
|          ID          |    NAME    |    ZONE ID    | STATUS  |  EXTERNAL IP  | INTERNAL IP |
+----------------------+------------+---------------+---------+---------------+-------------+
| fhm081u8bkbqf1pa5kgj | monitoring | ru-central1-a | RUNNING | 84.201.159.71 | 172.16.1.35 |
| fhmf37k03oobgu9jmd7p | kafka      | ru-central1-a | RUNNING | 84.201.173.41 | 172.16.1.31 |
| fhmt9pl1i8sf7ga6flgp | build      | ru-central1-a | RUNNING | 84.201.132.3  | 172.16.1.26 |
+----------------------+------------+---------------+---------+---------------+-------------+


Les ressources sont en place, et à partir de là, nous pouvons extraire leurs adresses IP. Partout ci-dessous, j'utiliserai des adresses IP pour me connecter via ssh et tester l'application. Si vous avez un compte cloudflare connecté à terraform, n'hésitez pas à utiliser les noms DNS nouvellement créés.

À propos, lors de la crĂ©ation d'une machine virtuelle, une adresse IP interne et un nom DNS interne sont Ă©mis, vous pouvez donc faire rĂ©fĂ©rence aux serveurs Ă  l'intĂ©rieur du rĂ©seau par des noms:



ubuntu@build:~$ ping kafka.ru-central1.internal
PING kafka.ru-central1.internal (172.16.1.31) 56(84) bytes of data.
64 bytes from kafka.ru-central1.internal (172.16.1.31): icmp_seq=1 ttl=63 time=1.23 ms
64 bytes from kafka.ru-central1.internal (172.16.1.31): icmp_seq=2 ttl=63 time=0.625 ms
^C
--- kafka.ru-central1.internal ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.625/0.931/1.238/0.308 ms


Cela nous sera utile pour indiquer Ă  l'application un endpoint avec kafk.



Assembler l'application



GĂ©nial, il y a des serveurs, il y a une application - il ne reste plus qu'Ă  la collecter et Ă  la publier. Pour l'assemblage, nous utiliserons la version habituelle du docker, mais comme stockage d'image, nous prendrons le service de Yandex - le registre de conteneurs. Mais tout d'abord.



Copiez l'application sur la machine de construction, accédez à ssh et collectez l'image:



vozerov@mba:~/events/terraform (master) $ cd ..
vozerov@mba:~/events (master) $ rsync -av app/ ubuntu@84.201.132.3:app/

... skipped ...

sent 3849 bytes  received 70 bytes  7838.00 bytes/sec
total size is 3644  speedup is 0.93

vozerov@mba:~/events (master) $ ssh 84.201.132.3 -l ubuntu
ubuntu@build:~$ cd app
ubuntu@build:~/app$ sudo docker build -t app .
Sending build context to Docker daemon  6.144kB
Step 1/9 : FROM golang:latest AS build
... skipped ...

Successfully built 9760afd8ef65
Successfully tagged app:latest


La moitié de la bataille est terminée - nous pouvons maintenant vérifier la fonctionnalité de notre application en l'exécutant et en la pointant vers kafka:



ubuntu@build:~/app$ sudo docker run --name app -d -p 8080:8080 app /app/app -kafka=kafka.ru-central1.internal:9092</code>

      event    :

<code>vozerov@mba:~/events (master) $ curl -D - -s -X POST -d '{"key1":"data1"}' http://84.201.132.3:8080/post
HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 13 Apr 2020 13:53:54 GMT
Content-Length: 41

{"status":"ok","partition":0,"Offset":0}
vozerov@mba:~/events (master) $


L'application a répondu avec le succÚs de l'enregistrement et en indiquant l'identifiant de la partition et le décalage dans lesquels le message est tombé. La seule chose à faire est de créer un registre dans Yandex.Cloud et d'y télécharger notre image (comment faire cela en utilisant trois lignes est décrit dans le fichier registry.tf). Nous créons un référentiel:



vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_container_registry.events

... skipped ...

Plan: 1 to add, 0 to change, 0 to destroy.

... skipped ...

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.


Il existe plusieurs façons de s'authentifier dans le registre de conteneurs - à l'aide d'un jeton oauth, d'un jeton iam ou d'une clé de compte de service. Pour plus d'informations sur ces méthodes, consultez la documentation https://cloud.yandex.ru/docs/container-registry/operations/authentication . Nous utiliserons la clé de compte de service, nous créons donc un compte:



vozerov@mba:~/events/terraform (master) $ terraform apply -target yandex_iam_service_account.docker -target yandex_resourcemanager_folder_iam_binding.puller -target yandex_resourcemanager_folder_iam_binding.pusher

... skipped ...

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.


Reste maintenant à lui faire une clé:



vozerov@mba:~/events/terraform (master) $ yc iam key create --service-account-name docker -o key.json
id: ajej8a06kdfbehbrh91p
service_account_id: ajep6d38k895srp9osij
created_at: "2020-04-13T14:00:30Z"
key_algorithm: RSA_2048


Nous obtenons des informations sur l'identifiant de notre stockage, retournons la clé et nous connectons:



vozerov@mba:~/events/terraform (master) $ scp key.json ubuntu@84.201.132.3:
key.json                                                                                                                    100% 2392   215.1KB/s   00:00

vozerov@mba:~/events/terraform (master) $ ssh 84.201.132.3 -l ubuntu

ubuntu@build:~$ cat key.json | sudo docker login --username json_key --password-stdin cr.yandex
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
ubuntu@build:~$


Pour charger l'image dans le registre, nous avons besoin du registre de conteneurs d'ID, nous le prenons de l'utilitaire yc:



vozerov@mba:~ $ yc container registry get events
id: crpdgj6c9umdhgaqjfmm
folder_id:
name: events
status: ACTIVE
created_at: "2020-04-13T13:56:41.914Z"


AprĂšs cela, nous Ă©tiquetons notre image avec un nouveau nom et chargeons:



ubuntu@build:~$ sudo docker tag app cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
ubuntu@build:~$ sudo docker push cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
The push refers to repository [cr.yandex/crpdgj6c9umdhgaqjfmm/events]
8c286e154c6e: Pushed
477c318b05cb: Pushed
beee9f30bc1f: Pushed
v1: digest: sha256:1dd5aaa9dbdde2f60d833be0bed1c352724be3ea3158bcac3cdee41d47c5e380 size: 946


Nous pouvons nous assurer que l'image a démarré avec succÚs:



vozerov@mba:~/events/terraform (master) $ yc container repository list
+----------------------+-----------------------------+
|          ID          |            NAME             |
+----------------------+-----------------------------+
| crpe8mqtrgmuq07accvn | crpdgj6c9umdhgaqjfmm/events |
+----------------------+-----------------------------+


Au fait, si vous installez l'utilitaire yc sur une machine Linux, vous pouvez utiliser la commande



yc container registry configure-docker


pour la configuration du docker.



Conclusion



Nous avons fait un travail formidable et difficile et par conséquent:



  1. .
  2. golang, -.
  3. container registry.


Dans la partie suivante, nous allons passer aux choses intéressantes - nous allons verser notre application en production et enfin lancer la charge dessus. Ne changez pas!



Ce matériel se trouve dans la vidéo de l'atelier ouvert REBRAIN & Yandex.Cloud: Nous acceptons 10000 demandes par seconde sur Yandex Cloud - https://youtu.be/cZLezUm0ekE





Si vous souhaitez visiter de tels événements en ligne et poser des questions en temps réel, connectez-vous à la chaßne DevOps par REBRAIN .



Nous tenons à remercier tout particuliÚrement Yandex.Cloud pour l'opportunité d'organiser un tel événement. Un lien vers eux est https://cloud.yandex.ru/prices



Si vous avez besoin d'une migration vers le cloud ou avez des questions sur votre infrastructure, n'hésitez pas à laisser une demande .



P.S. 2 , , .



All Articles