Δεχόμαστε 10 συμβάντα στο Yandex.Cloud. Μέρος 000

Γεια σε όλους, φίλοι!

* Αυτό το άρθρο βασίζεται στο ανοιχτό εργαστήριο REBRAIN & Yandex.Cloud, αν προτιμάτε να παρακολουθήσετε το βίντεο, μπορείτε να το βρείτε σε αυτόν τον σύνδεσμο - https://youtu.be/cZLezUm0ekE

Πρόσφατα είχαμε την ευκαιρία να δοκιμάσουμε το Yandex.Cloud live. Δεδομένου ότι θέλαμε να διερευνήσουμε πολύ και σκληρά, εγκαταλείψαμε αμέσως την ιδέα να ξεκινήσουμε ένα απλό ιστολόγιο Wordpress με βάση στο cloud - ήταν πολύ βαρετό. Μετά από λίγη σκέψη, αποφασίσαμε να αναπτύξουμε κάτι παρόμοιο με μια αρχιτεκτονική υπηρεσίας παραγωγής για τη λήψη και την ανάλυση γεγονότων σε λειτουργία σχεδόν σε πραγματικό χρόνο.

Είμαι απολύτως βέβαιος ότι η συντριπτική πλειονότητα των διαδικτυακών (και όχι μόνο) επιχειρήσεων συλλέγει με κάποιο τρόπο ένα βουνό από πληροφορίες σχετικά με τους χρήστες και τις ενέργειές τους. Τουλάχιστον, αυτό είναι απαραίτητο για τη λήψη ορισμένων αποφάσεων - για παράδειγμα, εάν διαχειρίζεστε ένα διαδικτυακό παιχνίδι, μπορείτε να δείτε τα στατιστικά στοιχεία σε ποιο επίπεδο οι χρήστες κολλάνε συχνότερα και διαγράφουν το παιχνίδι σας. Ή γιατί οι χρήστες εγκαταλείπουν τον ιστότοπό σας χωρίς να αγοράσουν τίποτα (γεια σας, Yandex.Metrica).

Λοιπόν, η ιστορία μας: πώς γράψαμε μια εφαρμογή σε golang, δοκιμάσαμε kafka εναντίον rabbitmq εναντίον yqs, γράψαμε ροή δεδομένων σε ένα σύμπλεγμα Clickhouse και οπτικοποιήσαμε τα δεδομένα χρησιμοποιώντας το yandex datalens. Φυσικά, όλα αυτά ήταν καρυκευμένα με απολαύσεις υποδομής με τη μορφή docker, terraform, gitlab ci και, φυσικά, prometheus. Πάμε!

Θα ήθελα να κάνω αμέσως κράτηση ότι δεν θα μπορούμε να διαμορφώσουμε τα πάντα σε μία συνεδρίαση - για αυτό θα χρειαστούμε πολλά άρθρα στη σειρά. Λίγα λόγια για τη δομή:

Μέρος 1 (το διαβάζετε). Θα αποφασίσουμε για τις προδιαγραφές και την αρχιτεκτονική της λύσης και θα γράψουμε επίσης μια εφαρμογή σε golang.
Μέρος 2ο. Κυκλοφορούμε την εφαρμογή μας στην παραγωγή, την κάνουμε κλιμακούμενη και δοκιμάζουμε το φορτίο.
Μέρος 3. Ας προσπαθήσουμε να καταλάβουμε γιατί πρέπει να αποθηκεύουμε μηνύματα σε buffer και όχι σε αρχεία, και επίσης να συγκρίνουμε την υπηρεσία ουράς kafka, rabbitmq και yandex.
Μέρος 4 Θα αναπτύξουμε ένα σύμπλεγμα Clickhouse, θα γράψουμε μια υπηρεσία ροής για τη μεταφορά δεδομένων από το buffer εκεί και θα ρυθμίσουμε την οπτικοποίηση στο datalens.
Μέρος 5 Ας φέρουμε ολόκληρη την υποδομή στη σωστή μορφή - ρυθμίστε το ci/cd χρησιμοποιώντας το gitlab ci, συνδέστε την παρακολούθηση και την ανακάλυψη υπηρεσιών χρησιμοποιώντας το prometheus και το consul.

ТЗ

