Pranojmë 10 000 evente në Yandex.Cloud. Pjesa 1

Përshëndetje të gjithëve, miq!

* Ky kjo artikull është shkruar mbi motivet e praktikës së hapur REBRAIN & Yandex.Cloud; nëse preferoni të shihni video, mund ta gjeni atë në këtë lidhje — https://youtu.be/cZLezUm0ekE

Kohët e fundit patëm mundësinë të provonim në jet një Yandex.Cloud. Duke qenë se dëshironim ta shqikonim për një kohë të gjatë, ne menjëherë e hodhëm poshtë idenë për të nisur një blog të thjeshtë WordPress me një bazë cloud — shumë e mërzitshme. Pas një reflektimi të shkurtër, vendosëm të zhvillonim diçka të ngjashme me një arkitekturë produksioni për pranimin dhe analizimin e ngjarjeve në kohë reale.

Jam plotësisht i sigurt se shumica dërrmuese e bizneseve online (dhe jo vetëm) mbledhin në një mënyrë ose në një tjetër një mal informacioni rreth përdoruesve të tyre dhe veprimeve të tyre. Të paktën, kjo është e nevojshme për të marrë disa vendime — për shembull, nëse menaxhoni një lojë online, mund të shikoni statistikat për nivelin ku përdoruesit shpesh ngecin dhe fshijnë lojën tuaj. Apo pse përdoruesit largohen nga saiti juaj pa blerë asgjë (përshëndetje, Yandex.Metrika).

Pra, historia jonë: si shkruam një aplikacion në Golang, testuam Kafka vs RabbitMQ vs YQS, shkruam streaming të të dhënave në një klaster Clickhouse dhe vizualizuam të dhënat me ndihmën e Yandex Datalens. Natyrisht, çdo gjë ishte e shoqëruar me përpjekjet infrastrukturale në formën e Docker, Terraform, GitLab CI, dhe, sigurisht, Prometheus. Le të fillojmë!

Menjëherë dua të sqaroj se nuk do të jemi në gjendje ta vendosim gjithçka një herë — për këtë na nevojiten disa artikuj në një seri. Pak fjalë mbi strukturën:

Pjesa 1 (po e lexoni tani). Do të përcaktojmë detyrën teknike dhe arkitekturën e zgjidhjes, si dhe do të shkruajmë aplikacionin në Golang.
Pjesa 2. Ne do ta hedhim aplikacionin tonë në prodhim, do ta bëjmë atë të shkallëzueshëm dhe do të testojmë ngarkesën.
Pjesa 3. Do të përpiqemi të kuptojmë pse duhet të ruajmë mesazhet në një buffer, e jo në skedarë, si dhe do të krahasojmë midis Kafka, RabbitMQ dhe Yandex Queue Service.
Pjesa 4. Do të vendosim një klaster Clickhouse, do të shkruajmë streaming për të transferuar të dhënat atje nga bufferi, dhe do të konfigurojmë vizualizimin në Datalens.
Pjesa 5. Do të sjellim gjithë infrastrukturën në formë të duhur — do të konfiguroni CI/CD duke përdorur GitLab CI, do të lidhim monitorimin dhe zbulimin e shërbimeve me ndihmën e Prometheus dhe Consul.

TL

Së pari, do të formulojmë detyrën teknike — çfarë saktësisht duam të arrijmë në përfundim.

  1. Ne duam të kemi një endpoint si events.kis.im (kis.im — domen testimi që do të përdorim gjatë të gjitha artikujve), i cili duhet të pranojë event-e përmes HTTPS.
  2. Eventet janë një json i thjeshtë si: {"event": "view", "os": "linux", "browser": "chrome"}. Në fazën përfundimtare do të shtojmë pak më shumë fusha, por kjo nuk do të ketë shumë rëndësi. Nëse dëshiron, mund të kalosh në protobuf.
  3. Shërbimi duhet të jetë i aftë të përpunojë 10,000 evenete në sekondë.
  4. Duhet të ketë mundësinë për të u zgjeruar horizontalisht — duke shtuar thjesht instancat e reja në zgjidhjen tonë. Do të ishte mirë nëse mund të zhvillonim pjesën front në lokacione të ndryshme për të zvogëluar latencën gjatë kërkesave nga klientët.
  5. Qëndrueshmëria. Zgjidhja duhet të jetë mjaft e qëndrueshme dhe të jetë në gjendje të mbijetojë kur bien ndonjë pjesë (deri në një numër të caktuar, natyrisht).

