CI/CD untuk arsitektur layanan mikro

Azure

Siklus rilis yang lebih cepat adalah salah satu keuntungan utama dari arsitektur layanan mikro. Tetapi tanpa proses CI / CD yang baik, Anda tidak akan mencapai kelincahan yang dijanjikan oleh layanan mikro. Artikel ini menjelaskan tantangan dan merekomendasikan beberapa pendekatan untuk masalah ini.

Apa itu CI/CD?

Ketika kita berbicara tentang CI / CD, kami benar-benar berbicara tentang beberapa proses terkait: Integrasi berkelanjutan, pengiriman berkelanjutan, dan penyebaran berkelanjutan.

  • Integrasi berkelanjutan Perubahan kode sering digabungkan ke cabang utama. Proses pembuatan dan pengujian otomatis memastikan bahwa kode di cabang utama selalu berkualitas produksi.

  • Pengiriman berkelanjutan Perubahan kode apa pun yang lulus proses CI secara otomatis dipublikasikan ke lingkungan seperti produksi. Penerapan ke dalam lingkungan produksi langsung mungkin membutuhkan persetujuan manual, tetapi sebaliknya otomatis. Tujuannya adalah agar kode Anda selalu siap untuk diterapkan ke dalam produksi.

  • Penyebaran berkelanjutan. Perubahan kode yang melewati dua langkah sebelumnya secara otomatis diterapkan ke dalam produksi.

Berikut ini beberapa tujuan dari proses CI/CD yang kuat untuk arsitektur layanan mikro:

  • Setiap tim dapat membuat dan menyebarkan layanan yang dimilikinya secara independen, tanpa memengaruhi atau mengganggu tim lain.

  • Sebelum layanan versi baru ditempatkan ke produksi, versi ini akan ditempatkan ke lingkungan dev/test/QA untuk validasi. Gerbang kualitas akan diberlakukan pada setiap tahap.

  • Layanan versi baru dapat ditempatkan secara berdampingan dengan versi sebelumnya.

  • Kebijakan kontrol akses yang memadai sudah ada.

  • Untuk pembatasan beban kerja, Anda dapat mempercayai gambaran wadah yang ditempatkan ke produksi.

Mengapa saluran pipa CI/CD yang kuat berpengaruh

Dalam aplikasi monolitik tradisional, ada saluran pipa build tunggal yang keluarannya adalah aplikasi yang dapat dieksekusi. Semua pekerjaan pengembangan masuk ke dalam saluran ini. Jika bug prioritas tinggi ditemukan, perbaikan harus diintegrasikan, diuji, dan dipublikasikan, yang dapat menunda rilis fitur baru. Anda dapat mengurangi masalah ini dengan memiliki modul yang diperhitungkan dengan baik dan menggunakan cabang fitur untuk meminimalkan dampak perubahan kode. Tetapi ketika aplikasi tumbuh lebih kompleks, dan lebih banyak fitur ditambahkan, proses rilis untuk monolit cenderung menjadi lebih rapuh dan cenderung rusak.

Sejalan dengan filosofi layanan mikro, seharusnya tidak pernah ada kereta rilis panjang di mana setiap tim harus mengantre. Tim yang membangun layanan "A" dapat merilis pembaruan kapan saja, tanpa menunggu perubahan dalam layanan "B" untuk digabungkan, diuji, dan diterapkan.

Diagram monolit CI/CD

Untuk mencapai kecepatan pelepasan yang tinggi, jalur pelepasan Anda harus otomatis dan sangat andal untuk meminimalkan risiko. Jika Anda merilis ke produksi satu atau beberapa kali setiap hari, regresi atau gangguan layanan harus jarang terjadi. Pada saat yang bersamaan, jika pembaruan yang buruk diterapkan, Anda harus memiliki cara yang andal untuk melakukan roll back atau roll forward ke versi layanan sebelumnya dengan cepat.