Αρχικά, ας διατυπώσουμε τους όρους αναφοράς - τι ακριβώς θέλουμε να έχουμε ως αποτέλεσμα.

  1. Θέλουμε να έχουμε ένα τελικό σημείο όπως το events.kis.im (το kis.im είναι ο δοκιμαστικός τομέας που θα χρησιμοποιήσουμε σε όλα τα άρθρα), το οποίο θα πρέπει να λαμβάνει συμβάντα χρησιμοποιώντας HTTPS.
  2. Τα συμβάντα είναι ένα απλό json όπως: {“event”: “view”, “os”: “linux”, “browser”: “chrome”}. Στο τελικό στάδιο θα προσθέσουμε λίγο ακόμα πεδία, αλλά αυτό δεν θα παίξει μεγάλο ρόλο. Εάν θέλετε, μπορείτε να μεταβείτε στο protobuf.
  3. Η υπηρεσία πρέπει να μπορεί να επεξεργάζεται 10 συμβάντα ανά δευτερόλεπτο.
  4. Θα πρέπει να είναι δυνατή η οριζόντια κλίμακα προσθέτοντας απλώς νέες παρουσίες στη λύση μας. Και θα ήταν ωραίο αν μπορούμε να μετακινήσουμε το μπροστινό μέρος σε διαφορετικές γεωγραφικές τοποθεσίες για να μειώσουμε τον λανθάνοντα χρόνο για αιτήματα πελατών.
  5. Ανοχή σε σφάλματα. Η λύση πρέπει να είναι αρκετά σταθερή και να μπορεί να επιβιώσει από την πτώση οποιωνδήποτε εξαρτημάτων (μέχρι ένα συγκεκριμένο αριθμό, φυσικά).

Αρχιτεκτονική

Γενικά, για αυτό το είδος εργασιών, έχουν επινοηθεί από καιρό κλασικές αρχιτεκτονικές που επιτρέπουν αποτελεσματική κλιμάκωση. Το σχήμα δείχνει ένα παράδειγμα της λύσης μας.

Δεχόμαστε 10 συμβάντα στο Yandex.Cloud. Μέρος 000

Λοιπόν τι έχουμε:

1. Στα αριστερά βρίσκονται οι συσκευές μας που δημιουργούν διάφορα συμβάντα, είτε πρόκειται για παίκτες που ολοκληρώνουν ένα επίπεδο σε ένα παιχνίδι σε ένα smartphone είτε δημιουργούν μια παραγγελία σε ένα ηλεκτρονικό κατάστημα μέσω ενός κανονικού προγράμματος περιήγησης. Ένα συμβάν, όπως ορίζεται στην προδιαγραφή, είναι ένα απλό json που αποστέλλεται στο τελικό μας σημείο - events.kis.im.

2. Οι δύο πρώτοι διακομιστές είναι απλοί εξισορροπητές, οι κύριες εργασίες τους είναι:

  • Να είστε συνεχώς διαθέσιμοι. Για να το κάνετε αυτό, μπορείτε να χρησιμοποιήσετε, για παράδειγμα, το keepalived, το οποίο θα εναλλάσσει την εικονική IP μεταξύ κόμβων σε περίπτωση προβλημάτων.
  • Τερματισμός TLS. Ναι, θα τερματίσουμε το TLS σε αυτά. Πρώτον, ώστε η λύση μας να συμμορφώνεται με τις τεχνικές προδιαγραφές και δεύτερον, για να απαλλαγούμε από το βάρος της δημιουργίας κρυπτογραφημένης σύνδεσης από τους διακομιστές υποστήριξης.
  • Εξισορροπήστε τα εισερχόμενα αιτήματα σε διαθέσιμους διακομιστές υποστήριξης. Η λέξη κλειδί εδώ είναι προσβάσιμη. Με βάση αυτό, καταλαβαίνουμε ότι οι εξισορροπητές φορτίου πρέπει να μπορούν να παρακολουθούν τους διακομιστές μας με εφαρμογές και να σταματήσουν την εξισορρόπηση της κυκλοφορίας σε αποτυχημένους κόμβους.

