Membangun Aplikasi di .NET Core dan Kubernetes: Pengalaman Kami

Halo semuanya!

Hari ini kita akan berbicara tentang pengalaman salah satu proyek DevOps kami. Kami memutuskan untuk mengimplementasikan aplikasi baru untuk Linux menggunakan .Net Core pada arsitektur microservice.

Kami berharap proyek ini akan berkembang secara aktif, dan akan ada semakin banyak pengguna. Oleh karena itu, harus mudah diukur baik dari segi fungsionalitas dan kinerja.

Kami membutuhkan sistem yang toleran terhadap kesalahan - jika salah satu blok fungsi tidak berfungsi, maka sisanya akan berfungsi. Kami juga ingin memastikan integrasi berkelanjutan, termasuk penyebaran solusi di server pelanggan.

Oleh karena itu, kami menggunakan teknologi berikut:

  • .Net Core untuk implementasi layanan microser. Proyek kami menggunakan versi 2.0,
  • Kubernet untuk orkestra layanan microser,
  • Docker untuk membuat gambar microservice,
  • bus integrasi Rabbit MQ dan Mass Transit,
  • Elasticsearch dan Kibana untuk logging,
  • TFS untuk mengimplementasikan pipa CI / CD.

Artikel ini akan membagikan perincian solusi kami.



Ini adalah transkrip pidato kami di pertemuan .NET, di sini ada tautan ke video pidato tersebut.

Tantangan bisnis kami


Pelanggan kami adalah perusahaan federal di mana ada pedagang - ini adalah orang-orang yang bertanggung jawab atas bagaimana barang disajikan di toko. Dan ada pengawas - ini adalah para pemimpin pedagang.

Perusahaan memiliki proses pelatihan dan evaluasi pekerjaan pedagang oleh pengawas, yang perlu diotomatisasi.



Begini cara solusi kami bekerja:

1. Pengawas menyusun kuesioner - ini adalah daftar periksa apa yang perlu Anda periksa dalam pekerjaan merchandiser.
2. Selanjutnya, penyelia memilih karyawan yang pekerjaannya akan diperiksa. Tanggal pertanyaan diberikan.
3. Selanjutnya, kegiatan dikirim ke perangkat seluler pengawas.
4. Kemudian kuesioner diisi dan dikirim ke portal.
5. Portal menghasilkan hasil dan berbagai laporan.

Microservices akan membantu kami memecahkan tiga masalah:


1. Di masa depan, kami ingin memperluas fungsionalitasnya, karena ada banyak proses bisnis serupa di perusahaan.
2. Kami ingin solusi menjadi toleran terhadap kesalahan. Jika ada bagian yang berhenti berfungsi, solusi akan dapat mengembalikan kerjanya sendiri, dan kegagalan satu bagian tidak akan sangat mempengaruhi operasi solusi secara keseluruhan.
3. Perusahaan tempat kami mengimplementasikan solusi memiliki banyak cabang. Dengan demikian, jumlah pengguna solusi terus meningkat. Karena itu, saya ingin ini tidak mempengaruhi kinerja.

Sebagai hasilnya, kami memutuskan untuk menggunakan layanan mikro pada proyek ini, yang membutuhkan sejumlah keputusan yang tidak sepele.

Teknologi apa yang membantu menerapkan solusi ini:


• Docker menyederhanakan distribusi distribusi solusi. Distribusi dalam kasus kami adalah satu set gambar microservice
• Karena ada banyak layanan mikro dalam solusi kami, kami perlu mengelolanya. Untuk ini kami menggunakan Kubernetes.
• Kami menerapkan layanan microser menggunakan .Net Core.
• Untuk memperbarui solusi di pelanggan dengan cepat, kita harus menerapkan integrasi dan pengiriman berkelanjutan yang nyaman.

Inilah seluruh rangkaian teknologi kami:

• .Net Core yang kami gunakan untuk membuat layanan microser,
• Microservice dikemas dalam gambar Docker,
• Integrasi berkelanjutan dan pengiriman berkelanjutan diimplementasikan menggunakan TFS,
• Ujung depan diimplementasikan dalam Angular,
• Untuk pemantauan dan penebangan, kami menggunakan Elasticsearch dan Kibana,
• RabbitMQ dan MassTransit digunakan sebagai bus integrasi.

.NET Core untuk Solusi Linux


