Ciao a tutti, amici!
* Questo articolo è scritto ispirato al laboratorio aperto REBRAIN & Yandex.Cloud; se preferite guardare un video, potete trovarlo a questo link —
Recentemente abbiamo avuto l'opportunità di toccare con mano Yandex.Cloud. Poiché volevamo esplorare a lungo, abbiamo subito scartato l'idea di lanciare un semplice blog WordPress con un database cloud — troppo noioso. Dopo brevi riflessioni, abbiamo deciso di implementare qualcosa di simile a un'architettura di produzione per la ricezione e l'analisi di eventi in tempo quasi reale.
Sono assolutamente sicuro che la stragrande maggioranza delle aziende online (e non solo) raccolga in qualche modo un'enorme quantità di informazioni sui propri utenti e sulle loro azioni. Al minimo, questo è necessario per prendere determinate decisioni — ad esempio, se gestite un gioco online, potete controllare le statistiche su quali livelli gli utenti si bloccano più spesso e disinstallano il vostro gioco. Oppure perché gli utenti lasciano il vostro sito senza acquistare nulla (saluti, Yandex.Metrica).
Quindi, la nostra storia: come abbiamo scritto un'applicazione in golang, testato kafka vs rabbitmq vs yqs, realizzato streaming di dati in un cluster Clickhouse e visualizzato i dati utilizzando Yandex Datalens. Naturalmente, tutto ciò è stato condito con accorgimenti infrastrutturali come docker, terraform, gitlab ci e, ovviamente, prometheus. Partiamo!
Voglio subito precisare che non riusciremo a configurare tutto in un colpo solo — per questo ci serviranno diverse articoli in serie. Un po' sulla struttura:
Parte 1 (la state leggendo). Definiremo il documento dei requisiti e l'architettura della soluzione, e scriveremo un'applicazione in golang.
Parte 2. Mettiamo l'applicazione in produzione, la rendiamo scalabile e testiamo il carico.
Parte 3. Cerchiamo di capire perché è necessario memorizzare i messaggi in un buffer e non in file, e confrontiamo kafka, rabbitmq e Yandex Queue Service.
Parte 4. Deplyghiamo un cluster Clickhouse, realizziamo streaming per trasferire i dati dal buffer e configuriamo la visualizzazione in datalens.
Parte 5. Mettiamo in ordine tutta l'infrastruttura — configuriamo ci/cd, utilizzando gitlab ci, colleghiamo il monitoraggio e la scoperta dei servizi usando prometheus e consul.
Specifiche
Iniziamo a formulare il documento di specifiche — cosa vogliamo in uscita.
- Vogliamo avere un endpoint del tipo events.kis.im (kis.im è il dominio di test che utilizzeremo in tutti gli articoli), che deve accettare eventi tramite HTTPS.
- Gli eventi sono un semplice JSON del tipo: {"event": "view", "os": "linux", "browser": "chrome"}. Nella fase finale aggiungeremo qualche campo in più, ma non avrà un grande impatto. Se desideri, puoi passare a protobuf.
- Il servizio deve essere in grado di gestire 10.000 eventi al secondo.
- Deve essere possibile scalare orizzontalmente, semplicemente aggiungendo nuove istanze alla nostra soluzione. E sarebbe utile se potessimo spostare la parte frontale in diverse geolocalizzazioni per ridurre la latenza nelle richieste dei clienti.
- Resilienza. La soluzione deve essere abbastanza stabile e in grado di sopravvivere ai guasti di qualsiasi parte (fino a un certo numero, naturalmente).
Architettura
Per questo tipo di compiti sono state ideate da tempo architetture classiche che consentono una scalabilità efficace. Nella figura è riportato un esempio della nostra soluzione.