3. Μετά τους εξισορροπητές, έχουμε διακομιστές εφαρμογών που εκτελούν μια αρκετά απλή εφαρμογή. Θα πρέπει να μπορεί να δέχεται εισερχόμενα αιτήματα μέσω HTTP, να επικυρώνει το json που έχει αποσταλεί και να τοποθετεί τα δεδομένα σε ένα buffer.

4. Το διάγραμμα δείχνει το kafka ως buffer, αν και, φυσικά, μπορούν να χρησιμοποιηθούν και άλλες παρόμοιες υπηρεσίες σε αυτό το επίπεδο. Θα συγκρίνουμε Kafka, rabbitmq και yqs στο τρίτο άρθρο.

5. Το προτελευταίο σημείο της αρχιτεκτονικής μας είναι το Clickhouse - μια στήλη βάσης δεδομένων που σας επιτρέπει να αποθηκεύετε και να επεξεργάζεστε τεράστιο όγκο δεδομένων. Σε αυτό το επίπεδο, πρέπει να μεταφέρουμε δεδομένα από το buffer στο ίδιο το σύστημα αποθήκευσης (περισσότερα για αυτό στο άρθρο 4).

Αυτός ο σχεδιασμός μας επιτρέπει να κλιμακώνουμε κάθε στρώμα ανεξάρτητα οριζόντια. Οι διακομιστές υποστήριξης δεν μπορούν να αντεπεξέλθουν - ας προσθέσουμε κάτι ακόμα - σε τελική ανάλυση, πρόκειται για εφαρμογές χωρίς κατάσταση, και επομένως, αυτό μπορεί να γίνει ακόμα και αυτόματα. Το buffer τύπου Kafka δεν λειτουργεί - ας προσθέσουμε περισσότερους διακομιστές και ας μεταφέρουμε μερικά από τα διαμερίσματα του θέματός μας σε αυτούς. Το Clickhouse δεν μπορεί να το χειριστεί - είναι αδύνατο :) Στην πραγματικότητα, θα συνδέσουμε επίσης τους διακομιστές και θα μοιραστούμε τα δεδομένα.

Παρεμπιπτόντως, εάν θέλετε να εφαρμόσετε το προαιρετικό μέρος των τεχνικών προδιαγραφών και της κλίμακας μας σε διαφορετικές γεωγραφικές τοποθεσίες, τότε δεν υπάρχει τίποτα πιο απλό:

Δεχόμαστε 10 συμβάντα στο Yandex.Cloud. Μέρος 000

Σε κάθε γεωγραφική θέση αναπτύσσουμε ένα load balancer με εφαρμογή και kafka. Σε γενικές γραμμές, αρκούν 2 διακομιστές εφαρμογών, 3 κόμβοι kafka και ένας εξισορροπητής cloud, για παράδειγμα, το cloudflare, το οποίο θα ελέγχει τη διαθεσιμότητα των κόμβων εφαρμογών και τα αιτήματα ισορροπίας κατά γεωγραφική τοποθεσία με βάση τη διεύθυνση IP πηγής του πελάτη. Έτσι, τα δεδομένα που αποστέλλονται από έναν Αμερικανό πελάτη θα προσγειωθούν σε αμερικανικούς διακομιστές. Και τα δεδομένα από την Αφρική είναι στα αφρικανικά.

Τότε όλα είναι πολύ απλά - χρησιμοποιούμε το εργαλείο καθρέφτη από το σετ Kafka και αντιγράφουμε όλα τα δεδομένα από όλες τις τοποθεσίες στο κεντρικό μας κέντρο δεδομένων που βρίσκεται στη Ρωσία. Εσωτερικά, αναλύουμε τα δεδομένα και τα καταγράφουμε στο Clickhouse για επακόλουθη οπτικοποίηση.

Λοιπόν, τακτοποιήσαμε την αρχιτεκτονική - ας αρχίσουμε να κουνάμε το Yandex.Cloud!

Σύνταξη αίτησης

Πριν από το Cloud, πρέπει ακόμα να κάνετε λίγη υπομονή και να γράψετε μια αρκετά απλή υπηρεσία για την επεξεργασία των εισερχόμενων συμβάντων. Θα χρησιμοποιήσουμε το golang επειδή έχει αποδειχθεί πολύ καλά ως γλώσσα για τη σύνταξη εφαρμογών δικτύου.

Αφού περάσουμε μια ώρα (ίσως μερικές ώρες), παίρνουμε κάτι σαν αυτό: https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/main.go.

