TL; DR : Deskripsi arsitektur client-server dari sistem manajemen konfigurasi jaringan internal kami, QControl. Ini didasarkan pada protokol transportasi dua tingkat yang bekerja dengan pesan yang dikemas gzip tanpa dekompresi antara titik akhir. Router dan titik akhir yang didistribusikan menerima pembaruan konfigurasi, dan protokol itu sendiri memungkinkan pemasangan relay menengah terlokalisasi. Sistem ini dibangun berdasarkan prinsip
cadangan diferensial ("stable-stable", dijelaskan di bawah) dan menggunakan bahasa permintaan JMESpath bersama dengan mesin template Jinja untuk membuat file konfigurasi.
Qrator Labs mengelola jaringan mitigasi serangan yang didistribusikan secara global. Jaringan kami bekerja berdasarkan prinsip anycast, dan subnet diumumkan melalui BGP. Menjadi jaringan BGP anycast yang secara fisik terletak di beberapa wilayah di Bumi, kami dapat memproses dan menyaring lalu lintas ilegal yang lebih dekat ke inti Internet - operator Tier-1.
Di sisi lain, menjadi jaringan yang didistribusikan secara geografis tidak mudah. Komunikasi antara titik-titik keberadaan jaringan sangat penting bagi penyedia layanan keamanan untuk memiliki konfigurasi yang konsisten dari semua node jaringan, memperbaruinya secara tepat waktu. Oleh karena itu, untuk menyediakan layanan dasar tingkat tertinggi bagi konsumen, kami perlu menemukan cara untuk menyinkronkan data konfigurasi dengan andal antar benua.
Pada mulanya adalah Firman. Dengan cepat menjadi protokol komunikasi yang membutuhkan pembaruan.
Landasan keberadaan QControl dan pada saat yang sama alasan utama untuk menghabiskan sejumlah besar waktu dan sumber daya untuk membangun protokol semacam itu adalah kebutuhan untuk mendapatkan sumber konfigurasi otoritatif tunggal dan, pada akhirnya, menyinkronkan titik kehadiran kami dengannya. Repositori itu sendiri hanyalah salah satu dari beberapa persyaratan selama pengembangan QControl. Selain itu, kami juga membutuhkan integrasi dengan layanan yang ada dan yang direncanakan di titik-titik keberadaan (TP), metode validasi data yang cerdas (dan kustom), serta kontrol akses. Selain itu, kami juga ingin mengelola sistem seperti itu menggunakan perintah, daripada membuat modifikasi pada file. Sebelum QControl, data dikirim ke titik kehadiran dalam mode hampir manual. Jika salah satu titik kehadiran tidak tersedia, dan kami lupa untuk memperbaruinya nanti, konfigurasi ternyata tidak sinkron - Anda harus menghabiskan waktu mengembalikannya ke layanan.
Hasilnya, kami membuat skema berikut:

Server konfigurasi bertanggung jawab atas validasi dan penyimpanan data, router memiliki beberapa titik akhir yang menerima dan menyiarkan pembaruan konfigurasi dari klien dan tim pendukung ke server, dan dari server ke titik keberadaan.
Kualitas koneksi internet masih sangat berbeda di berbagai belahan dunia - untuk menggambarkan tesis ini, mari kita lihat MTR sederhana dari Praha, Republik Ceko ke Singapura dan Hong Kong.

MTR dari Praha ke Singapura

