Pranojmë 10,000 ngjarje në Yandex.Cloud. Pjesa 1

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

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

Së fundmi, patëm mundësinë të provonim nga afër Yandex.Cloud. Duke pasur dëshirën për të eksperimentuar gjatë dhe thellësisht, ne menjëherë hoqëm dorë nga ideja e lançimit të një blogu të thjeshtë WordPress me një bazë cloud — ishte shumë e mërzitshme. Pas një reflektimi të shkurtër, vendosëm të zhvillojmë diçka të ngjashme me një arkitekturë prodhimi të shërbimit për pranim dhe analizim të eventeve në kohë reale.

Jam plotësisht i sigurt që shumica dërrmuese e bizneseve online (dhe jo vetëm) përmbledhin në një mënyrë ose në një tjetër një mal informacioni mbi përdoruesit e tyre dhe veprimet e tyre. Të paktën, kjo është e nevojshme për marrjen e disa vendimeve — për shembull, nëse menaxhoni një lojë online — mund të shikoni statistikat mbi nivelin ku përdoruesit përfundojnë më shpesh dhe heqin qafe lojën tuaj. Ose pse përdoruesit largohen nga faqja 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ë klasterin Clickhouse dhe vizualizuam të dhënat me ndihmën e yandex datalens. Natyrisht, gjithçka ishte e shoqëruar me bihit të infrastrukturës në formën e docker, terraform, gitlab ci dhe, sigurisht, prometheus. Le të fillojmë!

Menjëherë duam të theksojmë se nuk do të jemi në gjendje ta konfiguroni të gjithë këtë menjëherë — për këtë na duhen disa artikuj në një seri. Pak rreth strukturës:

Pjesa 1 (ju e lexoni këtë). Ne do të përcaktojmë kërkesat dhe arkitekturën e zgjidhjes, si dhe do të shkruajmë aplikacionin në golang.
Pjesa 2. Ne do ta nxjerrim aplikacionin tonë në prodhim, do ta bëjmë atë të shkallëzueshëm dhe do ta testojmë ngarkesën.
Pjesa 3. Do të përpiqemi të kuptojmë pse na nevojitet të ruajmë mesazhet në një tampon dhe jo në skedarë, si dhe do të krahasojmë mes vete kafka, rabbitmq dhe shërbimin e radhëve yandex.
Pjesa 4. Do të zhvillojmë klasterin Clickhouse, do të shkruajmë streaming për të transferuar të dhëna nga tamponi atje, dhe do të konfigurujemy vizualizimin në datalens.
Pjesa 5. Do ta sjellim gjithë infrastrukturen në gjendjen e duhur — do të konfigurimi ci/cd, duke përdorur gitlab ci, dhe do të lidhim monitorimin dhe zbulimin e shërbimeve me ndihmën e prometheus dhe consul.

Kërkesat

Fillimi, do të formulojmë një detyrë teknike — çfarë saktësisht duam të arrijmë në fund.

  1. Ne duam të kemi një endpoint të tipit events.kis.im (kis.im — një domen testimi, që do të përdorim gjatë të gjithë artikujve), i cili duhet të pranojë ngjarje nëpërmjet HTTPS.
  2. Ngjarjet janë një JSON i thjeshtë i tipit: {"event": "view", "os": "linux", "browser": "chrome"}. Në fazën finale do të shtojmë disa fusha të tjera, por kjo nuk do të ketë një rol të madh. Nëse ka dëshirë — mund të kalojmë në protobuf.
  3. Shërbimi duhet të jetë në gjendje të përpunojë 10,000 ngjarje në sekondë.
  4. Duhet të ketë mundësinë për t'u shkallëzuar horizontalisht — thjesht duke shtuar instancat e reja në zgjidhjen tonë. Dhe do të ishte mirë nëse do të ishim në gjendje të vendosnim pjesën frontale në lokacione të ndryshme gjeografike për të ulur latency 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ë gjatë rënies së çdo pjese (deri në një numër të caktuar, natyrisht).

Arkitektura

Për këtë lloj problemi, janë shpikur prej kohësh arkitekturat klasike, të cilat lejojnë shkallëzimin e efektshëm. Në figurë është paraqitur një shembull i zgjidhjes sonë.

Pranojmë 10,000 ngjarje në Yandex.Cloud. Pjesa 1

Pra, çfarë kemi:

1. Në anën e majtë janë pajisjet tona që gjenerojnë ngjarje të ndryshme, qofshin këto kalime të niveleve të lojtarëve në lojëra për smartphone ose krijimi i porosive në internet nëpërmjet një shfletuesi të zakonshëm. Ngjarja, siç është e specifikuar në kërkesat teknikë, është një json i thjeshtë që dërgohet në endpoint-in tonë — events.kis.im.

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

  • Të jenë gjithmonë të qasshëm. Për këtë, mund të përdorim, për shembull, keepalived, i cili do të kalojë IP-në virtuale mes node-ve në rast problemesh.
  • Të përfundojnë TLS. Po, ne do ta përfundojmë TLS-në saktësisht tek ata. Së pari, që zgjidhja jonë të përputhet me kërkesat teknike, dhe së dyti, për të lehtësuar ngarkesën e vendosjes së një lidhjeje të enkriptuar nga serverët tanë të backend-it.
  • Të balancojnë kërkesat hyrëse në serverët e disponueshëm të backend-it. Fjala kyçe këtu është — të disponueshëm. Duke e bazuar këtë, arrijmë në përfundimin se balancuesit e ngarkesës duhet të jenë në gjendje të monitorojnë serverët tanë me aplikacionet dhe të ndalojnë balancimin e trafikut në node-t e rëna.

3. Pas balancuesve, ne kemi serverë aplikacionesh, mbi të cilët është e instaluar një aplikacion mjaft i thjeshtë. Ai duhet të jetë në gjendje të pranojë kërkesa hyrëse nëpërmjet HTTP, të validejë JSON-in e dërguar dhe të ruajë të dhënat në një bufër.

4. Si bufër, në skemë paraqitet Kafka, megjithatë, natyrisht, në këtë nivel mund të përdoren edhe shërbime të tjera të ngjashme. Ne do të krahasojmë Kafka, RabbitMQ dhe YQS në artikullin e tretë.

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

Një skemë e tillë na lejon të shkallëzojmë horizontalisht çdo shtresë në mënyrë të pavarur. Nëse serverët e backend-it nuk përballojnë — do të shtojmë më shumë — për shkak se ata janë aplikacione stateless, kështu që është e mundur ta bëjmë këtë edhe në mënyrë automatike. Nëse bufri në formën e kafkës nuk funksionon — do të shtojmë edhe serverë dhe do të transferojmë një pjesë të particioneve të temës sonë mbi to. Nëse Clickhouse nuk përballon — kjo është e pamundur 🙂 Në të vërtetë, gjithashtu do të shtojmë serverë dhe do të kryejmë sharding të të dhënave.

Në fakt, nëse dëshironi të realizoni pjesën opsionale të specifikimeve tona dhe të bëni shpërndarje në geografitë e ndryshme, nuk ka asgjë më të thjeshtë:

Pranojmë 10,000 ngjarje në Yandex.Cloud. Pjesa 1

Në çdo geografitë ne vendosim një balancues ngarkese me aplikacionin dhe kafka. Në thelb, mjafton të kemi 2 serverë aplikacionesh, 3 node kafka dhe një balancues në rrjetin cloud, për shembull, cloudflare, i cili do të kontrollojë disponueshmërinë e node-ve të aplikacionit dhe do të balancojë kërkesat për geografitë në bazë të IP-adresës burimore 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 do të shkojnë në ato afrikane.

Pastaj gjithçka është shumë e thjeshtë — përdorim mjetin mirror nga grupi i kafkës dhe kopjojmë të gjitha të dhënat nga të gjitha lokacionet në qendrën tonë të të dhënave në Rusi. Brenda i analizojmë të dhënat dhe i regjistrojmë ato në Clickhouse për vizualizim të mëvonshëm.

Keshtu, me arkitekturën jemi të qartë — le të fillojmë të lëvizim Yandex.Cloud!

Shkruajmë aplikacionin

Për të kaluar në Re, do të duhet të presim pak dhe të shkruajmë një shërbim mjaft të thjeshtë për të trajtuar ngjarjet e mbërritjes. Ne do të përdorim golang, sepse ai ka treguar shumë mirë veten si një gjuhë për shkruar aplikacione rrjetesh.

Pasi të kemi kaluar një orë (ndoshta edhe dy), arrijmë diçka të tillë: https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/main.go.

Cilat janë pikat kryesore që do të doja të theksoja këtu:

1. Kur fillojmë aplikacionin, mund të tregojmë dy flamuj. Njëri lidhet me portin ku do të dëgjojmë kërkesat http që vijnë (-addr). Tjetri — me adresën e serverit kafka, ku do të regjistrojmë ngjarjet tona (-kafka):

addr     = flag.String("addr", ":8080", "Adresa TCP për të 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 dërgimin e mesazheve në klasterin kafka. Ne menjëherë kemi vendosur cilësimet, të orientuara për maksimumin e shpejtësisë së 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ë integruar një klient prometheus, i cili grumbullon metrika të ndryshme, si:

  • numri i kërkesave në aplikacionin tonë;
  • numri i gabimeve gjatë ekzekutimit të kërkesës (nuk është e mundur të lexohen kërkesat post, JSON i dëmtuar, nuk është e mundur të shkruhet në kafkë);
  • koha e përpunimit të një kërkese nga klienti, duke përfshirë kohën e regjistrimit të mesazhit në kafkë.

3. Tre endpoint'ët që përpunon aplikacioni ynë:

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

Dua të them se kodi nuk është perfekt — mund (dhe duhet!) të përmirësohet. 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 bërë kontrollin e vlefshmërisë së JSON në një etapë më vonë — kur të dhënat do të transferohen nga buffer në klasterin ClickHouse.

Përveç aspektit zhvillues të çështjes, ne menduam menjëherë për infrastrukturën tonë të ardhshme dhe morëm vendim të vendosim aplikacionin tonë përmes Docker. Dockerfile përfundimtar për ndërtimin e aplikacionit — 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ë dëshiroj të theksoj është ndërtimi multistage, i cili lejon të zvogëlohet imazhi përfundimtar i kontejnerit tonë.

Hapat e parë në cloud

Së pari, regjistrohemi në cloud.yandex.ru. Pasi të plotësoni të gjitha fushat e nevojshme, do të krijohet një llogari për ju dhe do të jepet një grant për një shumë të caktuar parash, e cila mund të përdoret për testimin e shërbimeve të cloud. Nëse dëshironi të përs повторoni të gjitha hapat nga artikulli ynë, ky grant duhet të mjaftojë për ju.

Pas regjistrimit, do t'ju krijohet një cloud i veçantë dhe një katalog default, ku mund të filloni të krijoni burime cloud. Në përgjithësi, lidhja e burimeve në Yandex.Cloud duket si më poshtë:

Pranojmë 10,000 ngjarje në Yandex.Cloud. Pjesa 1

Me një llogari, mund të krijoni disa cloud. Brenda një cloud, mund të krijoni kataloge të ndryshme për projekte të ndryshme të kompanisë. Më shumë rreth kësaj mund të lexoni në dokumentacionin — https://cloud.yandex.ru/docs/resource-manager/concepts/resources-hierarchy. A, për më tepër, më poshtë në tekst do të referohem shpesh tek ai. Kur e konfiguroni të gjithë infrastrukturën nga e para — dokumentacioni më ka ndihmuar shumë herë, ndaj e rekomandoj që ta studioni.

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

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

Nëse ju ka shqetësuar një gardian i brendshëm lidhur me ekzekutimin e skripteve nga interneti, së pari, mund ta hapni skriptin dhe ta lexoni, dhe së dyti, ne e ekzekutojmë atë me llogarinë tonë — pa të drejta rrotull.

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 konfigurimin e tij plotësisht:

vozerov@mba:~ $ yc init
Mirësevini! Ky komandë do t'ju çojë përmes procesit të konfigurimit.
Më lutni shkoni në https://oauth.yandex.ru/authorize?response_type=token&client_id= për të marrë tokenin OAuth.

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

Në parim, procesi është i thjeshtë — së pari duhet të merrni tokenin oauth për të menaxhuar cloud-in, të zgjidhni cloud-in dhe folderin që do të përdorni.

Nëse keni disa llogari ose dosje brenda një njësie të vetme, mund të krijoni profile të tjera me cilësime të ndara përmes yc config profile create dhe të kaloni midis tyre.

Përveç mënyrave të përmendura më sipër, ekipi i Yandex.Cloud ka shkruar një plugin shumë të mirë për terraform për menaxhimin e burimeve të cloud. Nga ana ime, kam përgatitur një repositore git, ku e kam përshkruar të gjitha burimet që do të krijohen në kuadër të këtij artikulli — https://github.com/rebrainme/yandex-cloud-events/. Na intereson dega master, le të e tërheqim 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ë të shkruara në skedarin main.tf. Për të filluar, krijoni një skedare private.auto.tfvars në dosjen terraform 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 yc config list, pasi ne tashmë e kemi konfigurimin e utilitarit të konsolës. Ju rekomandoj që menjëherë ta shtoni private.auto.tfvars në .gitignore, në mënyrë që të mos publikoni të dhëna private.

Në private.auto.tfvars ne gjithashtu kemi specifikuar të dhënat nga Cloudflare — për krijimin e regjistrave DNS dhe për të proksuar domenin kryesor events.kis.im në serverët tanë. Nëse nuk dëshironi 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ë tre metodat — si ndërfaqen e web-it, ashtu edhe utilitarin e konsolës, dhe terraform.

Rrjetet virtuale

Të drejtën e them, hapi i këtij mund të ndalohet, pasi gjatë krijimit të një cloud-i të ri do të krijohet automatikisht një rrjet i veçantë dhe 3 nënrrjete — një për çdo zonë të disponueshmërisë. Por megjithatë, do të doja të bënim një rrjet të veçantë për projektin tonë me adresimin e tij. Schemi e përgjithshme e funksionimit të rrjetit në Yandex.Cloud paraqitet në figurën më poshtë (e marrë me sinqeritet nga https://cloud.yandex.ru/docs/vpc/concepts/)

Pranojmë 10,000 ngjarje në Yandex.Cloud. Pjesa 1

Kështu, po krijoni një rrjet të përbashkët, brenda të cilit burimet mund të komunikojnë mes tyre. Për çdo zonë disponueshmërie krijohet një nënrrjet me adresimin e vet dhe lidhet me rrjetin e përbashkët. Si rezultat, të gjitha burimet në atë rrjet mund të komunikojnë, madje edhe nëse ndodhen në zona të ndryshme disponueshmërie. Burimet e lidhura me rrjete të ndryshme cloud mund të shikojnë njëra-tjetrën vetëm përmes adresave të jashtme. Për më tepër, si funksionon kjo magji brenda, është përshkruar mirë në Habrë.

Krijimi i rrjetit është përshkruar në skedarin network.tf të depozitës. Atje krijojmë një rrjet privat të përbashkët internal dhe e lidhim me tre 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).

Inicijalizojmë 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 kemi krijuar rrjetin tonë dhe tani jemi gati për të krijuar shërbimet tona të brendshme.

Krijimi i makinave virtuale

Për testimin e aplikacionit, do na duhet të krijojmë dy makina virtuale — e para do na nevojitet për ndërtimin dhe ekzekutimin e aplikacionit, e dyta — për të ekzekutuar kafka, të cilën do ta përdorim për ruajtjen e mesazheve hyrëse. Dhe do të krijojmë një makinë tjetër, ku do të konfiguroni prometheus për monitorimin e aplikacionit.

Virtualët do të konfigurohen me ndihmën e ansible, kështu që para se të nisni terraform, sigurohuni që të keni një nga versionet më të fundit të ansible. 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 u anashkaluar.
- cloudalchemy-grafana (master) është instaluar tashmë, duke u anashkaluar.
- sansible.kafka (master) është instaluar tashmë, duke u anashkaluar.
- sansible.zookeeper (master) është instaluar tashmë, duke u anashkaluar.
- geerlingguy.docker (master) është instaluar tashmë, duke u 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 virtualët, sigurohuni që keni nisur ssh-agent dhe keni shtuar çelësin ssh, në të kundërt terraform nuk do të mund të lidhet me makinat e krijuara. Sigurisht, kam ng encountered një bug në os x: https://github.com/ansible/ansible/issues/32499#issuecomment-341578864. Për të mos u ndier në një histori të tillë, para nisjes së 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ë burimet 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: Duke gjendjen... [id=enp2g2rhile7gbqlbrkr]
data.yandex_compute_image.ubuntu_image: Duke gjendjen...
yandex_vpc_subnet.internal-a: Duke gjendjen... [id=e9b1dad6mgoj2v4funog]

Një plan ekzekutimi është gjeneruar dhe shfaqet më poshtë.
Veprimet për burimet tregohen 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 ka përfunduar me sukses (siç duhet të jetë), atëherë 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 aksesueshme përmes portit 9092.

Le të sigurohemi që të gjitha 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 e tyre IP. Në vazhdim do të përdor adresat IP për lidhje përmes SSH dhe testimin e aplikacionit. Nëse keni një llogari në Cloudflare, të lidhur me Terraform, mos hezitoni të përdorni emrat e DNS të sapo krijuar.
Për më tepër, kur krijoni një makinë virtuale, ndryshohet një IP e brendshme dhe një emër DNS i brendshëm, kështu që mund të qaseni në serverat brenda rrjetit me emra:

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

Kjo do na ndihmojë për të specifikuar një endpoint për aplikacionin me kafkën.

Krijojmë aplikacionin

Shkëlqyer, serverët janë aty, aplikacioni është gati — tani mbetet vetëm ta krijojmë dhe ta publikojmë. Për krijimin do të përdorim docker build të zakonshëm, ndërsa si ruajtje të imazheve do të përdorim shërbimin nga Yandex — container registry. Por gjithçka me rend.

Kopjojmë aplikacionin në makinën build, hyjmë me ssh dhe krijojmë imazhin:

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

... u anashkalua ...

dërguar 3849 bytes  marrë 70 bytes  7838.00 bytes/sec
totali është 3644  shpejtimi është 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 .
Duke dërguar kontekstin e ndërtimit në daemon-in Docker  6.144kB
Hapi 1/9 : FROM golang:latest AS build
... u anashkalua ...

Me sukses u ndërtua 9760afd8ef65
Me sukses u etiketua app:latest

Pjesa e punës është bërë — tani mund të kontrollojmë 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</code>

Nga makina lokale mund të dërgoni një event provues dhe të shikoni përgjigjen:

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

Aplikimi ka përgjigjur me sukses regjistrimin dhe duke treguar id-në e particionit dhe offsetin ku u regjistrua mesazhi. Tani duhet të krijojmë një registry në Yandex.Cloud dhe të ngarkojmë atje imazhin tonë (si ta bëjmë këtë me tre rreshta, përshkruhet në skedarin registry.tf). Po krijojmë depo:

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

... u skipua ...

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

... u skipua ...

Aplikimi përfundoi! Burimet: 1 e shtuar, 0 e ndryshuar, 0 e shkatërruar.

Për autentifikimin në container registry ka disa mënyra — me anë të oauth token, iam token ose çelësit të llogarisë së shërbimit. Më shumë detaje mbi këto metoda janë 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ë po 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

... u skipua ...

Aplikimi përfundoi! Burimet: 3 e shtuar, 0 e ndryshuar, 0 e shkatërruar.

Tani na mbetet të bëjmë një çelës për të:

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

Merrni informacion mbi id-në e depozitës tonë, kaloni çelësin dhe autentikohuni:

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

Për të ngarkuar imazhin në regjistrin, na nevojitet ID e container registry, e marrim 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"

Pasi të bëjmë këtë, 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
The push refers to repository [cr.yandex/crpdgj6c9umdhgaqjfmm/events]
8c286e154c6e: Pushed
477c318b05cb: Pushed
beee9f30bc1f: Pushed
v1: digest: sha256:1dd5aaa9dbdde2f60d833be0bed1c352724be3ea3158bcac3cdee41d47c5e380 size: 946

Mund të sigurohemi se imazhi është ngarkuar me sukses:

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

Nëse instaloni mjetin yc në një makinë me linux, mund të përdorni komandën

yc container registry configure-docker

për të konfiguruar docker-in.

Përfundimi

Ne kemi kryer një punë të madhe dhe të vështirë dhe si rezultat:

  1. Kemi menduar arkitekturën e shërbimit tonë të ardhshëm.
  2. Kemi shkruar një aplikacion në golang që implementon logjikën tonë të biznesit.
  3. E kemi ndërtuar dhe hedhur në një container registry privat.

Në pjesën e ardhshme do të kalojmë në diçka interesante — do ta hedhim aplikacionin tonë në prodhim dhe përfundimisht do të fillojmë ngarkesën. Mos u largoni!

Ky material është në regjistrimin e hapur të praktikës REBRAIN & Yandex.Cloud: Pranojmë 10,000 kërkesa në sekondë në Yandex Cloud — https://youtu.be/cZLezUm0ekE

Nëse ju intereson që të merrni pjesë në aktivitete të tilla online dhe të bëni pyetje në kohë reale, lidheni me kanalin DevOps by REBRAIN.

Një falënderim të veçantë për Yandex.Cloud për mundësimin e zhvillimit të këtij eventi. Klikoni këtu për ta vizituar — https://cloud.yandex.ru/prices

Nëse ju nevojitet ndihmë për migrimin në cloud ose keni pyetje për infrastrukturën tuaj, mos hezitoni të lëni një kërkesë.

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

Burimi: habr.com

Bli një hosting të besueshëm për faqet me mbrojtje DDoS, VPS VDS serverë 🔥 Bli një hosting të besueshëm për faqet me mbrojtje DDoS, VPS VDS serverë | ProHoster