Ποια είναι τα κύρια σημεία που θα ήθελα να σημειώσω εδώ:

1. Κατά την εκκίνηση της εφαρμογής, μπορείτε να καθορίσετε δύο σημαίες. Ο ένας είναι υπεύθυνος για τη θύρα στην οποία θα ακούμε τα εισερχόμενα αιτήματα http (-addr). Το δεύτερο είναι για τη διεύθυνση διακομιστή kafka όπου θα καταγράφουμε τα συμβάντα μας (-kafka):

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

2. Η εφαρμογή χρησιμοποιεί τη βιβλιοθήκη sarama ([] github.com/Shopify/sarama) για να στείλετε μηνύματα στο σύμπλεγμα kafka. Ορίζουμε αμέσως τις ρυθμίσεις που στοχεύουν στη μέγιστη ταχύτητα επεξεργασίας:

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

3. Η εφαρμογή μας διαθέτει επίσης ενσωματωμένο πρόγραμμα-πελάτη prometheus, ο οποίος συλλέγει διάφορες μετρήσεις, όπως:

  • αριθμός αιτημάτων στην αίτησή μας·
  • αριθμός σφαλμάτων κατά την εκτέλεση της αίτησης (αδύνατη η ανάγνωση του αιτήματος ανάρτησης, κατεστραμμένο json, αδύνατη η εγγραφή στον Κάφκα).
  • χρόνος επεξεργασίας για ένα αίτημα από τον πελάτη, συμπεριλαμβανομένου του χρόνου για τη σύνταξη ενός μηνύματος στον Κάφκα.

4. Τρία τελικά σημεία που επεξεργάζεται η αίτησή μας:

  • /status - απλά επιστρέψτε ok για να δείξετε ότι είμαστε ζωντανοί. Αν και μπορείτε να προσθέσετε μερικούς ελέγχους, όπως τη διαθεσιμότητα του συμπλέγματος Kafka.
  • /metrics - σύμφωνα με αυτό το url, ο πελάτης prometheus θα επιστρέψει τις μετρήσεις που έχει συλλέξει.
  • Το /post είναι το κύριο τελικό σημείο όπου θα αποστέλλονται αιτήματα POST με json μέσα. Η εφαρμογή μας ελέγχει την εγκυρότητα του json και αν όλα είναι εντάξει, γράφει τα δεδομένα στο σύμπλεγμα Kafka.

Θα κάνω μια κράτηση ότι ο κωδικός δεν είναι τέλειος - μπορεί (και πρέπει!) να συμπληρωθεί. Για παράδειγμα, μπορείτε να σταματήσετε να χρησιμοποιείτε το ενσωματωμένο net/http και να μεταβείτε στο πιο γρήγορο http. Ή μπορείτε να κερδίσετε χρόνο επεξεργασίας και πόρους CPU μετακινώντας τον έλεγχο εγκυρότητας json σε μεταγενέστερο στάδιο - όταν τα δεδομένα μεταφέρονται από την προσωρινή μνήμη στο σύμπλεγμα clickhouse.

Εκτός από την αναπτυξιακή πλευρά του θέματος, σκεφτήκαμε αμέσως τη μελλοντική μας υποδομή και αποφασίσαμε να αναπτύξουμε την εφαρμογή μας μέσω docker. Το τελικό Dockerfile για τη δημιουργία της εφαρμογής είναι https://github.com/RebrainMe/yandex-cloud-events/blob/master/app/Dockerfile. Γενικά, είναι αρκετά απλό, το μόνο σημείο που θα ήθελα να προσέξω είναι η συναρμολόγηση πολλών σταδίων, που μας επιτρέπει να μειώσουμε την τελική εικόνα του δοχείου μας.

Τα πρώτα βήματα στο σύννεφο

Πρώτα απ 'όλα, εγγραφείτε στο cloud.yandex.ru. Αφού συμπληρώσουμε όλα τα απαραίτητα πεδία, θα δημιουργηθεί ένας λογαριασμός και θα μας δοθεί επιχορήγηση για ένα συγκεκριμένο χρηματικό ποσό, το οποίο μπορεί να χρησιμοποιηθεί για τη δοκιμή υπηρεσιών cloud. Εάν θέλετε να επαναλάβετε όλα τα βήματα από το άρθρο μας, αυτή η επιχορήγηση θα πρέπει να είναι αρκετή για εσάς.

Μετά την εγγραφή, θα δημιουργηθεί ένα ξεχωριστό cloud και ένας προεπιλεγμένος κατάλογος για εσάς, στον οποίο μπορείτε να ξεκινήσετε τη δημιουργία πόρων cloud. Γενικά, στο Yandex.Cloud, η σχέση των πόρων μοιάζει με αυτό:

Δεχόμαστε 10 συμβάντα στο Yandex.Cloud. Μέρος 000

Μπορείτε να δημιουργήσετε πολλά σύννεφα για έναν λογαριασμό. Και μέσα στο cloud, δημιουργήστε διαφορετικούς καταλόγους για διαφορετικά εταιρικά έργα. Μπορείτε να διαβάσετε περισσότερα σχετικά με αυτό στην τεκμηρίωση - https://cloud.yandex.ru/docs/resource-manager/concepts/resources-hierarchy. Παρεμπιπτόντως, θα αναφερθώ συχνά σε αυτό παρακάτω στο κείμενο. Όταν έφτιαξα ολόκληρη την υποδομή από την αρχή, η τεκμηρίωση με βοήθησε περισσότερες από μία φορές, γι' αυτό σας συμβουλεύω να τη μελετήσετε.

Για να διαχειριστείτε το cloud, μπορείτε να χρησιμοποιήσετε τόσο τη διεπαφή ιστού όσο και το βοηθητικό πρόγραμμα της κονσόλας - yc. Η εγκατάσταση πραγματοποιείται με μία εντολή (για Linux και Mac Os):

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

Εάν ο ειδικός σας στην εσωτερική ασφάλεια μαίνεται για την εκτέλεση σεναρίων από το Διαδίκτυο, τότε, πρώτον, μπορείτε να ανοίξετε το σενάριο και να το διαβάσετε και, δεύτερον, το εκτελούμε υπό τον χρήστη μας - χωρίς δικαιώματα root.

Εάν θέλετε να εγκαταστήσετε ένα πρόγραμμα-πελάτη για Windows, μπορείτε να χρησιμοποιήσετε τις οδηγίες εδώ και μετά εκτελέστε yc initγια να το προσαρμόσετε πλήρως:

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

Κατ 'αρχήν, η διαδικασία είναι απλή - πρώτα πρέπει να λάβετε ένα διακριτικό oauth για τη διαχείριση του cloud, να επιλέξετε το cloud και τον φάκελο που θα χρησιμοποιήσετε.

Εάν έχετε πολλούς λογαριασμούς ή φακέλους στο ίδιο cloud, μπορείτε να δημιουργήσετε πρόσθετα προφίλ με ξεχωριστές ρυθμίσεις μέσω της δημιουργίας προφίλ διαμόρφωσης yc και να κάνετε εναλλαγή μεταξύ τους.

Εκτός από τις παραπάνω μεθόδους, η ομάδα Yandex.Cloud έγραψε ένα πολύ καλό plugin για terraform για τη διαχείριση πόρων cloud. Από την πλευρά μου, ετοίμασα ένα αποθετήριο git, όπου περιέγραψα όλους τους πόρους που θα δημιουργηθούν ως μέρος του άρθρου - https://github.com/rebrainme/yandex-cloud-events/. Μας ενδιαφέρει το κύριο υποκατάστημα, ας το κλωνοποιήσουμε τοπικά:


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/

Όλες οι κύριες μεταβλητές που χρησιμοποιούνται στο terraform είναι γραμμένες στο αρχείο main.tf. Για να ξεκινήσετε, δημιουργήστε ένα αρχείο private.auto.tfvars στον φάκελο terraform με το ακόλουθο περιεχόμενο:

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

Όλες οι μεταβλητές μπορούν να ληφθούν από τη λίστα ρυθμίσεων yc, αφού έχουμε ήδη διαμορφώσει το βοηθητικό πρόγραμμα της κονσόλας. Σας συμβουλεύω να προσθέσετε αμέσως το private.auto.tfvars στο .gitignore, για να μην δημοσιεύσετε κατά λάθος προσωπικά δεδομένα.