Kita semua tahu apa itu .Net Framework klasik. Kerugian utama dari platform adalah bahwa itu bukan cross-platform. Karenanya, kami tidak dapat menjalankan solusi pada .Net Framework untuk Linux di Docker.

Untuk memberikan kemampuan untuk menggunakan C # di Docker, Microsoft memikirkan kembali .Net Framework dan membuat .Net Core. Dan untuk menggunakan perpustakaan yang sama, Microsoft menciptakan spesifikasi .Net Standard Library. Majelis .Net Standart Library dapat digunakan di .Net Framework dan .Net Core.



Kubernetes - untuk orkestra layanan microser


Kubernetes digunakan untuk mengelola dan mengelompokkan wadah Docker. Inilah keuntungan utama Kubernet yang telah kami manfaatkan:

- menyediakan kemampuan untuk dengan mudah mengkonfigurasi lingkungan layanan microser,
- Menyederhanakan manajemen lingkungan (Dev, QA, Stage),
- Out of the box menyediakan kemampuan untuk mereplikasi layanan microsoft dan load balancing pada replika.



Arsitektur Solusi


Pada awal pekerjaan, kami bertanya pada diri sendiri bagaimana membagi fungsionalitas menjadi layanan-layanan microser. Divisi ini dibuat berdasarkan prinsip tanggung jawab tunggal, hanya pada tingkat yang lebih besar. Tugas utamanya adalah membuat perubahan dalam satu layanan sesedikit mungkin memengaruhi layanan microser lainnya. Akibatnya, dalam kasus kami, layanan microsoft mulai melakukan area fungsionalitas yang terpisah.

Sebagai hasilnya, kami telah memunculkan layanan yang bergerak dalam perencanaan kuesioner, layanan microser untuk menampilkan hasil, layanan microser untuk bekerja dengan aplikasi mobile, dan layanan microser lainnya.



Opsi untuk berinteraksi dengan pelanggan eksternal


Microsoft dalam bukunya tentang microservices, “ .NET Microservices. Arsitektur Aplikasi Wadah NET. ”Menawarkan tiga kemungkinan implementasi berinteraksi dengan layanan microser. Kami meninjau ketiganya dan memilih yang paling cocok.

• Layanan API Gateway
API layanan Gateway adalah implementasi fasad untuk permintaan pengguna untuk layanan lain. Masalah dengan solusi adalah jika fasad tidak berfungsi, maka seluruh solusi akan berhenti berfungsi. Mereka memutuskan untuk meninggalkan pendekatan ini untuk toleransi kesalahan.

• API Gateway dengan Azure API Management
Microsoft menyediakan kemampuan untuk menggunakan fasad cloud di Azure. Tetapi solusi ini tidak cocok, karena kami akan menyebarkan solusi tidak di cloud, tetapi di server pelanggan.

• Komunikasi langsung Client-To-Microservice
Akibatnya, kami memiliki opsi terakhir untuk berinteraksi langsung dengan pengguna dengan layanan Microsoft. Kami memilihnya.



Ini plus dalam toleransi kesalahan. Kelemahannya adalah bahwa bagian dari fungsi harus direproduksi pada setiap layanan secara terpisah. Sebagai contoh, itu perlu untuk mengkonfigurasi otorisasi secara terpisah pada setiap microservice yang pengguna memiliki akses.

Tentu saja, muncul pertanyaan tentang bagaimana kita akan menyeimbangkan beban dan bagaimana toleransi kesalahan diimplementasikan. Semuanya sederhana di sini - Ingress Controller Kubernetes melakukan ini.



Node 1, simpul 2 dan simpul 3 adalah replika dari layanan Microsoft yang sama. Jika salah satu replika gagal, penyeimbang beban akan secara otomatis mengalihkan beban ke layanan microser lainnya.

Arsitektur fisik


Inilah cara kami mengatur infrastruktur solusi kami:

• Setiap microservice memiliki database sendiri (jika dia, tentu saja, membutuhkannya), layanan lain tidak mengakses database microservice lain.
• Layanan Microsoft berkomunikasi satu sama lain hanya melalui bus RabbitMQ + Mass Transit, serta menggunakan permintaan HTTP.
• Setiap layanan memiliki tanggung jawab yang jelas.
• Untuk logging, kami menggunakan Elasticsearch dan Kibana dan perpustakaan untuk bekerja dengannya Serilog .



Layanan database dikerahkan pada mesin virtual terpisah, dan tidak di Kubernetes, karena Microsoft DBMS tidak merekomendasikan menggunakan Docker di lingkungan produk.

Layanan logging juga dikerahkan pada mesin virtual terpisah untuk alasan toleransi kesalahan - jika kita memiliki masalah dengan Kubernetes, maka kita dapat mencari tahu apa masalahnya.

Penempatan: bagaimana kami mengatur pengembangan dan lingkungan produk


Infrastruktur kami memiliki 3 ruang nama di Kubernetes. Ketiga lingkungan mengakses satu layanan basis data dan satu layanan pencatatan. Dan, tentu saja, setiap lingkungan melihat basis datanya sendiri.



Pada infrastruktur pelanggan, kami juga memiliki dua lingkungan - pra-produksi dan produksi. Di bagian produksi, kami memiliki server basis data terpisah untuk lingkungan pra-penjualan dan produk. Untuk logging, kami telah mengalokasikan satu server ELK pada infrastruktur kami dan pada infrastruktur pelanggan.

Bagaimana cara menyebarkan 5 lingkungan dengan masing-masing 10 layanan microser?


Rata-rata, kami memiliki 10 layanan per proyek dan tiga lingkungan: QA, DEV, Stage, di mana sekitar 30 layanan mikro disebarkan secara total. Dan ini hanya pada infrastruktur pengembangan! Tambahkan 2 lingkungan lagi di infrastruktur pelanggan, dan kami mendapatkan 50 layanan mikro.



Jelaslah bahwa sejumlah layanan semacam itu entah bagaimana harus dikelola. Kubernetes membantu kita dengan ini.

Untuk menggunakan layanan Microsoft, Anda harus
• Perluas rahasia,
• Menyebarkan penyebaran,
• Perluas layanan.

Tentang rahasia tulis di bawah ini.
Penempatan adalah instruksi untuk Kubernetes, atas dasar itu akan meluncurkan wadah Docker dari layanan Microsoft kami. Berikut adalah perintah yang digunakan penyebaran:

kubectl apply -f .\(yaml deployment-) --namespace=DEV

 apiVersion: apps/v1beta1 kind: Deployment metadata: name: imtob-etr-it-dictionary-api spec: replicas: 1 template: metadata: labels: name: imtob-etr-it-dictionary-api spec: containers: - name: imtob-etr-it-dictionary-api image: nexus3.company.ru:18085/etr-it-dictionary-api:18289 resources: requests: memory: "256Mi" limits: memory: "512Mi" volumeMounts: - name: secrets mountPath: /app/secrets readOnly: true volumes: - name: secrets secret: secretName: secret-appsettings-dictionary 


File ini menjelaskan apa yang disebut penyebaran (imtob-etr-it-dictionary-api), gambar apa yang perlu digunakan untuk eksekusi, ditambah pengaturan lainnya. Di bagian rahasia, kami akan menyesuaikan lingkungan kami.

Setelah menyebarkan penyebaran, kami perlu menyebarkan layanan, jika perlu.

Layanan diperlukan ketika akses ke layanan mikro dari luar diperlukan. Misalnya, ketika Anda ingin pengguna atau layanan microser lain dapat membuat permintaan Dapatkan ke layanan microser lain.

kubectl apply -f .\imtob-etr-it-dictionary-api.yml --namespace=DEV

 apiVersion: v1 kind: Service metadata: name: imtob-etr-it-dictionary-api-services spec: ports: - name: http port: 80 targetPort: 80 protocol: TCP selector: name: imtob-etr-it-dictionary-api 


Biasanya deskripsi layanan kecil. Di dalamnya kita melihat nama layanan, bagaimana dapat diakses dan nomor port.

Akibatnya, untuk menyebarkan lingkungan, kita perlu

• satu set file dengan rahasia untuk semua layanan microser,
• satu set file dengan penyebaran semua layanan microser,
• satu set file dengan layanan semua layanan microser.

Kami menyimpan semua skrip ini di repositori git.

Untuk menyebarkan solusi, kami mendapat satu set tiga jenis skrip:

• folder dengan rahasia - ini adalah konfigurasi untuk setiap lingkungan,
• folder dengan penyebaran untuk semua layanan microser,
• folder dengan layanan untuk beberapa layanan microser,

di masing-masing - sekitar sepuluh tim, satu untuk setiap layanan mikro. Untuk kenyamanan, kami telah membuat halaman dengan skrip dalam Confluence, yang membantu kami dengan cepat menyebarkan lingkungan baru.

Berikut ini adalah skrip penyebaran penggunaan (ada set yang sama untuk rahasia dan untuk layanan):

Script penempatan
kubectl terapkan -f. \ imtob-etr-it-image-api.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-mobile-api.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-planning-api.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-result-api.yml --namespace = DEV
kubectl menerapkan -f. \ imtob-etr-it-web.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-report-api.yml --namespace = DEV
kubectl menerapkan -f. \ imtob-etr-it-template-constructor-api.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-dictionary-api.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-integrasi-api.yml --namespace = DEV
kubectl terapkan -f. \ imtob-etr-it-identity-api.yml --namespace = DEV


Implementasi CI / CD



Setiap layanan ada di foldernya sendiri, ditambah lagi kami memiliki satu folder dengan komponen umum.



Ada juga Build Definition dan Release Definition untuk setiap layanan Microsoft. Kami mengonfigurasi peluncuran Build Definion ketika melakukan ke layanan yang sesuai atau ketika melakukan ke folder yang sesuai. Jika isi folder dengan komponen umum diperbarui, maka semua layanan microsoft digunakan.

Apa keuntungan dari organisasi Build seperti itu?

1. Solusinya ada dalam satu repositori git,
2. Ketika mengganti beberapa layanan microser, rakitan mulai paralel dengan agen rakitan gratis,
3. Setiap Build Definition menyajikan skrip sederhana dari pembuatan gambar dan mendorongnya ke Nexus Registry.

Buat definisi dan Definisi Rilis


Cara menggunakan agen VSTS, kami sebelumnya dijelaskan dalam artikel ini .



Pertama adalah Build Definition. Pada perintah TFS VSTS, agen meluncurkan build Dockerfile. Sebagai hasilnya, kami mendapatkan gambar dari layanan microser. Gambar ini disimpan secara lokal di lingkungan tempat agen VSTS berjalan.

Setelah pembuatan, Push diluncurkan, yang mengirimkan gambar yang kami terima di langkah sebelumnya ke Nexus Registry. Sekarang dapat digunakan secara eksternal. Nexus Registry adalah sejenis Nuget, tidak hanya untuk perpustakaan, tetapi untuk gambar Docker dan banyak lagi.

Setelah gambar siap dan dapat diakses dari luar, Anda perlu menggunakannya. Untuk ini kami memiliki Definisi Rilis. Semuanya sederhana di sini - kami menjalankan perintah set image:

kubectl set image deployment/imtob-etr-it-dictionary-api imtob-etr-it-dictionary-api=nexus3.company.ru:18085/etr-it-dictionary-api:$(Build.BuildId)

Setelah itu, ia akan memperbarui gambar untuk microservice yang diinginkan dan meluncurkan wadah baru. Akibatnya, layanan kami telah diperbarui.

Sekarang mari kita bandingkan build dengan dan tanpa Dockerfile.



Tanpa Dockerfile, kami mendapatkan banyak langkah, yang memiliki banyak spesifikasi .Net. Di sebelah kanan kita melihat build gambar Docker. Segalanya menjadi jauh lebih mudah.

Seluruh proses pembuatan gambar dijelaskan dalam Dockerfile. Majelis ini dapat di-debug secara lokal.



Total: kami mendapatkan CI / CD sederhana dan transparan



1. Pemisahan pengembangan dan penyebaran. Perakitan dijelaskan dalam Dockerfile dan terletak di pundak pengembang.
2. Saat mengkonfigurasi CI / CD, Anda tidak perlu tahu tentang detail dan fitur perakitan - pekerjaan hanya dilakukan dengan Dockerfile.
3. Kami hanya memperbarui microservices yang diubah.

Selanjutnya, Anda perlu mengkonfigurasi RabbitMQ di K8S: kami menulis artikel terpisah tentang ini.

Pengaturan lingkungan


Dengan satu atau lain cara, kita perlu mengkonfigurasi layanan microser. Bagian utama dari lingkungan dikonfigurasi dalam file konfigurasi root Appsettings.json. File ini berisi pengaturan yang independen terhadap lingkungan.