Hal yang sama untuk hong kong
Penundaan tinggi berarti lebih sedikit kecepatan. Selain itu, ada paket loss. Lebar saluran tidak mengkompensasi masalah ini, yang harus selalu diperhitungkan ketika membangun sistem desentralisasi.
Konfigurasi titik penuh kehadiran adalah sejumlah besar data yang perlu dikirim ke banyak penerima melalui koneksi yang tidak dipercaya. Untungnya, meskipun konfigurasi terus berubah, ini terjadi dalam porsi kecil.
Desain terkini-stabil
Kita dapat mengatakan bahwa membangun jaringan terdistribusi dengan prinsip pembaruan tambahan adalah solusi yang cukup jelas. Tetapi ada banyak masalah dengan diff. Kami harus menyimpan semua perbedaan di antara titik kontrol, dan juga dapat mengirimnya jika seseorang melewatkan beberapa data. Setiap tujuan harus menerapkannya dalam urutan yang ditentukan secara ketat. Biasanya, dalam kasus beberapa tujuan, operasi semacam itu bisa memakan waktu lama. Penerima juga harus dapat meminta bagian yang hilang dan, tentu saja, bagian pusat harus menanggapi permintaan tersebut dengan benar, hanya mengirimkan data yang hilang.
Akibatnya, kami sampai pada solusi yang agak menarik - kami hanya memiliki satu lapisan dukungan, diperbaiki, sebut saja itu stabil, dan hanya satu perbedaan untuk itu baru-baru ini. Setiap terbaru didasarkan pada stabil terakhir yang dibentuk dan cukup untuk membangun kembali data konfigurasi. Begitu baru baru tiba di tujuannya, yang lama tidak lagi diperlukan.
Hanya tetap dari waktu ke waktu mengirim konfigurasi stabil yang baru, misalnya, karena kenyataan bahwa belakangan ini telah menjadi terlalu besar. Penting juga di sini bahwa kami mengirim semua pembaruan ini dalam mode siaran / multicast, tanpa khawatir tentang masing-masing penerima dan kemampuan mereka untuk mengumpulkan potongan-potongan data bersama. Segera setelah kami yakin bahwa setiap orang memiliki stabil yang benar, kami hanya mengirim yang baru. Apakah layak untuk menjelaskan bahwa ini berhasil? Itu bekerja. Stabil di-cache di server konfigurasi dan penerima, baru-baru ini dibuat sesuai kebutuhan.
Arsitektur Transportasi Dua Tingkat
Mengapa kami membangun transportasi di dua tingkat? Jawabannya cukup sederhana - kami ingin memisahkan rute dari logika tingkat tinggi, menggambar inspirasi dari model OSI dengan lapisan transport dan lapisan aplikasi. Untuk peran protokol transport, kami mengambil Thrift, dan untuk format pesan kontrol tingkat tinggi, format serialisasi msgpack. Itulah sebabnya router (mengeksekusi multicast / broadcast / relay) tidak melihat ke dalam msgpack, tidak membongkar dan tidak mengemas konten kembali, dan hanya melakukan transfer data.
Thrift (dari bahasa Inggris - “thrift”, diucapkan [θrift]) adalah bahasa deskripsi antarmuka yang digunakan untuk mendefinisikan dan membuat layanan untuk berbagai bahasa pemrograman. Ini adalah kerangka kerja untuk panggilan prosedur jarak jauh (RPC). Ini menggabungkan saluran perangkat lunak dengan mesin pembuatan kode untuk mengembangkan layanan yang, pada tingkat tertentu, bekerja secara efisien dan mudah antar bahasa.Kami mengambil kerangka kerja Hemat karena RPC dan dukungan untuk banyak bahasa. Seperti biasa, klien dan server adalah bagian yang mudah. Namun, router tersebut ternyata sangat sulit, sebagian karena kurangnya solusi yang sudah jadi selama pengembangan kami.