Ecco cosa abbiamo:
1. A sinistra sono rappresentati i nostri dispositivi che generano vari eventi, sia che si tratti di completare livelli nei giochi su smartphone o di effettuare ordini in un negozio online tramite un normale browser. L'evento, come specificato nel capitolato, è un semplice JSON che viene inviato al nostro endpoint — events.kis.im.
2. I primi due server sono semplici bilanciatori, i cui compiti principali sono:
- Essere sempre disponibili. A tal fine, si può utilizzare, ad esempio, keepalived, che commuterà l'IP virtuale tra i nodi in caso di problemi.
- Terminare TLS. Sì, termineremo TLS proprio su di essi. Prima di tutto, per garantire che la nostra soluzione rispetti il capitolato, e in secondo luogo, per alleviare il carico dovuto alla creazione della connessione crittografata dai nostri server backend.
- Bilanciare le richieste in entrata sui server backend disponibili. La parola chiave qui è disponibili. Da ciò ne deriva che i bilanciatori di carico devono essere in grado di monitorare i nostri server con le applicazioni e smettere di bilanciare il traffico sui nodi non funzionanti.
3. Dopo i bilanciatori di carico, abbiamo i server applicativi, su cui è in esecuzione un'applicazione piuttosto semplice. Deve poter accettare richieste in entrata via HTTP, convalidare il JSON inviato e archiviare i dati in un buffer.
4. Come buffer nel diagramma è rappresentata kafka, anche se, ovviamente, a questo livello si possono utilizzare altri servizi simili. Confronteremo Kafka, rabbitmq e yqs nel terzo articolo.
5. La penultima entità della nostra architettura è Clickhouse, un database colonnare che consente di archiviare e elaborare enormi quantità di dati. A questo livello dobbiamo trasferire i dati dal buffer al sistema di archiviazione vero e proprio (ne parleremo nel quarto articolo).
Questo schema ci permette di scalare orizzontalmente ogni strato in modo indipendente. Se i server backend non ce la fanno, possiamo aggiungerne altri, dato che sono applicazioni stateless, e quindi è possibile farlo anche in modo automatico. Se il buffer sotto forma di kafka è insufficiente, possiamo aggiungere altri server e trasferire parte delle partizioni del nostro topic. Se Clickhouse è sovraccarico, beh, non è possibile 🙂 In realtà possiamo aggiungere server e fare lo sharding dei dati.
A proposito, se desiderate implementare la parte opzionale del nostro specifiche tecniche e scalare in diverse geolocalizzazioni, non c'è niente di più semplice:

In ogni geolocalizzazione implementiamo un load balancer con un'applicazione e kafka. In generale, bastano 2 server applicativi, 3 nodi kafka e un bilanciatore di carico cloud, ad esempio, cloudflare, che controllerà la disponibilità dei nodi dell'applicazione e bilancerà le richieste per geolocalizzazione in base all'indirizzo IP del cliente. In questo modo, i dati inviati da un cliente americano arriveranno ai server americani. Mentre i dati provenienti dall'Africa arriveranno a quelli africani.
Dopo tutto è molto semplice: utilizziamo lo strumento mirror dal set di kafka e copiamo tutti i dati da tutte le località nel nostro data center centrale, situato in Russia. All'interno analizziamo i dati e li registriamo in Clickhouse per la successiva visualizzazione.
Quindi, abbiamo capito l'architettura: iniziamo a testare Yandex.Cloud!
Scriviamo un'applicazione
Dovremo aspettare un po' per il Cloud e scrivere un servizio piuttosto semplice per elaborare eventi in ingresso. Utilizzeremo golang, perché si è dimostrato un linguaggio molto valido per la scrittura di applicazioni di rete.
Dopo aver dedicato un'ora di tempo (forse anche un paio d'ore), otteniamo all'incirca qualcosa del genere: .
Quali sono i punti principali che vorrei evidenziare qui:
1. All'avvio dell'applicazione è possibile specificare due flag. Il primo indica la porta sulla quale ascolteremo le richieste http in arrivo (-addr). Il secondo è l'indirizzo del server kafka, dove registreremo i nostri eventi (-kafka):
addr = flag.String("addr", ":8080", "Indirizzo TCP su cui ascoltare")
kafka = flag.String("kafka", "127.0.0.1:9092", "Punti di accesso Kafka")2. L'applicazione utilizza la libreria sarama () per inviare messaggi al cluster kafka. Abbiamo immediatamente impostato configurazioni orientate alla massima velocità di elaborazione:
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForLocal
config.Producer.Compression = sarama.CompressionSnappy
config.Producer.Return.Successes = true3. Inoltre, nella nostra applicazione è integrato un client prometheus che raccoglie varie metriche, come ad esempio:
- il numero di richieste alla nostra applicazione;
- il numero di errori durante l'esecuzione della richiesta (impossibile leggere la richiesta post, json danneggiato, impossibile scrivere in kafka);
- il tempo di elaborazione di una singola richiesta da parte del cliente, incluso il tempo di scrittura del messaggio in kafka.
4. Tre endpoint che la nostra applicazione gestisce:
- /status — просто возвращаем ok, чтобы показать, что мы живы. Хотя можно и добавить некоторые проверки, типа доступности кафка кластера.
- /metrics — по этому url prometheus client будет возвращать собранные им метрики.
- /post — основной endpoint, куда будут приходить POST запросы с json внутри. Наше приложение проверяет json на валидность и если все ок — записывает данные в кафка-кластер.
Voglio sottolineare che il codice non è perfetto — può (e deve!) essere migliorato. Ad esempio, si potrebbe abbandonare l'uso del net/http integrato e passare a fasthttp, più veloce. Oppure si potrebbe guadagnare tempo di elaborazione e risorse CPU spostando il controllo della validità del json a un momento successivo — quando i dati verranno trasferiti dal buffer al cluster clickhouse.
Oltre all'aspetto dello sviluppo, abbiamo immediatamente pensato alla nostra futura infrastruttura e abbiamo deciso di distribuire la nostra applicazione tramite docker. Il Dockerfile finale per la costruzione dell'applicazione è . Nel complesso, è abbastanza semplice; l'unico punto su cui desidero richiamare l'attenzione è la costruzione multistage, che consente di ridurre l'immagine finale del nostro contenitore.
I primi passi nel cloud
Per prima cosa, ci registriamo su . Dopo aver compilato tutti i campi necessari, ci verrà creato un account e ci verrà assegnato un credito di una certa somma di denaro, che potrà essere utilizzata per testare i servizi del cloud. Se desiderate ripetere tutti i passaggi del nostro articolo, questo credito dovrebbe essere sufficiente.
Dopo la registrazione, verrà creato per voi un cloud separato e una cartella default, dove potrete iniziare a creare risorse cloud. Nel complesso, in Yandex.Cloud la relazione tra le risorse appare nel seguente modo:

Puoi creare più cloud per un singolo account. All'interno di un cloud, puoi creare diverse directory per diversi progetti aziendali. Puoi leggere di più nella documentazione — . A proposito, più avanti nel testo farò spesso riferimento ad essa. Quando ho configurato tutta l'infrastruttura da zero, la documentazione mi è stata utile più di una volta, quindi ti consiglio di studiarla.
Per gestire il cloud puoi utilizzare sia l'interfaccia web che l'utilità da linea di comando — yc. L'installazione avviene con un solo comando (per Linux e Mac OS):
curl https://storage.yandexcloud.net/yandexcloud-yc/install.sh | bashSe hai dei dubbi riguardo all'esecuzione di script da Internet, puoi innanzitutto aprire lo script e leggerlo. In secondo luogo, lo eseguiamo sotto il nostro utente — senza diritti di root.
Se desideri installare il client per Windows, puoi seguire le istruzioni e poi eseguire yc init, per configurarlo completamente:
vozerov@mba:~ $ yc init
Benvenuto! Questo comando ti guiderà attraverso il processo di configurazione.
Per favore vai su https://oauth.yandex.ru/authorize?response_type=token&client_id= per ottenere il token OAuth.
Per favore, inserisci il token OAuth:
Seleziona il cloud da utilizzare:
[1] cloud-b1gv67ihgfu3bp (id = b1gv67ihgfu3bpt24o0q)
[2] fevlake-cloud (id = b1g6bvup3toribomnh30)
Per favore, inserisci la tua scelta numerica: 2
Il tuo cloud attuale è stato impostato su 'fevlake-cloud' (id = b1g6bvup3toribomnh30).
Seleziona la cartella da utilizzare:
[1] default (id = b1g5r6h11knotfr8vjp7)
[2] Crea una nuova cartella
Per favore, inserisci la tua scelta numerica: 1
La tua cartella attuale è stata impostata su 'default' (id = b1g5r6h11knotfr8vjp7).
Vuoi configurare una zona Compute predefinita? [Y/n]
Quale zona desideri utilizzare come predefinita per il profilo?
[1] ru-central1-a
[2] ru-central1-b
[3] ru-central1-c
[4] Non impostare la zona predefinita
Per favore, inserisci la tua scelta numerica: 1
La tua zona Compute predefinita del profilo è stata impostata su 'ru-central1-a'.
vozerov@mba:~ $In linea di massima, il processo non è complicato: prima devi ottenere un token OAuth per gestire il cloud, scegliere il cloud e la cartella che utilizzerai.
Se hai più account o cartelle all'interno di un cloud, puoi creare profili aggiuntivi con impostazioni separate tramite yc config profile create e passare da un profilo all'altro.
Oltre ai metodi sopra menzionati, il team di Yandex.Cloud ha scritto un ottimo per gestire le risorse cloud. Da parte mia, ho preparato un repository git dove ho descritto tutte le risorse che verranno create nel corso dell'articolo — . Ci interessa il branch master, cloniamolo localmente:
vozerov@mba:~ $ git clone https://github.com/rebrainme/yandex-cloud-events/ events
Clonazione in 'events'...
remoto: Enumerazione degli oggetti: 100, completato.
remoto: Conteggio degli oggetti: 100% (100/100), completato.
remoto: Compressione degli oggetti: 100% (68/68), completato.
remoto: Totale 100 (delta 37), riutilizzati 89 (delta 26), pack-reused 0
Ricezione degli oggetti: 100% (100/100), 25.65 KiB | 168.00 KiB/s, completato.
Risoluzione dei delta: 100% (37/37), completato.
vozerov@mba:~ $ cd events/terraform/Tutte le variabili principali utilizzate in terraform sono scritte nel file main.tf. Per iniziare a lavorare, creiamo nella cartella terraform il file private.auto.tfvars con il seguente contenuto:
# 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 le variabili possono essere ottenute da yc config list, poiché abbiamo già configurato l'utilità da riga di comando. Ti consiglio di aggiungere subito private.auto.tfvars a .gitignore, per evitare di pubblicare accidentalmente dati privati.
In private.auto.tfvars abbiamo anche indicato i dati di Cloudflare — per la creazione di record DNS e il proxying del dominio principale events.kis.im sui nostri server. Se non vuoi usare Cloudflare, rimuovi l'inizializzazione del provider cloudflare in main.tf e il file dns.tf, che è responsabile della creazione dei necessari record DNS.
Nel nostro lavoro combineremo tutti e tre i metodi — interfaccia web, utilità da riga di comando e terraform.
Reti virtuali
A dire la verità, questo passaggio potrebbe essere evitato, poiché quando si crea un nuovo cloud si genera automaticamente una rete separata e 3 sottoreti — una per ciascuna zona di disponibilità. Tuttavia, ci piacerebbe creare per il nostro progetto una rete separata con la propria indirizzamento. Lo schema generale del funzionamento della rete in Yandex.Cloud è presentato nell'immagine qui sotto (preso onestamente da )