Στο private.auto.tfvars προσδιορίσαμε επίσης δεδομένα από το Cloudflare - για τη δημιουργία εγγραφών DNS και τη διαμεσολάβηση του κύριου τομέα events.kis.im στους διακομιστές μας. Εάν δεν θέλετε να χρησιμοποιήσετε το cloudflare, τότε αφαιρέστε την προετοιμασία του παρόχου cloudflare στο main.tf και το αρχείο dns.tf, το οποίο είναι υπεύθυνο για τη δημιουργία των απαραίτητων εγγραφών dns.

Στην εργασία μας θα συνδυάσουμε και τις τρεις μεθόδους - τη διεπαφή ιστού, το βοηθητικό πρόγραμμα κονσόλας και το terraform.

Εικονικά δίκτυα

Για να είμαστε ειλικρινείς, θα μπορούσατε να παραλείψετε αυτό το βήμα, καθώς όταν δημιουργείτε ένα νέο σύννεφο, θα έχετε αυτόματα ένα ξεχωριστό δίκτυο και 3 υποδίκτυα που δημιουργούνται - ένα για κάθε ζώνη διαθεσιμότητας. Ωστόσο, θα θέλαμε να δημιουργήσουμε ένα ξεχωριστό δίκτυο για το έργο μας με τη δική του διεύθυνση. Το γενικό διάγραμμα του τρόπου λειτουργίας του δικτύου στο Yandex.Cloud φαίνεται στο παρακάτω σχήμα (ειλικρινά λαμβάνεται από https://cloud.yandex.ru/docs/vpc/concepts/)

Δεχόμαστε 10 συμβάντα στο Yandex.Cloud. Μέρος 000

Έτσι, δημιουργείτε ένα κοινό δίκτυο μέσα στο οποίο οι πόροι μπορούν να επικοινωνούν μεταξύ τους. Για κάθε ζώνη διαθεσιμότητας, δημιουργείται ένα υποδίκτυο με τη δική του διεύθυνση και συνδέεται με το γενικό δίκτυο. Ως αποτέλεσμα, όλοι οι πόροι cloud σε αυτό μπορούν να επικοινωνούν, ακόμα κι αν βρίσκονται σε διαφορετικές ζώνες διαθεσιμότητας. Οι πόροι που συνδέονται με διαφορετικά δίκτυα cloud μπορούν να δουν ο ένας τον άλλον μόνο μέσω εξωτερικών διευθύνσεων. Παρεμπιπτόντως, πώς λειτουργεί αυτή η μαγεία μέσα, περιγράφηκε καλά στο Habré.

Η δημιουργία δικτύου περιγράφεται στο αρχείο network.tf από το αποθετήριο. Εκεί δημιουργούμε ένα κοινό ιδιωτικό εσωτερικό δίκτυο και συνδέουμε τρία υποδίκτυα σε αυτό σε διαφορετικές ζώνες διαθεσιμότητας - interior-a (172.16.1.0/24), interior-b (172.16.2.0/24), interior-c (172.16.3.0/24 ).

Εκκινήστε το terraform και δημιουργήστε δίκτυα:

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.

Εξαιρετική! Δημιουργήσαμε το δίκτυό μας και είμαστε πλέον έτοιμοι να δημιουργήσουμε τις εσωτερικές μας υπηρεσίες.

Δημιουργήστε εικονικές μηχανές

Για να δοκιμάσουμε την εφαρμογή, θα χρειαστεί να δημιουργήσουμε μόνο δύο εικονικές μηχανές - θα χρειαστούμε την πρώτη για τη δημιουργία και την εκτέλεση της εφαρμογής, τη δεύτερη για την εκτέλεση του kafka, την οποία θα χρησιμοποιήσουμε για την αποθήκευση των εισερχόμενων μηνυμάτων. Και θα δημιουργήσουμε ένα άλλο μηχάνημα όπου θα διαμορφώσουμε τον prometheus για να παρακολουθεί την εφαρμογή.

Οι εικονικές μηχανές θα ρυθμιστούν χρησιμοποιώντας το ansible, επομένως πριν ξεκινήσετε το terraform, βεβαιωθείτε ότι διαθέτετε μία από τις πιο πρόσφατες εκδόσεις του ansible. Και εγκαταστήστε τους απαραίτητους ρόλους με το ansible galaxy:

vozerov@mba:~/events/terraform (master) $ cd ../ansible/
vozerov@mba:~/events/ansible (master) $ ansible-galaxy install -r requirements.yml
- cloudalchemy-prometheus (master) is already installed, skipping.
- cloudalchemy-grafana (master) is already installed, skipping.
- sansible.kafka (master) is already installed, skipping.
- sansible.zookeeper (master) is already installed, skipping.
- geerlingguy.docker (master) is already installed, skipping.
vozerov@mba:~/events/ansible (master) $

Μέσα στο φάκελο ansible υπάρχει ένα παράδειγμα αρχείου διαμόρφωσης .ansible.cfg που χρησιμοποιώ. Μπορεί να σου φανεί χρήσιμο.

Πριν δημιουργήσετε εικονικές μηχανές, βεβαιωθείτε ότι έχετε ssh-agent σε λειτουργία και ότι έχετε προσθέσει ένα κλειδί ssh, διαφορετικά το terraform δεν θα μπορεί να συνδεθεί με τα μηχανήματα που δημιουργήσατε. Φυσικά, συνάντησα ένα σφάλμα στο os x: https://github.com/ansible/ansible/issues/32499#issuecomment-341578864. Για να μην συμβεί ξανά αυτό, προσθέστε μια μικρή μεταβλητή στο env πριν ξεκινήσετε το Terraform:

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

Στο φάκελο με το terraform δημιουργούμε τους απαραίτητους πόρους:

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

Εάν όλα τελείωσαν με επιτυχία (και θα έπρεπε να είναι), τότε θα έχουμε τρεις εικονικές μηχανές:

  1. build - μια μηχανή για δοκιμή και κατασκευή μιας εφαρμογής. Το Docker εγκαταστάθηκε αυτόματα από την Ansible.
  2. παρακολούθηση - μηχάνημα παρακολούθησης - εγκατεστημένο σε αυτό προμηθέας & γραφάνα. Σύνδεση / κωδικός πρόσβασης πρότυπο: admin / admin
  3. Το kafka είναι ένα μικρό μηχάνημα με εγκατεστημένο το kafka, προσβάσιμο στη θύρα 9092.

Ας βεβαιωθούμε ότι είναι όλα στη θέση τους:

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

Οι πόροι είναι διαθέσιμοι και από εδώ μπορούμε να λάβουμε τις διευθύνσεις IP τους. Σε όλα τα παρακάτω θα χρησιμοποιώ διευθύνσεις IP για να συνδεθώ μέσω ssh και να δοκιμάσω την εφαρμογή. Εάν έχετε έναν λογαριασμό cloudflare συνδεδεμένο στο terraform, μη διστάσετε να χρησιμοποιήσετε πρόσφατα δημιουργημένα ονόματα DNS.
Παρεμπιπτόντως, κατά τη δημιουργία μιας εικονικής μηχανής, δίνεται μια εσωτερική IP και ένα εσωτερικό όνομα DNS, ώστε να μπορείτε να έχετε πρόσβαση σε διακομιστές εντός του δικτύου με το όνομα:

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

Αυτό θα είναι χρήσιμο για να υποδείξουμε στην εφαρμογή το τελικό σημείο με το kafk.

Συναρμολόγηση της εφαρμογής

Υπέροχα, υπάρχουν διακομιστές, υπάρχει μια εφαρμογή - το μόνο που μένει είναι να τη συναρμολογήσουμε και να τη δημοσιεύσουμε. Για την κατασκευή θα χρησιμοποιήσουμε τη συνηθισμένη κατασκευή docker, αλλά ως αποθήκευση εικόνας θα χρησιμοποιήσουμε μια υπηρεσία από το Yandex - μητρώο κοντέινερ. Πρώτα όμως πρώτα.

Αντιγράφουμε την εφαρμογή στη μηχανή κατασκευής, συνδέουμε μέσω ssh και συναρμολογούμε την εικόνα:

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

Η μισή μάχη έχει τελειώσει - τώρα μπορούμε να ελέγξουμε τη λειτουργικότητα της εφαρμογής μας εκκινώντας την και στέλνοντάς την στο 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) $

