Panduan ini menyediakan praktik terbaik untuk mendesain, mengimplementasikan, menguji, dan men-deploy layanan penayangan Knative. Untuk tips lainnya, lihat Memigrasikan Layanan yang Sudah Ada.
Menulis layanan yang efektif
Bagian ini menjelaskan praktik terbaik umum untuk merancang dan mengimplementasikan layanan penayangan Knative.
Menghindari aktivitas latar belakang
Saat aplikasi yang berjalan di penayangan Knative selesai menangani permintaan, akses instance penampung ke CPU akan dinonaktifkan atau sangat terbatas. Oleh karena itu, Anda tidak boleh memulai thread atau rutinitas latar belakang yang berjalan di luar cakupan pengendali permintaan.
Menjalankan thread latar belakang dapat mengakibatkan perilaku yang tidak terduga karena permintaan berikutnya ke instance penampung yang sama akan melanjutkan aktivitas latar belakang yang ditangguhkan.
Aktivitas latar belakang meliputi segala sesuatu yang terjadi setelah respons HTTP dikirimkan. Tinjau kode Anda untuk memastikan semua operasi asinkron selesai sebelum Anda mengirimkan respons.
Jika Anda mencurigai mungkin ada aktivitas latar belakang dalam layanan yang tidak terlihat dengan jelas, Anda dapat memeriksa log: cari apa pun yang dicatat setelah entri untuk permintaan HTTP.
Menghapus file sementara
Di lingkungan Cloud Run, penyimpanan disk berfungsi sebagai sistem file dalam memori. File yang ditulis ke disk menggunakan memori yang seharusnya disediakan untuk layanan Anda, dan bisa tetap dipertahankan di antara pemanggilan. Jika file ini tidak dihapus, dapat terjadi error kehabisan memori yang disusul dengan cold start.
Mengoptimalkan performa
Bagian ini menjelaskan praktik terbaik untuk mengoptimalkan performa.
Memulai layanan dengan cepat
Karena instance penampung diskalakan sesuai kebutuhan, metode umum adalah menginisialisasi lingkungan eksekusi sepenuhnya. Ini jenis inisialisasi yang disebut "cold start". Jika permintaan klien memicu cold start, startup instance penampung akan menghasilkan latensi tambahan.
Rutinitas startup terdiri dari:
- Memulai layanan
- Memulai penampung
- Menjalankan perintah entrypoint untuk memulai server Anda.
- Memeriksa port layanan yang terbuka.
Mengoptimalkan kecepatan startup layanan akan meminimalkan latensi yang menunda instance penampung agar tidak melayani permintaan.
Menggunakan dependensi dengan bijak
Jika Anda menggunakan bahasa dinamis dengan library dependen, seperti mengimpor modul di Node.js, waktu pemuatan untuk modul tersebut akan menambahkan latensi selama cold start. Kurangi latensi startup dengan cara berikut:
- Minimalkan jumlah dan ukuran dependensi untuk mem-build layanan yang efisien.
- Memuat kode yang jarang digunakan secara lambat, jika bahasa Anda mendukung fitur ini.
- Gunakan pengoptimalan pemuatan kode seperti pengoptimalan autoloader composer pada PHP.
Menggunakan variabel global
Dalam penayangan Knative, Anda tidak dapat berasumsi bahwa status layanan dipertahankan di antara permintaan. Namun, penayangan Knative menggunakan kembali setiap instance penampung untuk menyalurkan traffic yang sedang berlangsung. Oleh karena itu, Anda dapat mendeklarasikan variabel dalam cakupan global agar nilainya dapat digunakan kembali dalam pemanggilan berikutnya. Tidak dapat diprediksi sebelumnya apakah setiap permintaan menerima manfaat dari penggunaan ulang ini.
Anda juga dapat menyimpan cache objek di memori jika objek tersebut mahal untuk dibuat ulang pada setiap permintaan layanan. Memindahkan tindakan ini dari logika permintaan ke cakupan global akan menghasilkan performa yang lebih baik.
Node.js
Python
Go
Java
Melakukan inisialisasi lambat untuk variabel global
Inisialisasi variabel global selalu terjadi selama startup, yang dapat meningkatkan waktu cold start. Gunakan inisialisasi lambat untuk objek yang jarang digunakan guna menunda biaya dan mengurangi waktu cold start.
Node.js
Python
Go
Java
Mengoptimalkan konkurensi
Instance penayangan Knative dapat menayangkan beberapa permintaan secara bersamaan, "secara serentak", hingga konkurensi maksimum yang dapat dikonfigurasi.
Hal ini berbeda dengan fungsi Cloud Run, yang menggunakan concurrency = 1
.
Anda harus mempertahankan setelan konkurensi maksimum default kecuali jika kode Anda memiliki persyaratan konkurensi tertentu.
Menyesuaikan konkurensi untuk layanan Anda
Jumlah permintaan serentak yang dapat dilayani oleh setiap instance container dapat dibatasi oleh technology stack dan penggunaan resource bersama seperti variabel dan koneksi database.
Untuk mengoptimalkan layanan Anda agar mencapai konkurensi maksimum yang stabil:
- Optimalkan performa layanan Anda.
- Tetapkan tingkat dukungan konkurensi yang diharapkan dalam konfigurasi konkurensi tingkat kode apa pun. Tidak semua technology stack memerlukan setelan tersebut.
- Deploy layanan Anda.
- Tetapkan konkurensi penayangan Knative untuk layanan Anda agar sesuai atau kurang dari konfigurasi tingkat kode apa pun. Jika tidak ada konfigurasi tingkat kode, gunakan konkurensi yang diharapkan.
- Gunakan alat pengujian beban yang mendukung konkurensi yang dapat dikonfigurasi. Anda perlu memastikan bahwa layanan Anda tetap stabil di bawah beban dan konkurensi yang diharapkan.
- Jika layanan tidak berfungsi dengan baik, lanjutkan ke langkah 1 untuk meningkatkan layanan atau langkah 2 untuk mengurangi konkurensi. Jika layanan berfungsi dengan baik, kembali ke langkah 2 dan tingkatkan konkurensi.
Lanjutkan iterasi sampai Anda menemukan konkurensi maksimum yang stabil.
Mencocokkan memori dengan konkurensi
Setiap permintaan yang ditangani layanan Anda memerlukan sejumlah memori tambahan. Jadi, saat menyesuaikan konkurensi ke atas atau ke bawah, pastikan Anda juga menyesuaikan batas memori.
Menghindari status global yang dapat berubah
Jika ingin memanfaatkan status global yang dapat berubah dalam konteks konkurensi, pastikan mengambil langkah tambahan dalam kode Anda untuk memastikan hal ini dilakukan dengan aman. Untuk menghindari konflik, sebaiknya batasi variabel global dengan inisialisasi satu kali dan gunakan kembali, seperti yang dijelaskan di bagian Performa di atas.
Jika Anda menggunakan variabel global yang dapat diubah dalam layanan yang menangani beberapa permintaan secara bersamaan, pastikan untuk menggunakan kunci atau mutex untuk menghindari kondisi race.
Keamanan container
Sebagian besar praktik keamanan software yang umum digunakan juga berlaku untuk aplikasi yang dijalankan dalam container. Ada beberapa praktik yang entah khusus untuk kontainer atau sesuai dengan filosofi dan arsitektur dari kontainer.
Untuk meningkatkan keamanan container:
Gunakan image dasar yang dikelola secara aktif dan aman, seperti image dasar Google atau image resmi Docker Hub.
Terapkan update keamanan pada layanan Anda dengan mem-build ulang image container secara rutin dan men-deploy ulang layanan Anda.
Sertakan hanya hal yang diperlukan ke dalam container untuk menjalankan layanan Anda. Kode, paket, dan alat tambahan dapat berpotensi terhadap kerentanan keamanan. Lihat di atas untuk dampak performa yang terkait.
Implementasikan proses build deterministik yang menyertakan versi software dan library tertentu. Langkah ini mencegah kode yang tidak terverifikasi untuk dimasukkan ke dalam kontainer Anda.
Atur container Anda untuk dijalankan sebagai pengguna selain
root
dengan pernyataanUSER
Dockerfile. Beberapa image kontainer mungkin sudah memiliki pengguna tertentu yang telah dikonfigurasi sebelumnya.
Mengotomatiskan pemindaian keamanan
Aktifkan pemindaian kerentanan untuk pemindaian keamanan image container yang disimpan di Artifact Registry.
Anda juga dapat menggunakan Otorisasi Biner untuk memastikan hanya image container yang aman yang di-deploy.
Mem-build image container minimal
Image container besar cenderung meningkatkan kerentanan keamanan karena mengandung lebih dari yang diperlukan oleh kode.
Pada penayangan Knative, ukuran image container Anda tidak memengaruhi cold start atau waktu pemrosesan permintaan dan tidak mengurangi memori yang tersedia untuk container Anda.
Untuk mem-build container minimal, sebaiknya gunakan image dasar yang efisien seperti:
Ubuntu berukuran lebih besar, tetapi merupakan image dasar yang biasa digunakan dengan lingkungan server siap pakai dan lebih lengkap.
Jika layanan Anda memiliki proses build dengan banyak alat, pertimbangkan untuk menggunakan build multi-stage agar container tetap ringan saat dijalankan.
Referensi ini memberikan informasi lebih lanjut tentang cara membuat image container yang efisien:
- Praktik terbaik Kubernetes: Cara dan alasan build image container kecil
- 7 praktik terbaik untuk membuat container