Quindi, stai creando una rete comune, all'interno della quale le risorse potranno comunicare tra loro. Per ogni zona di disponibilità viene creata una sottorete con il proprio indirizzamento e viene collegata alla rete comune. Alla fine, tutte le risorse cloud in essa possono comunicare, anche se si trovano in diverse zone di disponibilità. Le risorse collegate a diverse reti cloud possono vedersi solo attraverso indirizzi esterni. A proposito, come funziona questa magia all'interno, .
La creazione della rete è descritta nel file network.tf del repository. Lì creiamo una rete privata comune internal e colleghiamo ad essa tre sottoreti in diverse zone di disponibilità — internal-a (172.16.1.0/24), internal-b (172.16.2.0/24), internal-c (172.16.3.0/24).
Inizializziamo terraform e creiamo le reti:
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 ...
Piano: 4 da aggiungere, 0 da modificare, 0 da distruggere.
Vuoi eseguire queste azioni?
Terraform eseguirà le azioni descritte sopra.
Solo 'yes' sarà accettato per approvare.
Inserisci un valore: yes
yandex_vpc_network.internal: Creazione...
yandex_vpc_network.internal: Creazione completata dopo 3s [id=enp2g2rhile7gbqlbrkr]
yandex_vpc_subnet.internal-a: Creazione...
yandex_vpc_subnet.internal-b: Creazione...
yandex_vpc_subnet.internal-c: Creazione...
yandex_vpc_subnet.internal-a: Creazione completata dopo 6s [id=e9b1dad6mgoj2v4funog]
yandex_vpc_subnet.internal-b: Creazione completata dopo 7s [id=e2liv5i4amu52p64ac9p]
yandex_vpc_subnet.internal-c: Ancora in creazione... [10s trascorsi]
yandex_vpc_subnet.internal-c: Creazione completata dopo 10s [id=b0c2qhsj2vranoc9vhcq]
Applicazione completata! Risorse: 4 aggiunte, 0 modificate, 0 distrutte.Ottimo! Abbiamo creato la nostra rete e ora siamo pronti per creare i nostri servizi interni.
Creazione di macchine virtuali
Per testare l'applicazione ci basterà creare due macchine virtuali: la prima ci servirà per compilare e lanciare l'applicazione, la seconda per far partire Kafka, che utilizzeremo per memorizzare i messaggi in arrivo. E creiamo anche un'altra macchina dove configureremo Prometheus per il monitoraggio dell'applicazione.
Le macchine virtuali saranno configurate tramite Ansible, quindi prima di avviare Terraform assicurati di avere una delle ultime versioni di Ansible. E installa i ruoli necessari da Ansible Galaxy:
vozerov@mba:~\/events\/terraform (master) $ cd ..\/ansible\/\nvozerov@mba:~\/events\/ansible (master) $ ansible-galaxy install -r requirements.yml
- cloudalchemy-prometheus (master) è già installato, salto.
- cloudalchemy-grafana (master) è già installato, salto.
- sansible.kafka (master) è già installato, salto.
- sansible.zookeeper (master) è già installato, salto.
- geerlingguy.docker (master) è già installato, salto.
vozerov@mba:~\/events\/ansible (master) $All'interno della cartella Ansible c'è un esempio di file di configurazione .ansible.cfg che uso io. Potrebbe esserti utile.
Prima di creare le macchine virtuali, assicurati che il tuo ssh-agent sia in esecuzione e che la chiave ssh sia stata aggiunta, altrimenti Terraform non riuscirà a connettersi alle macchine create. Ovviamente, mi sono imbattuto in un bug su OS X: . Per evitare che ti si ripeta questa storia, prima di avviare Terraform aggiungi una piccola variabile nell'env:
vozerov@mba:~\/events\/terraform (master) $ export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YESNella cartella con Terraform creiamo le risorse necessarie:
vozerov@mba:~\/events\/terraform (master) $ terraform apply -target yandex_compute_instance.build -target yandex_compute_instance.monitoring -target yandex_compute_instance.kafka\nyandex_vpc_network.internal: Aggiornamento dello stato... [id=enp2g2rhile7gbqlbrkr]\ndata.yandex_compute_image.ubuntu_image: Aggiornamento dello stato...\nyandex_vpc_subnet.internal-a: Aggiornamento dello stato... [id=e9b1dad6mgoj2v4funog]\n\nÈ stato generato un piano di esecuzione e viene mostrato di seguito. Le azioni sulle risorse sono indicate con i seguenti simboli:\n + crea\n\n... saltato ...\n\nPiano: 3 da aggiungere, 0 da modificare, 0 da distruggere.\n\n... saltato ...Se tutto è andato a buon fine (e così deve essere), avremo tre macchine virtuali:
- build — macchina per il testing e la compilazione dell'applicazione. Docker è stato installato automaticamente da ansible.
- monitoring — macchina per il monitoraggio — su di essa sono installati prometheus & grafana. Nome utente / password standard: admin / admin
- kafka — piccola macchina con kafka installata, accessibile sulla porta 9092.
Assicuriamoci che siano tutte presenti:
vozerov@mba:~\/events (master) $ yc compute instance list\n+----------------------+------------+---------------+---------+---------------+-------------+\n| ID | NOME | ZONE ID | STATO | IP ESTERNO | IP INTERNO |\n+----------------------+------------+---------------+---------+---------------+-------------+\n| fhm081u8bkbqf1pa5kgj | monitoring | ru-central1-a | IN ESECUZIONE | 84.201.159.71 | 172.16.1.35 |\n| fhmf37k03oobgu9jmd7p | kafka | ru-central1-a | IN ESECUZIONE | 84.201.173.41 | 172.16.1.31 |\n| fhmt9pl1i8sf7ga6flgp | build | ru-central1-a | IN ESECUZIONE | 84.201.132.3 | 172.16.1.26 |\n+----------------------+------------+---------------+---------+---------------+-------------+ Le risorse sono presenti, e da qui possiamo estrarre i loro indirizzi IP. Ovunque d'ora in poi userò gli indirizzi IP per connettermi via ssh e testare l'applicazione. Se hai un account su cloudflare collegato a terraform, non esitare a usare i nomi DNS appena creati.
A proposito, quando si crea la macchina virtuale viene fornito un indirizzo IP interno e un nome DNS interno, quindi è possibile accedere ai server all'interno della rete utilizzando i nomi:
ubuntu@build:~$ ping kafka.ru-central1.internal\nPING kafka.ru-central1.internal (172.16.1.31) 56(84) byte di dati.\n64 byte da kafka.ru-central1.internal (172.16.1.31): icmp_seq=1 ttl=63 tempo=1.23 ms\n64 byte da kafka.ru-central1.internal (172.16.1.31): icmp_seq=2 ttl=63 tempo=0.625 ms\n^C\n--- statistiche ping di kafka.ru-central1.internal ---\n2 pacchetti trasmessi, 2 ricevuti, 0% perdita pacchetti, tempo 1001ms\nrtt min\/avg\/max\/mdev = 0.625\/0.931\/1.238\/0.308 msQuesto ci sarà utile per indicare all'applicazione l'endpoint con kafka.
Compiliamo l'applicazione
Ottimo, i server ci sono, l'applicazione è pronta — rimane solo da compilarla e pubblicarla. Per la compilazione utilizzeremo un normale docker build, mentre come repository delle immagini prenderemo il servizio di yandex — container registry. Ma andiamo con ordine.
Copiamo l'applicazione sulla macchina build, accediamo via ssh e compiliamo l'immagine:
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
total size is 3644 speedup is 0.93\n\nvozerov@mba:~\/events (master) $ ssh 84.201.132.3 -l ubuntu
ubuntu@build:~$ cd app
ubuntu@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È stato fatto metà del lavoro — ora possiamo verificare il funzionamento della nostra applicazione avviandola e inviando a kafka:
ubuntu@build:~\/app$ sudo docker run --name app -d -p 8080:8080 app \/app\/app -kafka=kafka.ru-central1.internal:9092\n\nDalla macchina locale possiamo inviare un evento di test e vedere la risposta:\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) $L'applicazione ha risposto con successo alla registrazione, indicando l'id della partizione e dell'offset in cui è stato collocato il messaggio. Ora resta solo da creare un registry in Yandex.Cloud e caricare la nostra immagine (come fare questo in poche righe è descritto nel file registry.tf). Creiamo lo storage:
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.Per l'autenticazione nel container registry ci sono diversi metodi — tramite token oauth, token iam o chiave dell'account di servizio. Maggiori dettagli su questi metodi sono disponibili nella documentazione. Utilizzeremo la chiave dell'account di servizio, quindi creiamo l'account:
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.Ora dobbiamo creare una chiave:
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_2048Otteniamo informazioni sull'id del nostro storage, trasferiamo la chiave e ci autorizziamo:
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\nubuntibuild:~$ 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\nubuntibuild:~$Per caricare l'immagine nel registry avremo bisogno dell'ID del container registry, lo prendiamo dallo strumento yc:
vozerov@mba:~ $ yc container registry get events
id: crpdgj6c9umdhgaqjfmm
folder_id:
name: events
status: ATTIVO
created_at: "2020-04-13T13:56:41.914Z"Dopo questo, diamo un nuovo nome alla nostra immagine e la carichiamo:
ubuntu@build:~$ sudo docker tag app cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
ubuntu@build:~$ sudo docker push cr.yandex/crpdgj6c9umdhgaqjfmm/events:v1
Il push si riferisce al repository [cr.yandex/crpdgj6c9umdhgaqjfmm/events]
8c286e154c6e: Inviato
477c318b05cb: Inviato
beee9f30bc1f: Inviato
v1: digest: sha256:1dd5aaa9dbdde2f60d833be0bed1c352724be3ea3158bcac3cdee41d47c5e380 dimensione: 946Possiamo assicurarci che l'immagine sia stata caricata con successo:
vozerov@mba:~/events/terraform (master) $ yc container repository list
+----------------------+-----------------------------+
| ID | NAME |
+----------------------+-----------------------------+
| crpe8mqtrgmuq07accvn | crpdgj6c9umdhgaqjfmm/events |
+----------------------+-----------------------------+A proposito, se installate l'utilità yc su una macchina Linux, potete usare il comando
yc container registry configure-dockerper configurare Docker.
Conclusione
Abbiamo fatto un grande e difficile lavoro e, di conseguenza:
- Abbiamo ideato l'architettura del nostro futuro servizio.
- Abbiamo scritto un'applicazione in golang che realizza la nostra logica di business.
- L'abbiamo raccolta e caricata in un registry container privato.
Nella prossima parte passeremo a qualcosa di interessante: caricheremo la nostra applicazione in produzione e infine la testeremo con un carico. Non cambiate canale!
Questo materiale è disponibile come registrazione video del laboratorio aperto REBRAIN & Yandex.Cloud: Accettiamo 10.000 richieste al secondo su Yandex Cloud —
Se siete interessati a partecipare a eventi del genere online e a porre domande in tempo reale, collegatevi a.
Un ringraziamento speciale va a Yandex.Cloud per aver reso possibile questo evento. Il loro link —
Se hai bisogno di migrare nel cloud o hai domande sulla tua infrastruttura, .
P.S. Abbiamo 2 audit gratuiti al mese, forse il tuo progetto sarà tra questi.
Fonte: habr.com