Tantangan

  • Banyak basis kode independen kecil. Setiap tim bertanggung jawab untuk membangun layanannya sendiri, dengan saluran pembuatannya sendiri. Di beberapa organisasi, tim dapat menggunakan repositori kode terpisah. Repositori terpisah bisa mengarah ke situasi di mana pengetahuan tentang cara membangun sistem tersebar di seluruh tim, dan tidak ada di organisasi yang tahu bagaimana mengerahkan seluruh aplikasi. Misalnya, apa yang terjadi dalam skenario pemulihan bencana, jika Anda membutuhkan penyebaran ke cluster baru dengan cepat?

    Mitigasi: Memiliki saluran terpadu dan otomatis untuk membangun dan menerapkan layanan, sehingga pengetahuan ini tidak "tersembunyi" di dalam setiap tim.

  • Beberapa bahasa dan kerangka kerja. Dengan masing-masing tim menggunakan campuran teknologinya sendiri, mungkin sulit untuk membuat satu proses pembuatan yang berfungsi di seluruh organisasi. Proses pembuatan harus cukup fleksibel sehingga setiap tim dapat menyesuaikannya untuk pilihan bahasa atau kerangka kerja mereka.

    Mitigasi: Menampung proses build untuk setiap layanan. Dengan begitu, sistem build hanya perlu bisa menjalankan kontainer.

  • Integrasi dan pengujian beban. Dengan tim yang merilis pembaruan dengan kecepatannya sendiri, dapat sulit untuk merancang pengujian langsung yang kuat, terutama ketika layanan memiliki ketergantungan pada layanan lain. Terlebih lagi, menjalankan kluster produksi penuh bisa menjadi mahal, jadi tidak mungkin setiap tim akan menjalankan kluster penuh sendiri pada skala produksi, hanya untuk pengujian.

  • Manajemen rilis. Setiap tim harus dapat menerapkan pembaruan untuk produksi. Hal itu tidak berarti bahwa setiap anggota tim memiliki izin untuk melakukannya. Tetapi memiliki peran Release Manager terpusat dapat mengurangi kecepatan penyebaran.

    Mitigasi: Semakin CD/CD Anda terproses secara otomatis dan andal, semakin sedikit kebutuhan akan otoritas pusat. Dapat dikatakan, Anda mungkin memiliki kebijakan yang berbeda untuk merilis pembaruan fitur utama versus perbaikan bug kecil. Menjadi terdesentralisasi bukan berarti zero tata kelola.

  • Pembaruan layanan. Saat Anda memperbarui layanan ke versi baru, hal tersebut seharusnya tidak merusak layanan lain yang bergantung padanya.

    Mitigasi: Gunakan teknik penyebaran seperti rilis blue-green atau canary untuk perubahan yang tidak melanggar. Untuk melanggar perubahan API, terapkan versi baru berdampingan dengan versi sebelumnya. Dengan begitu, layanan yang mengkonsumsi API sebelumnya dapat diperbarui dan diuji untuk API baru. Lihat Perbaruan layanan, di bawah ini.

Monorepo vs. multi-repo

Sebelum membuat alur kerja CI/CD, Anda harus tahu bagaimana basis kode akan disusun dan dikelola.

  • Apakah tim bekerja di repositori terpisah atau dalam monorepo (repositori tunggal)?
  • Apa strategi bercabang Anda?
  • Siapa dapat mendorong kode ke produksi? Apakah ada peran manajer rilis?

Pendekatan monorepo telah mendapatkan dukungan tetapi ada kelebihan dan kekurangan untuk keduanya.

  Monorepo Beberapa repo
Kelebihan Berbagi kode
Lebih mudah untuk membakukan kode dan alat
Lebih mudah untuk refactor kode
Discoverability - tampilan tunggal kode
Kepemilikan yang jelas per tim
Berpotensi lebih sedikit konflik penggabungan
Membantu menegakkan decoupling layanan mikro
Tantangan Perubahan pada kode bersama dapat memengaruhi beberapa layanan mikro
Potensi yang lebih besar untuk menggabungkan konflik
Perkakas harus diskalakan ke basis kode besar
Kontrol akses
Proses penyebaran yang lebih kompleks
Lebih sulit untuk berbagi kode
Lebih sulit untuk menegakkan standar pengkodean
Manajemen dependensi
Basis kode yang menyebar, sulit ditemukan
Kurangnya infrastruktur bersama

Memperbarui layanan

Ada berbagai strategi untuk memperbarui layanan yang sudah diproduksi. Di sini kita membahas tiga opsi umum: Pembaruan bergulir, penyebaran biru-hijau, dan rilis canary.

Pembaruan bergulir

Dalam pembaruan bergulir, Anda menerapkan instans layanan baru, dan instans baru mulai menerima permintaan segera. Saat instans baru muncul, instans sebelumnya akan dihapus.

Contoh. Di Kubernetes, pembaruan bergulir adalah perilaku default saat Anda memperbarui spesifikasi pod untuk Deployment. Pengontrol Deployment membuat ReplicaSet baru untuk pod yang diperbarui. Kemudian ia meningkatkan ReplicaSet baru sambil menurunkan yang lama, untuk mempertahankan jumlah replika yang diinginkan. Itu tidak menghapus pod lama sampai yang baru siap. Kubernetes menyimpan riwayat pembaruan, sehingga Anda dapat memutar kembali pembaruan jika diperlukan.

Contoh. Azure Service Fabric menggunakan strategi rolling update secara default. Strategi ini paling cocok untuk menerapkan versi layanan dengan fitur baru tanpa mengubah API yang ada. Service Fabric memulai penyebaran pemutakhiran dengan memperbarui jenis aplikasi ke subset node atau domain pembaruan. Kemudian bergulir ke depan ke domain pembaruan berikutnya sampai semua domain ditingkatkan. Jika domain pemutakhiran gagal diperbarui, jenis aplikasi akan kembali ke versi sebelumnya di semua domain. Sadarilah bahwa jenis aplikasi dengan beberapa layanan (dan jika semua layanan diperbarui sebagai bagian dari satu penyebaran peningkatan) rentan terhadap kegagalan. Jika satu layanan gagal diperbarui, seluruh aplikasi akan diluncurkan kembali ke versi sebelumnya dan layanan lainnya tidak diperbarui.

Salah satu tantangan dari pembaruan bergulir adalah bahwa selama proses pembaruan, campuran versi lama dan baru berjalan dan menerima lalu lintasnya. Selama periode ini, permintaan apa pun dapat dialihkan ke salah satu dari dua versi.

Untuk memecahkan perubahan API, praktik yang baik adalah mendukung kedua versi berdampingan, sampai semua klien dari versi sebelumnya diperbarui. Penerapan versi API

Penyebaran biru/hijau

Dalam penyebaran biru-hijau, Anda menerapkan versi baru bersama versi sebelumnya. Setelah memvalidasi versi baru, Anda mengalihkan semua lalu lintas sekaligus dari versi sebelumnya ke versi baru. Setelah beralih, Anda memantau aplikasi untuk setiap masalah. Jika ada yang tidak beres, Anda dapat bertukar kembali ke versi lama. Dengan asumsi tidak ada masalah, Anda dapat menghapus versi lama.

Dengan aplikasi monolitik atau N-tier yang lebih tradisional, penyebaran biru-hijau umumnya berarti menyediakan dua lingkungan yang identik. Anda akan menerapkan versi baru ke lingkungan staging, lalu mengarahkan lalu lintas klien ke lingkungan staging — misalnya, dengan menukar alamat VIP. Dalam arsitektur layanan mikro, pembaruan terjadi pada tingkat layanan mikro, sehingga Anda biasanya akan menyebarkan pembaruan ke lingkungan yang sama dan menggunakan mekanisme penemuan layanan untuk bertukar.

Contoh. Di Kubernetes, Anda tidak perlu menyediakan klaster terpisah untuk melakukan penyebaran biru-hijau. Sebagai gantinya, Anda dapat memanfaatkan penyeleksi. Buat sumber daya Deployment baru dengan spesifikasi pod baru dan sekumpulan label yang berbeda. Buat penyebaran ini, tanpa menghapus penyebaran sebelumnya atau memodifikasi layanan yang mengarah ke sana. Setelah pod baru berjalan, Anda dapat memperbarui pemilih layanan agar sesuai dengan penyebaran baru.

Salah satu kelemahan penerapan biru-hijau adalah selama pembaruan, Anda menjalankan pod dua kali lebih banyak untuk layanan (saat ini dan berikutnya). Jika pod membutuhkan banyak sumber daya CPU atau memori, Anda mungkin perlu menskalakan klaster sementara untuk menangani konsumsi sumber daya.

Rilis kenari

Dalam rilis canary, Anda meluncurkan versi terbaru ke sejumlah kecil klien. Kemudian Anda memantau perilaku layanan baru sebelum meluncurkannya ke semua klien. Hal ini memungkinkan Anda melakukan peluncuran yang lambat secara terkendali, mengamati data nyata, dan menemukan masalah sebelum semua pelanggan terpengaruh.

Rilis canary lebih kompleks untuk dikelola daripada pembaruan biru-hijau atau bergulir, karena Anda harus secara dinamis merutekan permintaan ke berbagai versi layanan.

Contoh. Di Kubernetes, Anda dapat mengonfigurasi Layanan untuk menjangkau dua set replika (satu untuk setiap versi) dan menyesuaikan jumlah replika secara manual. Namun, pendekatan ini agak kasar, karena cara Kubernetes memuat penyeimbangan di seluruh pod. Misalnya, jika Anda memiliki total 10 replika, Anda hanya dapat mengalihkan lalu lintas dengan kenaikan 10%. Jika Anda menggunakan mesh layanan, Anda dapat menggunakan aturan perutean mesh layanan untuk menerapkan strategi rilis canary yang lebih canggih.

Langkah berikutnya