Ada beberapa opsi lain, seperti protobuf / gRPC, namun ketika kami memulai proyek kami, gRPC masih sangat muda dan kami tidak berani mengambilnya.
Tentu saja, kami dapat (dan pada kenyataannya, itu layak dilakukan) untuk membuat sepeda kami sendiri. Akan lebih mudah untuk membuat protokol untuk apa yang kita butuhkan, karena arsitektur client-server relatif mudah dalam implementasinya dibandingkan dengan membangun router di Thrift. Dengan satu atau lain cara, ada sikap berprasangka tradisional terhadap protokol yang ditulis sendiri dan implementasi perpustakaan populer (tidak sia-sia), di samping itu, diskusi selalu menimbulkan pertanyaan: "Bagaimana kita akan porting ke bahasa lain?" Karena itu, kami segera membuang ide tentang sepeda.
Msgpack adalah analog dari JSON, tetapi lebih cepat dan lebih sedikit. Ini adalah format serialisasi data biner yang memungkinkan pertukaran data antara berbagai bahasa.Pada tingkat pertama, kami memiliki penghematan dengan informasi minimum yang diperlukan untuk penerusan pesan. Pada tingkat kedua adalah struktur msgpack dikemas.
Kami memilih msgpack karena lebih cepat dan lebih kompak dibandingkan dengan JSON. Tetapi yang lebih penting, ini mendukung tipe data khusus, memungkinkan kami untuk menggunakan fitur keren seperti mentransfer binari mentah atau objek khusus yang menunjukkan kurangnya data, yang penting untuk skema stabil terbaru kami.
JmespathJMESPath adalah bahasa permintaan JSON.Ini persis seperti apa uraiannya, yang kita dapatkan dari dokumentasi resmi JMESPath, tetapi pada kenyataannya, itu memberi lebih banyak. JMESPath memungkinkan Anda untuk mencari dan memfilter sub pohon dalam struktur pohon yang berubah-ubah, serta menerapkan perubahan pada data dengan cepat. Ini juga memungkinkan Anda untuk menambahkan filter khusus dan prosedur konversi data. Meskipun, tentu saja, itu membutuhkan ketegangan otak untuk mengerti.
JinjaBagi sebagian konsumen, kami perlu mengubah konfigurasi menjadi file - jadi kami menggunakan mesin template dan Jinja adalah pilihan yang jelas. Dengan bantuannya, kami membuat file konfigurasi dari template dan data yang diterima di tujuan.
Untuk menghasilkan file konfigurasi, kita memerlukan permintaan JMESPath, templat untuk lokasi file di FS, templat untuk konfigurasi itu sendiri. Juga pada tahap ini menyenangkan untuk memperjelas izin file. Semua ini ternyata berhasil digabungkan dalam satu file - sebelum dimulainya template konfigurasi, kami menempatkan header dalam format YAML, yang menggambarkan sisanya.
Sebagai contoh:
---
selector: "[@][?@.fft._meta.version == `42`] | items([0].fft_config || `{}`)"
destination_filename: "fft/{{ match[0] }}.json"
file_mode: 0644
reload_daemons: [fft]
...
{{ dict(match[1]) | json(indent=2, sort_keys=True) }}
Untuk membuat file konfigurasi untuk layanan baru, kami hanya menambahkan file template baru. Tidak ada perubahan pada kode sumber atau perangkat lunak pada titik kehadiran diperlukan.
Apa yang telah berubah sejak QControl diperkenalkan ke dalam operasi? Yang pertama dan paling penting adalah pengiriman pembaruan konfigurasi yang konsisten dan andal di semua node dalam jaringan. Yang kedua adalah untuk mendapatkan alat verifikasi konfigurasi yang kuat dan mengubahnya oleh tim dukungan kami, serta oleh konsumen layanan.
Kami berhasil melakukan semua ini menggunakan skema pembaruan terkini-stabil untuk menyederhanakan komunikasi antara server konfigurasi dan penerima konfigurasi. Menggunakan protokol dua lapis untuk mendukung metode perutean data independen konten. Setelah berhasil mengintegrasikan mesin generasi konfigurasi berbasis Jinja ke jaringan penyaringan terdistribusi. Sistem ini mendukung berbagai metode konfigurasi untuk periferal terdistribusi dan beraneka ragam kami.
Terima kasih telah menulis materi, terima kasih kepada
VolanDamrod ,
serenheit ,
NoN .
Versi bahasa Inggris dari pos.