Arkitektura

Në të vërtetë, për këtë lloj detyre janë shpikur prej kohësh arkitektura klasike që lejojnë zgjerim efikas. Në figurë është dhënë një shembull i zgjidhjes sonë.

Pranojmë 10 000 evente në Yandex.Cloud. Pjesa 1

Pra, çfarë kemi:

1. Majtas janë pajisjet tona që gjenerojnë evente të ndryshme, qofshin këto kalimi i niveleve nga lojtarët në një lojë në smartphone ose krijimi i një porosie në një dyqan online përmes një shfletuesi të zakonshëm. Një event, siç është e specifikuar në T.K., është një json i thjeshtë që dërgohet në endpoint-in tonë — events.kis.im.

2. Dy serverat e parë janë thjesht balancues, detyrat e tyre kryesore janë:

  • Të jenë gjithmonë të disponueshëm. Për këtë, mund të përdorim, për shembull, keepalived, që do të kalojë IP-in virtual midis nodave në rast problemesh.
  • Të terminoni TLS-në. Po, ne do ta terminoni TLS-në pikërisht aty. Së pari, në mënyrë që zgjidhja jonë të përputhet me T.K., dhe së dyti, për të hequr ngarkesën e krijimit të një lidhjeje të enkriptuar nga serverat tanë backend.
  • Të balancojnë kërkesat e ardhshme në serverat backend të disponueshëm. Fjalë kyçe këtu është — të disponueshëm. Duke e marrë këtë parasysh, arrijmë në kuptimin se balancuesit e ngarkesës duhet të jenë në gjendje të monitorojnë serverat tanë me aplikacione dhe të ndalin balancimin e trafikut në nodet që kanë rënë.

3. Pas balancuesve janë serverat e aplikacionit, ku është e hapur një aplikacion mjaft i thjeshtë. Ai duhet të jetë në gjendje të pranojë kërkesat e ardhshme përmes HTTP, të vlefsojë json-in e dërguar dhe të ruajë të dhënat në një memorie tampon.

4. Si në buffer në skemë është paraqitur kafka, megjithatë, sigurisht, në këtë nivel mund të përdoren edhe shërbime të tjera të ngjashme. Ne do t'i krahasojmë Kafka, rabbitmq dhe yqs në artikullin e tretë.

5. Pika përfundimtare e arkitekturës sonë është Clickhouse — një bazë të dhënash kolonore që lejon ruajtjen dhe përpunimin e një sasi të madhe të dhënash. Në këtë nivel, na nevojitet të transferojmë të dhënat nga bufferi në, në fakt, sistemin e ruajtjes (për këtë do të flasim në artikullin e katërt).

Kjo skemë na lejon të bëjmë horizontal scaling të çdo shtrese në mënyrë të pavarur. Nëse serverët backend nuk arrijnë — do të shtojmë edhe më shumë — sepse ata janë aplikacione stateless, dhe për këtë arsye, kjo mund të bëhet madje në mënyrë automatike. Nëse bufferi në formën e kafkës nuk përballon — do të shtojmë edhe servera dhe do të transferojmë në ata një pjesë të particioneve të temës tonë. Nëse Clickhouse nuk përballon — kjo është e pamundur 🙂 Në të vërtetë, gjithashtu do të shtojmë servera dhe do të shardojmë të dhënat.

Megjithatë, nëse dëshironi të realizoni pjesën opsionale të kërkesës sonë dhe të bëni scaling në gjeolokacione të ndryshme, nuk ka asgjë më të lehtë:

Pranojmë 10 000 evente në Yandex.Cloud. Pjesa 1

Në çdo gjeolokacion ne shtojmë një load balancer me aplikacion dhe kafka. Në përgjithësi, mjaftojnë 2 servera aplikacioni, 3 node të kafkës dhe një balancues të muzikës në cloud, për shembull, cloudflare, i cili do të verifikojë disponueshmërinë e node-ve të aplikacionit dhe do të balancojë kërkesat sipas gjeolokacioneve mbi bazën e adresës IP të klientit. Kështu, të dhënat e dërguara nga një klient amerikan do të arrijnë në serverat amerikanë. Ndërsa të dhënat nga Afrika — në ato afrikan.

