Acceptemu 10 000 avvenimenti in Yandex.Cloud. Parte 1

Salute à tutti, amichi !

* Questu articulu hè basatu annantu à l'attellu apertu REBRAIN & Yandex.Cloud, se preferite vede u video, pudete truvà à stu ligame - https://youtu.be/cZLezUm0ekE

Recentemente avemu avutu l'uppurtunità di pruvà Yandex.Cloud live. Siccomu ci vulia à pruvà longu è duru, abbandunemu immediatamente l'idea di lancià un blog Wordpress simplice cù una basa di nuvola - era troppu noioso. Dopu qualchì pensamentu, avemu decisu di implementà qualcosa di simile à una architettura di serviziu di produzzione per riceve è analizà avvenimenti in modu quasi in tempu reale.

Sò assolutamente sicuru chì a maiò parte di l'imprese in linea (è micca solu) recullanu in qualchì modu una muntagna d'infurmazioni nantu à i so utilizatori è e so azzioni. À u minimu, questu hè necessariu per piglià certe decisioni - per esempiu, se gestionate un ghjocu in linea, pudete guardà e statistiche à quale l'utilizatori di livellu più spessu si bloccanu è sguassate u vostru ghjoculu. O perchè l'utilizatori lascianu u vostru situ senza cumprà nunda (salutu, Yandex.Metrica).

Allora, a nostra storia: cumu avemu scrittu una applicazione in golang, testatu kafka vs rabbitmq vs yqs, hà scrittu dati in streaming in un cluster Clickhouse è visualizatu i dati cù yandex datalens. Naturalmente, tuttu questu era staghjunatu cù delizie infrastrutturali in forma di docker, terraform, gitlab ci è, sicuru, prometheus. Andemu!

Vogliu fà immediatamente una riservazione chì ùn pudemu micca cunfigurà tuttu in una seduta - per questu avemu bisognu di parechji articuli in a serie. Un pocu nantu à a struttura:

Parte 1 (a stai leghjendu). Decideremu nantu à e specificazioni è l'architettura di a suluzione, è ancu scrive una applicazione in golang.
Parte 2. Rilasciamu a nostra applicazione in pruduzzione, facemu scalabile è testemu a carica.
Parte 3. Pruvemu di capisce perchè avemu bisognu di guardà i missaghji in un buffer è micca in i schedari, è ancu paragunate u serviziu di fila di kafka, rabbitmq è yandex.
Parte 4 Implementaremu un cluster Clickhouse, scriveremu un serviziu di streaming per trasfiriri dati da u buffer quì, è stabilisce a visualizazione in datalens.
Parte 5 Purtemu tutta l'infrastruttura in forma propria - cunfigurà ci/cd usendu gitlab ci, cunnetta u monitoraghju è a scuperta di serviziu cù prometheus è consul.

TK

Prima, formulemu i termini di riferimentu - ciò chì esattamente vulemu ottene u risultatu.

  1. Vulemu avè un puntu finale cum'è events.kis.im (kis.im hè u duminiu di prova chì avemu da aduprà in tutti l'articuli), chì deve riceve avvenimenti cù HTTPS.
  2. L'avvenimenti sò un json simplice cum'è: {"event": "view", "os": "linux", "browser": "chrome"}. À a tappa finale, aghjunghje un pocu più campi, ma questu ùn hà micca un rolu maiò. Se vulete, pudete cambià à protobuf.
  3. U serviziu deve esse capace di processà 10 000 avvenimenti per seconda.
  4. Hè da esse pussibule di scala orizzontalmente solu aghjunghjendu novi istanze à a nostra suluzione. È serà bellu se pudemu spustà a parte frontale à diverse geolocazioni per riduce a latenza per e dumande di i clienti.
  5. Tolleranza à i difetti. A suluzione deve esse abbastanza stabile è esse capace di sopravvive à a caduta di ogni parte (finu à un certu numaru, sicuru).

architettura

In generale, per stu tipu di travagliu, l'architetture classiche sò longu inventate chì permettenu un scaling efficiente. A figura mostra un esempiu di a nostra suluzione.

Acceptemu 10 000 avvenimenti in Yandex.Cloud. Parte 1

Allora ciò chì avemu:

1. A manca sò i nostri dispusitivi chì generanu diversi avvenimenti, sia i ghjucatori chì cumplenu un livellu in un ghjoculu nantu à un smartphone o creanu un ordine in una tenda in linea attraversu un navigatore regulare. Un avvenimentu, cum'è specificatu in a specificazione, hè un json simplice chì hè mandatu à u nostru endpoint - events.kis.im.

2. I primi dui servitori sò balancers simplici, i so compiti principali sò:

  • Siate sempre dispunibili. Per fà questu, pudete aduprà, per esempiu, keepalived, chì cambia l'IP virtuale trà i nodi in casu di prublemi.
  • Termina TLS. Iè, finiremu TLS nantu à elli. Prima, in modu chì a nostra suluzione cumplessi cù e specificazioni tecniche, è in segundu, per allevà u pesu di stabilisce una cunnessione criptata da i nostri servitori backend.
  • Equilibrate e dumande entrate à i servitori backend dispunibili. A parolla chjave quì hè accessibile. Basatu annantu à questu, avemu capitu chì l'equilibriu di carica deve esse capace di monitorà i nostri servitori cù l'applicazioni è impediscenu di equilibrà u trafficu à i nodi falluti.

3. Dopu à i balancers, avemu i servitori di l'applicazioni chì correnu una applicazione abbastanza simplice. Deve esse capace di accettà e dumande entrate via HTTP, cunvalidà u json mandatu è mette i dati in un buffer.

4. U diagramma mostra kafka cum'è un buffer, ancu s'è, sicuru, altri servizii simili ponu esse usatu à questu livellu. Compararemu Kafka, rabbitmq è yqs in u terzu articulu.

5. U penultimu puntu di a nostra architettura hè Clickhouse - una basa di dati columnar chì permette di almacenà è processà una quantità enorme di dati. À questu livellu, avemu bisognu di trasfiriri dati da u buffer à u sistema di almacenamiento stessu (più nantu à questu in l'articulu 4).

Stu disignu ci permette di scala ogni capa indipindentamente horizontale. I servitori di backend ùn ponu micca affruntà - aghjustemu una cosa più - dopu tuttu, sò applicazioni senza statu, è per quessa, questu pò esse fattu ancu automaticamente. U buffer in stile Kafka ùn funziona micca - aghjunghje più servitori è trasfirìu alcune di e partizioni di u nostru tema à elli. Clickhouse ùn pò micca trattà - hè impussibile :) In fatti, avemu ancu cunnette i servitori è sparghje i dati.

A propositu, se vulete implementà a parte facultativa di e nostre specificazioni tecniche è scala in diverse geolocazioni, ùn ci hè nunda di più simplice:

Acceptemu 10 000 avvenimenti in Yandex.Cloud. Parte 1

In ogni geolocalizzazione, implementemu un equilibratore di carica cù l'applicazione è kafka. In generale, i servitori di l'applicazioni 2, i nodi kafka 3 è un equilibratore di nuvola, per esempiu, cloudflare, sò abbastanza, chì verificanu a dispunibilità di i nodi di l'applicazioni è e dumande di equilibriu per geolocation basatu annantu à l'indirizzu IP fonte di u cliente. Cusì, i dati mandati da un cliente americanu sbarcaranu nantu à i servitori americani. E dati da l'Africa sò in africanu.

Allora tuttu hè abbastanza simplice - usemu u strumentu di specchiu da u set Kafka è copià tutte e dati da tutti i lochi à u nostru centru di dati cintrali situatu in Russia. Internamente, analizemu i dati è arregistremu in Clickhouse per a visualizazione successiva.

Allora, avemu risoltu l'architettura - cuminciamu à scuzzulate Yandex.Cloud!

Scrive una applicazione

Prima di u Cloud, avete ancu esse un pocu paziente è scrive un serviziu abbastanza simplice per processà l'avvenimenti entranti. Adupremu golang perchè s'hè pruvatu assai bè cum'è una lingua per scrive applicazioni di rete.