Η εφαρμογή απάντησε με επιτυχία της εγγραφής και υποδεικνύοντας το αναγνωριστικό του διαμερίσματος και της μετατόπισης στο οποίο συμπεριλήφθηκε το μήνυμα. Το μόνο που μένει να κάνετε είναι να δημιουργήσετε ένα μητρώο στο Yandex.Cloud και να ανεβάσετε την εικόνα μας εκεί (το πώς να το κάνετε αυτό χρησιμοποιώντας τρεις γραμμές περιγράφεται στο αρχείο registry.tf). Δημιουργία αποθηκευτικού χώρου:

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.

Υπάρχουν διάφοροι τρόποι για έλεγχο ταυτότητας στο μητρώο κοντέινερ - χρησιμοποιώντας ένα διακριτικό oauth, ένα διακριτικό iam ή ένα κλειδί λογαριασμού υπηρεσίας. Περισσότερες λεπτομέρειες σχετικά με αυτές τις μεθόδους μπορείτε να βρείτε στην τεκμηρίωση. https://cloud.yandex.ru/docs/container-registry/operations/authentication. Θα χρησιμοποιήσουμε το κλειδί λογαριασμού υπηρεσίας, επομένως δημιουργούμε έναν λογαριασμό:

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.

Τώρα το μόνο που μένει είναι να φτιάξουμε ένα κλειδί για αυτό:

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

