Nous acceptons 10 000 événements dans Yandex.Cloud. Partie 1

Bonjour à tous, les amis !

* Cet article est basé sur l'atelier ouvert REBRAIN & Yandex.Cloud, si vous préférez regarder la vidéo, vous pouvez la trouver sur ce lien - https://youtu.be/cZLezUm0ekE

Nous avons récemment eu l'occasion d'essayer Yandex.Cloud en direct. Comme nous voulions enquêter longuement et durement, nous avons immédiatement abandonné l'idée de lancer un simple blog Wordpress avec une base cloud - c'était trop ennuyeux. Après réflexion, nous avons décidé de déployer quelque chose de similaire à une architecture de service de production pour recevoir et analyser les événements en mode temps quasi réel.

Je suis absolument sûr que la grande majorité des entreprises en ligne (et pas seulement) collectent d’une manière ou d’une autre 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 consulter les statistiques à quel niveau les utilisateurs restent le plus souvent bloqués et suppriment votre jouet. Ou pourquoi les utilisateurs quittent votre site sans rien acheter (bonjour Yandex.Metrica).

Alors, notre histoire : comment nous avons écrit une application en golang, testé kafka vs lapinmq vs yqs, écrit le streaming de données dans un cluster Clickhouse et visualisé les données à l'aide de Yandex Datalens. Naturellement, tout cela était agrémenté de plaisirs d'infrastructure sous la forme de docker, terraform, gitlab ci et, bien sûr, prometheus. Allons-y!

Je voudrais immédiatement faire une réserve sur le fait que nous ne pourrons pas tout configurer en une seule fois - pour cela, nous aurons besoin de plusieurs articles de la série. Un peu sur la structure :

Partie 1 (vous êtes en train de la lire). Nous déciderons des spécifications et de 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.
Partie 4 Nous allons déployer un cluster Clickhouse, écrire un service de streaming pour y transférer les données du tampon et configurer la visualisation dans datalens.
Partie 5 Mettons l'ensemble de l'infrastructure en bon état - 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, formulons les termes de référence - ce que nous voulons exactement obtenir comme résultat.

  1. Nous voulons avoir un point de terminaison comme events.kis.im (kis.im est le domaine de test que nous utiliserons dans tous les articles), qui devrait recevoir des événements via HTTPS.
  2. Les événements sont un simple json comme : {"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 être capable de traiter 10 000 événements par seconde.
  4. Il devrait être possible d'évoluer horizontalement en ajoutant simplement de nouvelles instances à notre solution. Et ce serait bien si nous pouvions déplacer la partie avant 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 à la chute de n'importe quelle pièce (jusqu'à un certain nombre bien sûr).

Architecture

En général, pour ce type de tâche, des architectures classiques ont été inventées depuis longtemps pour permettre une mise à l'échelle efficace. La figure montre un exemple de notre solution.

Nous acceptons 10 000 événements dans Yandex.Cloud. Partie 1

Alors ce que nous avons :

1. À gauche se trouvent nos appareils qui génèrent divers événements, qu'il s'agisse de joueurs complétant un niveau de jouet sur un smartphone ou créant une commande dans une boutique en ligne via un navigateur classique. Un événement, comme spécifié dans la spécification, est un simple json qui est envoyé à notre point de terminaison - events.kis.im.

2. Les deux premiers serveurs sont de simples équilibreurs, leurs tâches principales sont :

  • Soyez constamment disponible. Pour ce faire, vous pouvez utiliser, par exemple, keepalived, qui basculera l'IP virtuelle entre les nœuds en cas de problème.
  • Terminez TLS. Oui, nous mettrons fin à TLS sur eux. Premièrement, pour que notre solution soit conforme aux spécifications techniques, et deuxièmement, afin de soulager la charge liée à l'établissement d'une connexion cryptée depuis nos serveurs backend.
  • Équilibrez les demandes entrantes avec les serveurs backend disponibles. Le mot clé ici est accessible. Sur cette base, nous comprenons que les équilibreurs de charge doivent être capables de surveiller nos serveurs avec des applications et d'arrêter d'équilibrer le trafic vers les nœuds défaillants.

3. Après les équilibreurs, nous avons des serveurs d'applications exécutant une application assez simple. Il devrait être capable d'accepter les requêtes entrantes via HTTP, de valider le json envoyé et de mettre les données dans un tampon.

4. Le diagramme montre Kafka comme tampon, bien que, bien entendu, 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 du tampon vers le système de stockage lui-même (plus de détails à ce sujet dans l'article 4).

Cette conception nous permet de redimensionner chaque couche indépendamment horizontalement. Les serveurs backend ne peuvent pas faire face - ajoutons encore une chose - après tout, ce sont des applications sans état et, par conséquent, cela peut être fait même automatiquement. Le tampon de style Kafka ne fonctionne pas : ajoutons plus de serveurs et transférons-y certaines partitions de notre sujet. Clickhouse ne peut pas le gérer - c'est impossible :) En fait, nous connecterons également les serveurs et partagerons les données.

D’ailleurs, si vous souhaitez mettre en œuvre la partie optionnelle de nos spécifications techniques et évoluer dans différentes géolocalisations, alors il n’y a rien de plus simple :

Nous acceptons 10 000 événements dans Yandex.Cloud. Partie 1

Dans chaque géolocalisation nous déployons un équilibreur de charge avec application et kafka. En général, 2 serveurs d'applications, 3 nœuds kafka et un cloud balancer, 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 source du client. Ainsi, les données envoyées par un client américain atterriront sur des serveurs américains. Et les données de l’Afrique sont en 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. En interne, nous analysons les données et les enregistrons dans Clickhouse pour une visualisation ultérieure.

Nous avons donc réglé l'architecture - commençons à secouer Yandex.Cloud !

Rédaction d'une candidature

Avant le Cloud, il faut encore être un peu patient et écrire un service assez simple pour traiter les événements entrants. Nous utiliserons Golang car il a fait ses preuves en tant que langage d'é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 principaux points que je voudrais souligner ici :

1. Lors du 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). La seconde concerne 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 définissons immédiatement les paramètres visant la vitesse de traitement maximale :

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

3. Notre application dispose également d'un client prometheus intégré, qui collecte diverses mesures, telles que :

  • nombre de demandes à notre application ;
  • nombre d'erreurs lors de l'exécution de la requête (impossible de lire la requête post, json cassé, impossible d'écrire sur Kafka) ;
  • temps de traitement d'une demande du client, y compris le temps d'écriture d'un message à Kafka.

4. Trois points finaux que notre application traite :

  • /status - retournez simplement ok pour montrer que nous sommes vivants. Bien que vous puissiez ajouter quelques vérifications, comme la disponibilité du cluster Kafka.
  • /metrics - selon cette URL, le client prometheus renverra les métriques qu'il a collectées.
  • /post est le point de terminaison principal où les requêtes POST contenant json à l'intérieur seront envoyées. Notre application vérifie la validité du json et si tout va bien, elle écrit les données dans le cluster Kafka.

Je ferai une réserve sur le fait que le code n'est pas parfait - il peut (et doit !) être complété. Par exemple, vous pouvez arrêter d'utiliser le net/http intégré et passer au fasthttp plus rapide. Ou vous pouvez gagner du temps de traitement et des ressources CPU en déplaçant la vérification de validité json à une étape ultérieure - lorsque les données sont transférées du tampon vers le cluster Clickhouse.

Outre l'aspect développement du problème, nous avons immédiatement réfléchi à notre future infrastructure et avons décidé de déployer notre application via docker. Le Dockerfile final pour créer 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 auquel je voudrais prêter attention est l'assemblage en plusieurs étapes, qui nous permet de réduire l'image finale de notre conteneur.

Premiers pas dans le cloud

Tout d'abord, inscrivez-vous sur cloud.yandex.ru. Après avoir rempli tous les champs nécessaires, nous créerons un compte et nous accorderons une subvention d'un certain montant, qui pourra être utilisée 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 entre les ressources est la suivante :

Nous acceptons 10 000 événements dans Yandex.Cloud. Partie 1

Vous pouvez créer plusieurs cloud pour un seul 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. D’ailleurs, j’y ferai souvent référence ci-dessous dans le texte. Lorsque j'ai configuré toute l'infrastructure à partir de zéro, la documentation m'a aidé plus d'une fois, je vous conseille donc de l'étudier.

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

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

Si votre spécialiste de la sécurité interne s'empresse d'exécuter des scripts à partir d'Internet, alors, d'une part, vous pouvez ouvrir le script et le lire, et deuxièmement, nous l'exécutons sous notre utilisateur - sans droits root.

Si vous souhaitez installer un client pour Windows, vous pouvez utiliser les instructions ici puis exécutez yc initpour le personnaliser entièrement :

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 un jeton oauth pour gérer le cloud, sélectionner 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 rédigé un très bon plugin pour Terraform pour gérer les ressources cloud. Pour ma part, j'ai préparé un dépôt 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 nous intéressons à 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 accidentellement 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 proxy le domaine principal events.kis.im vers 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 console et Terraform.

Réseaux virtuels

Pour être honnête, vous pouvez ignorer cette étape, car lorsque vous créez un nouveau cloud, vous aurez automatiquement un réseau distinct et 3 sous-réseaux créés - un pour chaque zone de disponibilité. Mais nous aimerions quand même créer un réseau séparé pour notre projet avec son propre adressage. Le schéma général du fonctionnement du réseau dans Yandex.Cloud est présenté dans la figure ci-dessous (honnêtement tiré de https://cloud.yandex.ru/docs/vpc/concepts/)

Nous acceptons 10 000 événements dans Yandex.Cloud. Partie 1

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 créé avec son propre adressage et connecté au réseau général. En conséquence, toutes les ressources cloud qu'il contient peuvent communiquer, même si elles se trouvent 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 opère-t-elle à l'intérieur, a été bien décrit sur Habré.

La création du 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). ).

Initialisez terraform et créez 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.

Super! Nous avons créé notre réseau et sommes désormais prêts à créer nos services internes.

Création de machines virtuelles

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

Les machines virtuelles seront configurées à l'aide d'ansible, donc avant de démarrer terraform, assurez-vous que vous disposez de l'une des dernières versions d'ansible. Et installez les rôles nécessaires 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 se trouve un exemple de fichier de configuration .ansible.cfg que j'utilise. Cela pourrait ê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 est ajoutée, sinon Terraform ne pourra pas se connecter aux machines créées. Bien sûr, je suis tombé sur un bug dans OS X : https://github.com/ansible/ansible/issues/32499#issuecomment-341578864. Pour éviter que cela ne se reproduise, ajoutez une petite variable à env avant de lancer Terraform :

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

Dans le dossier avec terraform nous créons les ressources nécessaires :

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 terminé avec succès (et cela devrait être le cas), 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. surveillance - une machine de surveillance - prometheus & grafana installés dessus. Norme de connexion / mot de passe : admin / admin
  3. kafka est une petite machine sur laquelle kafka est installé, accessible 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 obtenir leurs adresses IP. Tout au long de ce qui suit, j'utiliserai les adresses IP pour me connecter via ssh et tester l'application. Si vous disposez d'un compte cloudflare connecté à terraform, n'hésitez pas à utiliser des noms DNS fraîchement créés.
À propos, lors de la création d'une machine virtuelle, une adresse IP interne et un nom DNS interne sont donnés, vous pouvez donc accéder aux serveurs du réseau par leur nom :

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 le point final avec kafk.

Assemblage de l'application

Génial, il y a des serveurs, il y a une application, il ne reste plus qu'à l'assembler et à la publier. Pour la construction, nous utiliserons la construction Docker habituelle, mais comme stockage d'images, nous utiliserons un service de Yandex - registre de conteneurs. Mais tout d’abord.

Nous copions l'application sur la machine de build, nous connectons via ssh et assemblons l'image :

vozerov@mba:~/events/terraform (master) $ cd ..
vozerov@mba:~/events (master) $ rsync -av app/ [email protected]: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 la lançant et en l'envoyant à 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 succès de l'enregistrement et en indiquant l'identifiant de la partition et le décalage dans lequel le message était inclus. Il ne reste plus qu'à créer un registre dans Yandex.Cloud et à y télécharger notre image (comment procéder en utilisant trois lignes est décrit dans le fichierregistre.tf). Créez un stockage :

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. Plus de détails sur ces méthodes peuvent être trouvés dans la documentation. https://cloud.yandex.ru/docs/container-registry/operations/authentication. Nous utiliserons la clé du 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.

Il ne reste plus qu'à lui créer 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 recevons des informations sur l'identifiant de notre stockage, transférons la clé et nous connectons :

vozerov@mba:~/events/terraform (master) $ scp key.json [email protected]:
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 télécharger l'image dans le registre, nous avons besoin de l'ID du registre du conteneur, nous le récupérons 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 marquons notre image avec un nouveau nom et télé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 vérifier que l'image s'est chargée avec succès :

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

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

yc container registry configure-docker

pour configurer Docker.

Conclusion

Nous avons fait beaucoup de travail et en conséquence :

  1. Nous avons imaginé l'architecture de notre futur service.
  2. Nous avons écrit une application en Golang qui implémente notre logique métier.
  3. Nous l'avons collecté et versé dans un registre de conteneurs privé.

Dans la partie suivante, nous passerons aux choses intéressantes : nous publierons notre application en production et enfin lancerons le chargement dessus. Ne changez pas !

Ce matériel se trouve dans l'enregistrement vidéo de l'atelier ouvert REBRAIN & Yandex.Cloud : Nous acceptons 10 000 requêtes par seconde sur Yandex Cloud - https://youtu.be/cZLezUm0ekE

Si vous souhaitez assister à de tels événements en ligne et poser des questions en temps réel, connectez-vous à DevOps par canal REBRAIN.

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

Si vous avez besoin de migrer vers le cloud ou avez des questions sur votre infrastructure, N'hésitez pas à faire une demande.

PS Nous avons 2 audits gratuits par mois, peut-être que votre projet en fera partie.

Source: habr.com

Ajouter un commentaire