Dopu avè passatu una ora (forse un paru d'ore), avemu qualcosa cum'è questu: https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/main.go.

Chì sò i punti principali chì vogliu nutà quì:

1. Quandu principia l'applicazione, pudete specificà dui bandieri. Unu hè rispunsevuli di u portu nantu à quale avemu da sente e richieste http entranti (-addr). U sicondu hè per l'indirizzu di u servitore kafka induve registreremu i nostri avvenimenti (-kafka):

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

2. L'applicazione usa a biblioteca sarama ([] github.com/Shopify/sarama) per mandà missaghji à u cluster kafka. Fixemu immediatamente i paràmetri destinati à a velocità massima di trasfurmazioni:

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

3. A nostra applicazione hà ancu un cliente prometheus integratu, chì raccoglie diverse metriche, cum'è:

  • numeru di dumande à a nostra applicazione;
  • numeru di errori quandu eseguisce a dumanda (impossibile di leghje a dumanda di post, json rottu, impussibile di scrive à Kafka);
  • tempu di trasfurmazioni per una dumanda da u cliente, cumpresu u tempu per scrive un missaghju à Kafka.

4. Trè endpoints chì a nostra applicazione processa:

  • /status - simpricimenti vultà bè per dimustrà chì simu vivi. Ancu s'ellu pudete aghjunghje certi cuntrolli, cum'è a dispunibilità di u cluster Kafka.
  • /metrics - secondu questu url, u cliente prometheus restituverà e metriche chì hà cullatu.
  • / post hè u puntu finale principale induve e richieste POST cù json in l'internu seranu mandate. A nostra applicazione verifica u json per a validità è se tuttu hè bè, scrive i dati à u cluster Kafka.

Fararaghju una riservazione chì u codice ùn hè micca perfettu - pò (è deve!) esse cumpletu. Per esempiu, pudete piantà di utilizà a rete / http integrata è cambià à u più veloce http. O pudete guadagnà u tempu di trasfurmazioni è e risorse di CPU movendu u cuntrollu di validità json à una tappa più tardi - quandu i dati sò trasferiti da u buffer à u cluster di clickhouse.

In più di u latu di sviluppu di u prublema, avemu pensatu immediatamente à a nostra infrastruttura futura è decisu di implementà a nostra applicazione via docker. L'ultime Dockerfile per custruisce l'applicazione hè https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/Dockerfile. In generale, hè abbastanza simplice, l'unicu puntu chì mi piacerebbe attentu hè l'assemblea multistage, chì ci permette di riduce l'imaghjini finali di u nostru containeru.

I primi passi in u nuvulu

Prima di tuttu, registrate cloud.yandex.ru. Dopu à cumplettà tutti i campi nicissarii, avemu da esse creatu un contu è datu una cuncessione per una certa quantità di soldi, chì pò esse usata à pruvà servizii nuvola. Se vulete ripetiri tutti i passi da u nostru articulu, sta cuncessione deve esse abbastanza per voi.

Dopu a registrazione, una nuvola separata è un repertoriu predeterminatu seranu creati per voi, in quale pudete inizià a creazione di risorse di nuvola. In generale, in Yandex.Cloud, a rilazioni di risorse pare cusì:

Acceptemu 10 000 avvenimenti in Yandex.Cloud. Parte 1

Pudete creà parechje nuvole per un contu. È in u nuvulu, fate diverse cartulari per i prughjetti di a cumpagnia. Pudete leghje più nantu à questu in a documentazione - https://cloud.yandex.ru/docs/resource-manager/concepts/resources-hierarchy. In modu, spessu si riferite à quì sottu in u testu. Quandu aghju stallatu tutta l'infrastruttura da zero, a ducumentazione m'hà aiutatu più di una volta, cusì vi cunsigliu di studià.

Per gestisce u nuvulu, pudete aduprà l'interfaccia web è l'utilità di cunsola - yc. L'installazione hè fatta cù un cumandamentu (per Linux è Mac Os):

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

Se u vostru specialista in a sicurezza interna hè in furia per eseguisce script da Internet, allora, prima, pudete apre u script è leghje, è in segundu, l'avemu eseguitu sottu u nostru utilizatore - senza diritti di root.

Se vulete installà un cliente per Windows, pudete aduprà l'istruzzioni ccà e poi eseguite yc initper persunalizà cumplettamente:

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:~ $

In principiu, u prucessu hè simplice - prima avete bisognu di ottene un token oauth per gestisce u nuvulu, selezziunate u nuvulu è u cartulare chì vi aduprà.

Se tenete parechji cunti o cartulare in u stessu nuvulu, pudete creà profili supplementari cù paràmetri separati via yc config profile create and switch between them.

In più di i metudi di sopra, a squadra Yandex.Cloud hà scrittu assai bè plugin per terraform per a gestione di risorse cloud. Per a mo parte, aghju preparatu un repository git, induve aghju descrittu tutte e risorse chì seranu create in parte di l'articulu - https://github.com/rebrainme/yandex-cloud-events/. Semu interessati à u ramu maestru, clonemu in u locu:


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/

Tutti i variàbili principali chì sò usati in terraform sò scritti in u schedariu main.tf. Per principià, crea un schedariu private.auto.tfvars in u cartulare terraform cù u cuntenutu seguente:

# 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 = ""

Tutte e variàbili ponu esse pigliate da a lista di cunfigurazione yc, postu chì avemu digià cunfiguratu l'utilità di cunsola. Vi cunsigliu di aghjunghje immediatamente private.auto.tfvars à .gitignore, per ùn publicà accidentalmente dati privati.

In private.auto.tfvars avemu ancu specificatu dati da Cloudflare - per creà registri DNS è proxy u duminiu principali events.kis.im à i nostri servitori. Se ùn vulete micca usà cloudflare, allora sguassate l'inizializazione di u fornitore di cloudflare in main.tf è u schedariu dns.tf, chì hè rispunsevule per creà i registri dns necessarii.

In u nostru travagliu, combineremu tutti i trè metudi - l'interfaccia web, l'utilità di cunsola è terraform.

Reti virtuali

Per esse onesto, pudete saltà stu passu, postu chì quandu create un novu nuvulu, averete automaticamente una rete separata è 3 subnets creati - unu per ogni zona di dispunibilità. Ma vulemu ancu fà una reta separata per u nostru prughjettu cù u so propiu indirizzu. U schema generale di u funziunamentu di a reta in Yandex.Cloud hè mostratu in a figura sottu (onestamente pigliata da https://cloud.yandex.ru/docs/vpc/concepts/)

Acceptemu 10 000 avvenimenti in Yandex.Cloud. Parte 1

Cusì, crea una reta cumuna in quale e risorse ponu cumunicà cù l'altri. Per ogni zona di dispunibilità, una subnet hè creata cù u so propiu indirizzu è cunnessu à a reta generale. In u risultatu, tutte e risorse di nuvola in questu ponu cumunicà, ancu s'ellu sò in diverse zoni di dispunibilità. I risorse cunnessi à e diverse rete di nuvola ponu vede l'altri solu per indirizzi esterni. Per via, cumu funziona sta magia in l'internu, era ben descritta in Habré.

A creazione di a rete hè descritta in u schedariu network.tf da u repository. Ci creemu una rete privata cumuna interna è cunnetta trè subnets à questu in diverse zoni di dispunibilità - interna-a (172.16.1.0/24), interna-b (172.16.2.0/24), interna-c (172.16.3.0/24). ).

Inizializza terraform è crea rete:

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.

Perfettu! Avemu criatu a nostra reta è avà sò pronti à creà i nostri servizii internu.

Creazione di macchine virtuali

Per pruvà l'applicazione, avemu solu bisognu di creà duie macchine virtuali - avemu bisognu di u primu per custruisce è eseguisce l'applicazione, u sicondu per eseguisce kafka, chì avemu aduprà per almacenà i missaghji entranti. È creeremu una altra macchina induve cunfiguremu prometheus per monitorà l'applicazione.

E macchine virtuali seranu cunfigurate cù ansible, cusì prima di inizià a terraform, assicuratevi chì avete una di l'ultime versioni di ansible. È installate i roli necessarii cù a galaxia ansible:

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) $

Dentru u cartulare ansible ci hè un esempiu di schedariu di cunfigurazione .ansible.cfg chì aghju utilizatu. Puderia esse utile.

Prima di creà macchine virtuali, assicuratevi chì avete ssh-agent in esecuzione è una chjave ssh aghjunta, altrimenti terraform ùn serà micca capace di cunnette cù e macchine create. Naturalmente, aghju trovu un bug in os x: https://github.com/ansible/ansible/issues/32499#issuecomment-341578864. Per impediscenu chì questu succede di novu, aghjunghje una piccula variabile à env prima di lancià Terraform:

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

In u cartulare cù terraform creemu i risorse necessarii:

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 ...

Se tuttu hè finitu cù successu (è duverebbe esse), allora averemu trè macchine virtuali:

  1. build - una macchina per pruvà è custruisce una applicazione. Docker hè stata installata automaticamente da Ansible.
  2. surviglianza - una macchina di surviglianza - prometheus & grafana stallati nantu à questu. Login / password standard: admin / admin
  3. kafka hè una piccula macchina cù kafka installata, accessibile in u portu 9092.

Assicuratevi chì sò tutti in u locu:

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 |
+----------------------+------------+---------------+---------+---------------+-------------+

I risorse sò in u locu, è da quì pudemu avè i so indirizzi IP. In tuttu ciò chì seguita aduprà l'indirizzi IP per cunnette via ssh è pruvà l'applicazione. Sì avete un contu cloudflare cunnessu à terraform, sentite liberu di utilizà nomi DNS appena creati.
In modu, quandu crea una macchina virtuale, una IP interna è un nome DNS internu sò datu, cusì pudete accede à i servitori in a reta per nome:

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

Questu serà utile per noi per indicà à l'applicazione l'endpoint cù kafk.

Assembla l'applicazione

Grande, ci sò servitori, ci hè una applicazione - tuttu ciò chì resta hè di assemblellu è di publicà. Per a custruzione useremu u solitu docker build, ma cum'è un almacenamentu di l'imaghjini useremu un serviziu da Yandex - container registry. Ma prima cosa prima.

Copiemu l'applicazione à a macchina di custruzzione, login via ssh è assemblemu l'imaghjini:

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

A mità di a battaglia hè fatta - avà pudemu verificà a funziunalità di a nostra applicazione lanciandula è mandendu à 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'applicazione hà rispostu cù successu di a registrazione è indicà l'id di a partizione è l'offset in quale u messagiu era inclusu. Tuttu ciò chì resta da fà hè di creà un registru in Yandex.Cloud è cullà a nostra maghjina quì (cumu per fà questu cù trè linee hè descrittu in u schedariu registry.tf). Crea un almacenamentu:

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.

Ci hè parechje manere di autentificà in u registru di u containeru - utilizendu un token d'auth, un token iam, o una chjave di u contu di serviziu. Più dettagli nantu à sti metudi ponu esse truvati in a documentazione. https://cloud.yandex.ru/docs/container-registry/operations/authentication. Avemu aduprà a chjave di u contu di serviziu, cusì creemu un contu:

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.

Avà tuttu ciò chì resta hè di fà una chjave per questu:

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

Ricevemu infurmazioni nantu à l'id di u nostru almacenamentu, trasfiriri a chjave è accede:

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:~$

Per carica l'imaghjini à u registru, avemu bisognu di l'ID di registru di u containeru, pigliamu da l'utilità yc:

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

Dopu quì, tagghemu a nostra maghjina cù un novu nome è carichemu:

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

Pudemu verificà chì l'imaghjina hè stata caricata bè:

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

Per via, se installate l'utilità yc in una macchina Linux, pudete aduprà u cumandamentu

yc container registry configure-docker

per cunfigurà docker.

cunchiusioni

Avemu fattu assai travagliu duru è u risultatu:

  1. Avemu ghjuntu cù l'architettura di u nostru serviziu futuru.
  2. Avemu scrittu una applicazione in golang chì implementa a nostra logica cummerciale.
  3. L'avemu cullatu è l'avemu versatu in un registru privatu di cuntainer.

In a prossima parte, andemu à e cose interessanti - libereremu a nostra applicazione in produzzione è infine lanciamu a carica nantu à questu. Ùn cambiate micca!

Stu materiale hè in l'arregistramentu video di l'attellu apertu REBRAIN & Yandex.Cloud: Accettemu 10 000 richieste per seconda in Yandex Cloud - https://youtu.be/cZLezUm0ekE

Sè site interessatu à assistisce à tali avvenimenti in linea è à dumandà dumande in tempu reale, cunnetta canale DevOps da REBRAIN.

Vulemu dì un ringraziu speciale à Yandex.Cloud per l'uppurtunità di accoglie un tali avvenimentu. Link à elli - https://cloud.yandex.ru/prices

Sè avete bisognu di passà à u nuvulu o avete dumande nantu à a vostra infrastruttura, sentite liberu di lascià una dumanda.

PS Avemu 2 auditi gratuiti per mese, forsi u vostru prughjettu serà unu di elli.

Source: www.habr.com

Add a comment