Pengaturan yang bergantung pada lingkungan disimpan dalam folder rahasia di file appsettings.secret.json. Kami mengambil pendekatan yang dijelaskan dalam artikel Mengelola Pengaturan Aplikasi Inti ASP.NET di Kubernetes .

 var configuration = new ConfigurationBuilder() .AddJsonFile($"appsettings.json", true) .AddJsonFile("secrets/appsettings.secrets.json", optional: true) .Build(); 


File appsettings.secrets.json berisi pengaturan untuk indeks Pencarian Elastis dan string koneksi database.
 { "Serilog": { "WriteTo": [ { "Name": "Elasticsearch", "Args": { "nodeUris": "http://192.168.150.114:9200", "indexFormat": "dev.etr.it.ifield.api.dictionary-{0:yyyy.MM.dd}", "templateName": "dev.etr.it.ifield.api.dictionary", "typeName": "dev.etr.it.ifield.api.dictionary.event" } } ] }, "ConnectionStrings": { "DictionaryDbContext": "Server=192.168.154.162;Database=DEV.ETR.IT.iField.Dictionary;User Id=it_user;Password=PASSWORD;" } } 


Tambahkan file konfigurasi ke Kubernetes


Untuk menambahkan file ini, Anda perlu menggunakannya di wadah Docker. Ini dilakukan dalam file penyebaran Kubernetis. Penyebaran menjelaskan di folder mana file rahasia c harus dibuat dan dengan rahasia apa diperlukan untuk mengaitkan file tersebut.

 apiVersion: apps/v1beta1 kind: Deployment metadata: name: imtob-etr-it-dictionary-api spec: replicas: 1 template: metadata: labels: name: imtob-etr-it-dictionary-api spec: containers: - name: imtob-etr-it-dictionary-api image: nexus3.company.ru:18085/etr-it-dictionary-api:18289 resources: requests: memory: "256Mi" limits: memory: "512Mi" volumeMounts: - name: secrets mountPath: /app/secrets readOnly: true volumes: - name: secrets secret: secretName: secret-appsettings-dictionary 


Anda dapat membuat rahasia di Kubernetes menggunakan utilitas kubectl. Kita lihat di sini nama rahasia dan jalur ke file. Kami juga menunjukkan nama lingkungan tempat kami membuat rahasia.

kubectl create secret generic secret-appsettings-dictionary
--from-file=./Dictionary/appsettings.secrets.json --namespace=DEMO


Kesimpulan


Kontra dari pendekatan yang dipilih


1. Ambang entri tinggi. Jika Anda melakukan proyek semacam itu untuk pertama kalinya, akan ada banyak informasi baru.
2. Layanan Mikro → desain yang lebih kompleks. Kita perlu menerapkan banyak solusi yang tidak jelas karena fakta bahwa kita tidak memiliki solusi monolitik, tetapi solusi microservice.
3. Tidak semuanya diimplementasikan untuk Docker. Tidak semuanya dapat dijalankan dalam arsitektur layanan mikro. Misalnya, saat SSRS tidak ada di buruh pelabuhan.

Kelebihan dari pendekatan yang diuji sendiri


1. Infrastruktur sebagai kode
Deskripsi infrastruktur disimpan dalam kontrol sumber. Pada saat penempatan, Anda tidak perlu menyesuaikan lingkungan.
2. Penskalaan baik pada tingkat fungsionalitas dan pada tingkat kinerja di luar kotak.
3. Layanan mikro terisolasi dengan baik
Praktis tidak ada bagian yang penting, kegagalan yang mengarah pada ketidakmampuan sistem secara keseluruhan.
4. Pengiriman perubahan yang cepat
Hanya layanan microser yang telah ada pembaruan yang diperbarui. Jika Anda tidak memperhitungkan waktu untuk koordinasi dan hal-hal lain yang berkaitan dengan faktor manusia, maka memperbarui satu layanan mikro berlangsung dalam 2 menit atau kurang.

Kesimpulan untuk kita


1. Pada .NET Core, Anda dapat dan harus menerapkan solusi industri.
2. K8S benar-benar membuat hidup lebih mudah, menyederhanakan pembaruan lingkungan, memfasilitasi konfigurasi layanan.
3. TFS dapat digunakan untuk mengimplementasikan CI / CD untuk Linux.

Source: https://habr.com/ru/post/id420665/


All Articles