Më pas gjithçka është shumë e thjeshtë — përdorim mjetin mirror nga kafka dhe kopjojmë të dhënat nga të gjitha lokacionet në qendrën tonë të të dhënave, e cila ndodhet në Rusi. Brenda ne e analizojmë të dhënat dhe i regjistrojmë ato në Clickhouse për vizualizim të mëtejshëm.

Pra, ne e kuptuam arkitekturën — le të fillojmë të përdorim Yandex.Cloud!

Po shkruajmë aplikacionin

Duhet të presim pak më shumë për Cloud-in dhe të shkruajmë një shërbim mjaft të thjeshtë për përpunimin e ngjarjeve që po vijnë. Do të përdorim golang, sepse ka treguar shumë mirë se është një gjuhë për zhvillimin e aplikacioneve të rrjetit.

Pas një ore kohë (ndoshta edhe disa orë), arrijmë diçka të tillë: https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/main.go.

Cilat janë pikat kryesore që dëshirojmë të theksojmë këtu:

1. Gjatë fillimit të aplikacionit mund të rindizni dy flamuj. Njëri përgjigjet për portin, në të cilin do të dëgjojmë kërkesat http që vijnë (-addr). Tjetri - për adresën e serverit kafka, ku do të shkaqum ngjarjet tona (-kafka):

addr     = flag.String("addr", ":8080", "Adresa TCP për t'u dëgjuar")
kafka    = flag.String("kafka", "127.0.0.1:9092", "Pikat e Kafka")

2. Aplikacioni përdor bibliotekën sarama ([] github.com/Shopify/sarama) për të dërguar mesazhe në klasterin kafka. Ne menjëherë vendosëm konfigurations që janë të orientuara për shpejtësinë maksimale të përpunimit:

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

3. Gjithashtu, në aplikacionin tonë është e integruar një klient prometheus, i cili mbledh metrika të ndryshme, të tilla si:

  • numri i kërkesave për aplikacionin tonë;
  • numri i gabimeve gjatë ekzekutimit të kërkesës (nuk mund të lexohet kërkesa post, json i prishur, nuk mund të shkruhet në kafka);
  • koha e përpunimit të një kërkese nga klienti, duke përfshirë kohën e dërgimit të mesazhit në kafka.

4. Tre endpoint që përpunon aplikacioni ynë:

  • /status — просто возвращаем ok, чтобы показать, что мы живы. Хотя можно и добавить некоторые проверки, типа доступности кафка кластера.
  • /metrics — по этому url prometheus client будет возвращать собранные им метрики.
  • /post — основной endpoint, куда будут приходить POST запросы с json внутри. Наше приложение проверяет json на валидность и если все ок — записывает данные в кафка-кластер.

Dua të theksoj se kodi nuk është perfekt - ai mund të përmirësohet (dhe duhet!). Për shembull, mund të heqim dorë nga përdorimi i net/http të integruar dhe të kalojmë në fasthttp, më të shpejtë. Ose të fitojmë kohë përpunimi dhe burime CPU, duke e zhvendosur kontrollin e vlefshmërisë së json në një fazë më të vonë - kur të dhënat do të kalojnë nga blloku në klasterin clickhouse.

Përveç aspektit zhvillues të çështjes, ne mendojmë menjëherë për infrastrukturën tonë të ardhshme dhe morëm vendimin të zbatojmë aplikacionin tonë përmes docker. Dockerfile përfundimtar për ndërtimin e aplikacionit është - https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/Dockerfile. Në përgjithësi, ai është mjaft i thjeshtë, momenti i vetëm që dua të theksoj është ndërtimi multistage, i cili ndihmon në zvogëlimin e imazhit përfundimtar të kontejnerit tonë.

Hapat e para në re

Së pari, regjistrohemi në cloud.yandex.ru. Pasi të plotësojmë të gjitha fushat e nevojshme, do të na krijohet një llogari dhe do të na jepet një grant për një shumë të caktuar parash, të cilat mund t'i përdorim për testimin e shërbimeve të re. Nëse dëshiron të përsërisësh të gjitha hapat nga artikulli ynë, ky grant do të mjaftojë.

Pas regjistrimit, do të krijohet një re e veçantë për ju dhe katalogu default, ku mund të filloni të krijoni burime të reja të cloud. Në të vërtetë, lidhja e burimeve në Yandex.Cloud duket kështu:

Pranojmë 10 000 evente në Yandex.Cloud. Pjesa 1

Me një llogari mund të krijoni disa cloud-e. Brenda cloud-it, mund të krijoni katalogë të ndryshëm për projekte të ndryshme të kompanisë. Mund të lexoni më shumë rreth kësaj në dokumentacion — https://cloud.yandex.ru/docs/resource-manager/concepts/resources-hierarchy. Për më tepër, më poshtë do të referohem shpesh në të. Kur isha duke konfiguruar të gjithë infrastrukturën nga e para — dokumentacioni më ndihmoi jo pak, prandaj rekomandoj ta studiuesh.

Për të menaxhuar cloud-in, mund të përdorni si ndërfaqen e uebit, ashtu dhe mjetin e komandës — yc. Instalimi kryhet me një komandë (për Linux dhe Mac Os):

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

Nëse brenda jush është aktivizuar ndonjë siguri për ekzekutimin e skripteve nga interneti — së pari, mund të hapni skriptin dhe ta lexoni atë, së dyti, ne e ekzekutojmë atë nën përdoruesin tonë — pa të drejta root.

Nëse dëshironi të instaloni klientin për Windows, mund të përdorni udhëzimin këtu dhe pastaj të ekzekutoni yc init, për ta konfigurur atë plotësisht:

vozerov@mba:~ $ yc init
Mirësevini! Kjo komandë do t'ju kalojë nëpër procesin e konfigurimit.
Ju lutemi shkoni në https://oauth.yandex.ru/authorize?response_type=token&client_id= për të marrë token-in OAuth.

Ju lutemi shkruani token-in OAuth:
Ju lutemi zgjidhni cloud-in për të përdorur:
 [1] cloud-b1gv67ihgfu3bp (id = b1gv67ihgfu3bpt24o0q)
 [2] fevlake-cloud (id = b1g6bvup3toribomnh30)
Ju lutemi shkruani zgjedhjen tuaj numerike: 2
Cloud-i juaj aktual është vendosur në 'fevlake-cloud' (id = b1g6bvup3toribomnh30).
Ju lutemi zgjidhni dosjen për të përdorur:
 [1] default (id = b1g5r6h11knotfr8vjp7)
 [2] Krijoni një dosje të re
Ju lutemi shkruani zgjedhjen tuaj numerike: 1
Dosha juaj aktuale është vendosur në 'default' (id = b1g5r6h11knotfr8vjp7).
A dëshironi të konfiguroni një zonë të parazgjedhur Compute? [Y/n]
Cila zonë dëshironi të përdorni si default për profilin?
 [1] ru-central1-a
 [2] ru-central1-b
 [3] ru-central1-c
 [4] Mos vendosni zonë të parazgjedhur
Ju lutemi shkruani zgjedhjen tuaj numerike: 1
Zona juaj e parazgjedhur Compute është vendosur në 'ru-central1-a'.
vozerov@mba:~ $

Në të përgjithshëm, procesi nuk është i komplikuar — së pari duhet të merrni token-in oauth për të menaxhuar cloud-in, të zgjidhni cloud-in dhe doshën që do të përdorni.

Nëse keni disa llogari ose dosje brenda një cloud-i, mund të krijoni profile shtesë me konfigurime të veçanta përmes yc config profile create dhe të kaloni mes tyre.

Përveç mënyrave të mësipërme, ekipi i Yandex.Cloud ka shkruar një plugin shumë të mirë për terraform për menaxhimin e burimeve cloud. Nga ana ime, kam përgatitur një repozitor git, ku kam përshkruar të gjitha burimet që do të krijohen në kuadër të artikullit — https://github.com/rebrainme/yandex-cloud-events/. Na intereson dega master, le të klonojmë atë lokal:


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/

Të gjitha variablat kryesore që përdoren në terraform janë shkruar në skedarin main.tf. Për të filluar punën, krijoni në dosjen terraform skedarin private.auto.tfvars me përmbajtjen e mëposhtme:

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

Të gjitha variablat mund të merren nga lista e konfiguracionit yc, pasi ne tashmë kemi konfiguruar mjetin e konsolës. Ju rekomandoj ta shtoni menjëherë private.auto.tfvars në .gitignore, për të mos e publikuar rastësisht informacionin privat.

Në private.auto.tfvars ne gjithashtu kemi specifikuar të dhënat nga Cloudflare — për krijimin e regjistrave dns dhe për të përcjellë domenin kryesor events.kis.im në serverët tanë. Nëse nuk doni të përdorni cloudflare, hiqni inicializimin e ofruesit cloudflare në main.tf dhe skedarin dns.tf, i cili është përgjegjës për krijimin e regjistrave të nevojshëm dns.

Ne në punën tonë do të kombinojmë të tri mënyrat — si ndërfaqen web, ashtu edhe mjetin e konsolës dhe terraform.

Rrjetet virtuale

Sinqerisht, ky hap mund të kishte kaluar, sepse kur krijoni një re të re automatikisht do të krijohet një rrjet i veçantë dhe 3 nënrrjete — një për secilën zonë disponueshmërie. Por, çdo mënyrë, do të donim të krijonim një rrjet të veçantë për projektin tonë me adresimin e tij. Diagrami i përgjithshëm i funksionimit të rrjetit në Yandex.Cloud është paraqitur në figurën më poshtë (e marrë sinqerisht nga https://cloud.yandex.ru/docs/vpc/concepts/)

Pranojmë 10 000 evente në Yandex.Cloud. Pjesa 1

Pra, krijoni një rrjet të përbashkët, brenda së cilës burimet do të mund të komunicojnë me njëra-tjetrën. Për secilën zonë disponueshmërie krijohet një nënrrjet me adresimin e tij dhe lidhet me rrjetin e përbashkët. Në fund, të gjitha burimet e cloud-it brenda tij mund të komunikojnë, edhe duke qenë në zona të ndryshme disponueshmërie. Burimet e lidhura me rrjete të ndryshme cloud-i mund ta shohin njëra-tjetrën vetëm përmes adresave të jashtme. Nga ana tjetër, si funksionon kjo magji brenda, është përshkruar mirë në Habr.

Krijimi i rrjetit është përshkruar në skedarin network.tf nga repositori. Atje krijojmë një rrjet privat të përbashkët internal dhe lidhemi me të tri nënrrjete në zona të ndryshme disponueshmërie — internal-a (172.16.1.0/24), internal-b (172.16.2.0/24), internal-c (172.16.3.0/24).

Inicizojmë terraform dhe krijojmë rrjetet:

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.

Shkëlqyer! Ne krijuam rrjetin tonë dhe tani jemi gati për krijimin e shërbimeve tona të brendshme.

Krijimi i makinave virtuale

Për testimin e aplikacionit tonë do të mjaftonte të krijonim dy virtuale — e para na nevojitet për ndërtimin dhe ekzekutimin e aplikacionit, e dyta — për ekzekutimin e kafka, që do ta përdorim për ruajtjen e mesazheve hyrëse. Dhe do të krijojmë edhe një kompjuter, ku do të konfigurojmë prometheus për monitorimin e aplikacionit.

Virtualet do të konfigurohen me ndihmën e ansible, kështu që para se të nisni terraform, sigurohuni që keni instaluar një nga versionet më të fundit të ansibla. Dhe instaloni rolet e nevojshme me ansible galaxy:

vozerov@mba:~\/events\/terraform (master) $ cd ..\/ansible\/ 
vozerov@mba:~\/events\/ansible (master) $ ansible-galaxy install -r requirements.yml
- cloudalchemy-prometheus (master) është instaluar tashmë, duke e anashkaluar.
- cloudalchemy-grafana (master) është instaluar tashmë, duke e anashkaluar.
- sansible.kafka (master) është instaluar tashmë, duke e anashkaluar.
- sansible.zookeeper (master) është instaluar tashmë, duke e anashkaluar.
- geerlingguy.docker (master) është instaluar tashmë, duke e anashkaluar.
vozerov@mba:~\/events\/ansible (master) $

Brenda dosjes ansible ka një shembull të skedarit të konfigurimit .ansible.cfg, që unë e përdor. Mund të jetë i dobishëm.

Para se të krijoni virtualet, sigurohuni që ssh-agent është aktiv dhe çelësi ssh është i shtuar, përndryshe terraform nuk do të mund të lidhet me kompjuterët e krijuar. Natyrisht, unë u takova me një bug në os x: https://github.com/ansible/ansible/issues/32499#issuecomment-341578864. Në mënyrë që ta shmangni një histori të tillë, para se të nisni Terraform, shtoni një variabël të vogël në env:

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

Në dosjen me terraform krijojmë resurset e nevojshme:

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]

Një plan ekzekutimi është gjeneruar dhe shihet më poshtë.
Veprimet e burimeve janë të treguara me simbolet e mëposhtme:
  + krijo

... u anashkalua ...

Plani: 3 për të shtuar, 0 për të ndryshuar, 0 për të shkatërruar.

... u anashkalua ...

Nëse gjithçka përfundoi me sukses (dhe kaq duhet të jetë), do të kemi tre makina virtuale:

  1. build — makina për testimin dhe ndërtimin e aplikacionit. Docker u instalua automatikisht nga ansible.
  2. monitoring — makina për monitorim — në të është instaluar prometheus & grafana. Login / fjalëkalimi standard: admin / admin
  3. kafka — një makinë e vogël me kafka të instaluar, e cila është e aksesueshme në portin 9092.

Le të sigurohemi që të gjithë janë në vend:

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

Burimet janë në vend, dhe nga këtu mund të nxjerrim adresat ip. Nga tani e tutje do të përdor adresat ip për të lidhur me ssh dhe për testimin e aplikacionit. Nëse keni një llogari në cloudflare, të lidhur me terraform, ndihuni të lirë të përdorni emrat e sapo krijuar DNS.
Apropos, kur krijohet makina virtuale, jepet një ip i brendshëm dhe një emër DNS i brendshëm, kështu që mund të adresohemi tek serverat brenda rrjetit përmes emrave:

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
--- statistikat e ping të kafka.ru-central1.internal ---
2 paketa e dërguara, 2 të pranuara, 0% humbje pakete, koha 1001ms
rtt min/avg/max/mdev = 0.625/0.931/1.238/0.308 ms

Kjo na nevojitet për të treguar aplikacionit endpointin me kafkën.

Po ndërtojmë aplikacionin

Shkëlqyer, serverat janë aty, aplikacioni është aty — na mbetet vetëm ta ndërtojmë dhe ta publikojmë. Për ndërtimin do të përdorim docker build të zakonshëm, ndërsa si ruajtje të imazheve do të marrim shërbimin nga yandex — container registry. Por për çdo gjë në radhë.

Kopjojmë aplikacionin në makinën build, hyjmë përmes ssh dhe ndërtojmë imazhin:

vozerov@mba:~\/events\/terraform (master) $ cd ..
vozerov@mba:~\/events (master) $ rsync -av app\/ ubuntu@84.201.132.3:app\/\n\n... skipped ...\n\nsent 3849 bytes  received 70 bytes  7838.00 bytes\/sec\ntotal size is 3644  speedup is 0.93\n\nvozerov@mba:~\/events (master) $ ssh 84.201.132.3 -l ubuntu\nubunt@build:~$ cd app\nubunt@build:~\/app$ sudo docker build -t app .\nSending build context to Docker daemon  6.144kB\nStep 1\/9 : FROM golang:latest AS build\n... skipped ...\n\nSuccessfully built 9760afd8ef65\nSuccessfully tagged app:latest

Gati të bëhet — tani mund ta verifikojmë funksionimin e aplikacionit tonë duke e aktivizuar atë dhe duke e drejtuar në kafka:

ubuntu@build:~\/app$ sudo docker run --name app -d -p 8080:8080 app \/app\/app -kafka=kafka.ru-central1.internal:9092\n\nNga makina lokale mund të dërgojmë një ngjarje testuese dhe të shikojmë përgjigjen:\n\nvozerov@mba:~\/events (master) $ curl -D - -s -X POST -d '{"key1":"data1"}' http:\/\/84.201.132.3:8080\/post\nHTTP\/1.1 200 OK\nContent-Type: application\/json\nDate: Mon, 13 Apr 2020 13:53:54 GMT\nContent-Length: 41\n\n{"status":"ok","partition":0,"Offset":0}\nvozerov@mba:~\/events (master) $

Aplikacioni është përgjigjur me sukses lidhur me regjistrimin dhe identifikimin e id-së së pjesës dhe ofsetit në të cilin është vendosur mesazhi. E vetmja gjë që mbetet është të krijojmë një regjistër në Yandex.Cloud dhe të ngarkojmë atje imazhin tonë (si ta bëjmë këtë me tre rreshta, është përshkruar në skedarin registry.tf). Krijojmë depo:

vozerov@mba:~\/events\/terraform (master) $ terraform apply -target yandex_container_registry.events\n\n... skipped ...\n\nPlan: 1 to add, 0 to change, 0 to destroy.\n\n... skipped ...\n\nApply complete! Resources: 1 added, 0 changed, 0 destroyed.

Për autentifikimin në regjistrin e kontejnerëve ka disa mënyra — me anë të OAuth token, IAM token ose çelësit të llogarisë së shërbimit. Më shumë mbi këto metoda — në dokumentacion. https://cloud.yandex.ru/docs/container-registry/operations/authentication. Ne do të përdorim çelësin e llogarisë së shërbimit, kështu që krijojmë llogarinë:

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\n\n... skipped ...\n\nApply complete! Resources: 3 added, 0 changed, 0 destroyed.

Tani mbetet të krijojmë një çelës për të:

vozerov@mba:~\/events\/terraform (master) $ yc iam key create --service-account-name docker -o key.json\nid: ajej8a06kdfbehbrh91p\nservice_account_id: ajep6d38k895srp9osij\ncreated_at: "2020-04-13T14:00:30Z"\nkey_algorithm: RSA_2048

Marrim informacion mbi id-në e depozitës sonë, dërgojmë çelësin dhe autentifikojmë:

vozerov@mba:~\/events\/terraform (master) $ scp key.json ubuntu@84.201.132.3:\nkey.json                                                                                                                    100% 2392   215.1KB\/s   00:00\n\nvozerov@mba:~\/events\/terraform (master) $ ssh 84.201.132.3 -l ubuntu\n\nubunt@build:~$ cat key.json | sudo docker login --username json_key --password-stdin cr.yandex\nWARNING! Your password will be stored unencrypted in \/home\/ubuntu\/.docker\/config.json.\nConfigure a credential helper to remove this warning. See\nhttps:\/\/docs.docker.com\/engine\/reference\/commandline\/login\/#credentials-store\n\nLogin Succeeded\nubunt@build:~$

Për të ngarkuar imazhin në regjistrin, na nevojitet ID e regjistrit të kontejnerëve, e marrim këtë nga utilitari yc:

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

Pas kësaj, ne e etiketojmë imazhin tonë me emrin e ri dhe e ngarkojmë:

ubuntu@build:~$ sudo docker tag app cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
ubuntu@build:~$ sudo docker push cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
Ngarkimi i referohet depozitës [cr.yandex/crpdgj6c9umdhgaqjfmm/events]
8c286e154c6e: Ngarkuar
477c318b05cb: Ngarkuar
beee9f30bc1f: Ngarkuar
v1: digest: sha256:1dd5aaa9dbdde2f60d833be0bed1c352724be3ea3158bcac3cdee41d47c5e380 madhësia: 946

Mund ta konfirmojmë se imazhi u ngarkua me sukses:

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

Për më tepër, nëse e instaloni utilitarin yc në një makinë me linux, mund të përdorni komandën

yc container registry configure-docker

për të konfiguruar dockerin.

Përfundim

Kemi bërë një punë të madhe dhe të vështirë dhe si rezultat:

  1. Krijuam arkitekturën e shërbimit tonë të ardhshëm.
  2. Shkruam një aplikacion në golang që implementon logjikën tonë të biznesit.
  3. E mbledhëm atë dhe e ngarkuam në një privat container registry.

Në pjesën tjetër do të kalojmë në diçka interesante — do ta ngarkojmë aplikacionin tonë në prodhim dhe përfundimisht do ta testojmë. Mos u ndërlikoni!

Ky material është në formën e një regjistrimi video të praktikës së hapur REBRAIN & Yandex.Cloud: Mirëpresim 10 000 kërkesa për sekondë në Yandex Cloud — https://youtu.be/cZLezUm0ekE

Nëse jeni të interesuar të merrni pjesë në ngjarje të tilla online dhe të bëni pyetje në kohë reale, lidheni me kanalin DevOps by REBRAIN.

Një falënderim të veçantë duam t'i japim Yandex.Cloud për mundësinë e organizimit të një evenimenti të tillë. Linku për ta — https://cloud.yandex.ru/prices

Nëse keni nevojë për një kalim në cloud ose keni pyetje në lidhje me infrastrukturën tuaj, mos hezitoni të lini një kërkesë.

P.S. Ne kemi 2 audita të lira në muaj, ndoshta projekti juaj do të jetë në mesin e tyre.

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster