Panduan ini memandu Anda dalam mengimplementasikan rilis canary untuk layanan inferensi dalam mode Raw Deployment menggunakan NGINX Ingress Controller sebagai gerbang. Anda akan menyebarkan dua versi layanan inferensi secara berdampingan, mengalihkan lalu lintas secara bertahap dari v1 ke v2, dan melakukan peralihan penuh setelah v2 divalidasi.
Prasyarat
Sebelum memulai, pastikan Anda telah:
Cara kerja
Panduan ini menggunakan dua layanan inferensi yang dideploy dari model yang sama (canary): satu menjalankan v1 dan satu menjalankan v2. NGINX Ingress Controller mengarahkan lalu lintas di antara keduanya menggunakan anotasi canary. Dua strategi pemisahan lalu lintas dibahas:
-
Routing berbasis Header: Permintaan dengan header permintaan tertentu (
foo: bar) dialihkan ke v2. Semua permintaan lainnya dialihkan ke v1. -
Routing berbasis Bobot: 20% permintaan dialihkan ke v2, sedangkan 80% sisanya dialihkan ke v1.
Setelah v2 divalidasi, perbarui Service backend agar mengarah sepenuhnya ke v2, lalu bersihkan sumber daya v1.
Untuk informasi latar belakang tentang rilis canary dan blue-green dengan NGINX Ingress, lihat Gunakan controller NGINX Ingress untuk mengimplementasikan rilis canary dan rilis blue-green.
Langkah 1: Deploy dan verifikasi layanan inferensi
Deploy kedua versi layanan inferensi dan buat Service Kubernetes untuk masing-masing.
Deploy v1
-
Deploy layanan inferensi v1.
arena serve kserve \ --name=model-v1 \ --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/ai-sample/kserve-canary:1.0.0 \ --cpu=1 \ --memory=2Gi \ "python app.py --model_name=canary" -
Buat file bernama
model-svc.yamldengan konten berikut.apiVersion: v1 kind: Service metadata: name: model-svc spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: serving.kserve.io/inferenceservice: model-v1 type: ClusterIP -
Buat Service tersebut.
kubectl apply -f model-svc.yaml -
Verifikasi bahwa model-v1 berjalan dengan benar.
curl -H "Host: $(kubectl get inferenceservice model-v1 -o jsonpath='{.status.url}' | cut -d "/" -f 3)" \ -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \ -d '{"data": "test"}'
Deploy v2
-
Deploy layanan inferensi v2.
arena serve kserve \ --name=model-v2 \ --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/ai-sample/kserve-canary:1.0.0 \ --cpu=1 \ --memory=2Gi \ "python app-v2.py --model_name=canary" -
Buat file bernama
model-v2-svc.yamldengan konten berikut.apiVersion: v1 kind: Service metadata: name: model-v2-svc spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: serving.kserve.io/inferenceservice: model-v2 type: ClusterIP -
Buat Layanan.
kubectl apply -f model-v2-svc.yaml -
Verifikasi bahwa model-v2 berjalan dengan benar.
curl -H "Host: $(kubectl get inferenceservice model-v2 -o jsonpath='{.status.url}' | cut -d "/" -f 3)" \ -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \ -d '{"data": "test"}'
Langkah 2: Buat Ingress
Buat Ingress dasar yang mengarahkan seluruh lalu lintas ke Service v1 secara default.
-
Buat file bernama
model-ingress.yamldengan konten berikut.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: model-ingress spec: rules: - host: model.example.com # Ganti dengan hostname Anda. http: paths: - path: / backend: service: name: model-svc # Service untuk v1. port: number: 80 pathType: ImplementationSpecific -
Buat Ingress tersebut.
kubectl apply -f model-ingress.yaml
Langkah 3: Buat dan verifikasi kebijakan rilis canary
Pilih salah satu strategi berikut tergantung pada cara Anda ingin mengontrol lalu lintas yang mencapai v2.
Skenario 1: Pemisahan trafik berbasis header
Arahkan permintaan dengan header permintaan tertentu ke v2. Semua permintaan lainnya dialihkan ke v1 secara default. Gunakan strategi ini untuk pengujian terarah dengan klien atau tim tertentu.
-
Buat file bernama
gray-release-canary.yamldengan konten berikut.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "20" # Mengarahkan 20% trafik ke v2. Total bobot default adalah 100. spec: rules: - host: model.example.com http: paths: - path: / backend: service: name: model-v2-svc # Layanan untuk v2. port: number: 80 pathType: ImplementationSpecific -
Deploy kebijakan rilis canary.
kubectl apply -f gray-release-canary.yaml -
Verifikasi bahwa permintaan tanpa header canary dialihkan ke v1.
# Ganti hostname dengan yang ditentukan dalam Ingress Anda. curl -H "Host: model.example.com" -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \ -d '{"data": "test"}'Output yang diharapkan:
{"id":"4d8c110d-c291-4670-ad0a-1a30bf8e314c","model_name":"canary","model_version":null,"outputs":[{"name":"output-0","shape":[1,1],"datatype":"STR","data":["model-v1"]}]}Tanggapan dari model-v1 mengonfirmasi bahwa lalu lintas default tetap mencapai v1.
-
Verifikasi bahwa permintaan dengan
foo: bardialihkan ke v2.curl -H "Host: model.example.com" -H "Content-Type: application/json" \ -H "foo: bar" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \ -d '{"data": "test"}'Output yang diharapkan:
{"id":"4d3efc12-c8bd-40f8-898f-7983377db7bd","model_name":"canary","model_version":null,"outputs":[{"name":"output-0","shape":[1,1],"datatype":"STR","data":["model-v2"]}]}Tanggapan dari model-v2 mengonfirmasi bahwa kebijakan rilis canary berfungsi.
Skenario 2: Pemisahan trafik berbasis bobot
Arahkan persentase tetap lalu lintas ke v2 tanpa mempertimbangkan header permintaan. Gunakan strategi ini untuk validasi canary menyeluruh di seluruh pengguna.
-
Buat file bernama
gray-release-canary.yamldengan konten berikut.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "20" # Arahkan 20% trafik ke v2. Bobot total default adalah 100. spec: rules: - host: model.example.com http: paths: - path: / backend: service: name: model-v2-svc # Service untuk v2. port: number: 80 pathType: ImplementationSpecific -
Deploy kebijakan rilis canary.
kubectl apply -f gray-release-canary.yaml -
Verifikasi distribusi lalu lintas dengan mengirimkan beberapa permintaan.
curl -H "Host: model.example.com" -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \ -d '{"data": "test"}'Jalankan perintah ini beberapa kali. Sekitar 20% tanggapan akan menampilkan
"data":["model-v2"]dan sisanya 80% akan menampilkan"data":["model-v1"], yang mengonfirmasi bahwa kebijakan rilis canary berfungsi.
Langkah 4: Alihkan trafik ke versi baru
Setelah v2 berjalan sesuai harapan, arahkan seluruh lalu lintas ke v2 dan hapus v1.
-
Perbarui
model-svc.yamlagar Servicemodel-svcmengarah ke v2.apiVersion: v1 kind: Service metadata: name: model-svc spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: serving.kserve.io/inferenceservice: model-v2 # Diubah dari model-v1 menjadi model-v2. type: ClusterIP -
Terapkan layanan yang telah diperbarui.
kubectl apply -f model-svc.yaml -
Verifikasi bahwa seluruh lalu lintas kini mencapai v2.
curl -H "Host: model.example.com" -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \ -d '{"data": "test"}'Output yang diharapkan:
{"id":"a13f2089-73ce-41e3-989e-e58457d14fed","model_name":"canary","model_version":null,"outputs":[{"name":"output-0","shape":[1,1],"datatype":"STR","data":["model-v2"]}]}Jalankan perintah ini beberapa kali untuk memastikan semua tanggapan berasal dari model-v2.
-
Hapus Ingress canary dan sumber daya v1.
kubectl delete ingress gray-release-canary arena serve delete model-v1 kubectl delete svc model-v2-svc