Λαμβάνουμε πληροφορίες σχετικά με το αναγνωριστικό του αποθηκευτικού μας χώρου, μεταφέρουμε το κλειδί και συνδεόμαστε:

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

Για να ανεβάσουμε την εικόνα στο μητρώο, χρειαζόμαστε το αναγνωριστικό μητρώου κοντέινερ, το παίρνουμε από το βοηθητικό πρόγραμμα yc:

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

Μετά από αυτό, προσθέτουμε ετικέτα στην εικόνα μας με ένα νέο όνομα και ανεβάζουμε:

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

Μπορούμε να επαληθεύσουμε ότι η εικόνα φορτώθηκε με επιτυχία:

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

Παρεμπιπτόντως, εάν εγκαταστήσετε το βοηθητικό πρόγραμμα yc σε μια μηχανή Linux, μπορείτε να χρησιμοποιήσετε την εντολή

yc container registry configure-docker

για να ρυθμίσετε το docker.

Συμπέρασμα

Κάναμε πολύ σκληρή δουλειά και ως αποτέλεσμα:

  1. Καταλήξαμε στην αρχιτεκτονική της μελλοντικής μας υπηρεσίας.
  2. Γράψαμε μια εφαρμογή σε golang που εφαρμόζει την επιχειρηματική μας λογική.
  3. Το συλλέξαμε και το χύσαμε σε ένα ιδιωτικό μητρώο κοντέινερ.

Στο επόμενο μέρος, θα προχωρήσουμε στα ενδιαφέροντα πράγματα - θα κυκλοφορήσουμε την εφαρμογή μας στην παραγωγή και τελικά θα ξεκινήσουμε το φορτίο σε αυτήν. Μην αλλάζετε!

Αυτό το υλικό βρίσκεται στη βιντεοσκόπηση του ανοιχτού εργαστηρίου REBRAIN & Yandex.Cloud: Δεχόμαστε 10 αιτήματα ανά δευτερόλεπτο στο Yandex Cloud - https://youtu.be/cZLezUm0ekE

Εάν ενδιαφέρεστε να παρακολουθήσετε τέτοιες εκδηλώσεις διαδικτυακά και να κάνετε ερωτήσεις σε πραγματικό χρόνο, συνδεθείτε στο κανάλι DevOps από το REBRAIN.

Θα θέλαμε να πούμε ένα ιδιαίτερο ευχαριστώ στο Yandex.Cloud για την ευκαιρία να φιλοξενήσει μια τέτοια εκδήλωση. Σύνδεσμος με αυτούς - https://cloud.yandex.ru/prices

Εάν πρέπει να μεταβείτε στο cloud ή έχετε ερωτήσεις σχετικά με την υποδομή σας, μη διστάσετε να αφήσετε ένα αίτημα.

Υ.Γ. Έχουμε 2 δωρεάν ελέγχους το μήνα, ίσως το έργο σας να είναι ένας από αυτούς.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο