Alihkan lalu lintas secara bertahap ke versi layanan baru berdasarkan header, cookie, atau bobot sebelum beralih sepenuhnya.
Latar Belakang
Baik rilis bertahap (juga disebut rilis canary) maupun penyebaran biru-hijau menjalankan versi baru secara bersamaan dengan versi lama dan mengarahkan sebagian lalu lintas ke versi baru tersebut. Setelah stabil, seluruh lalu lintas dialihkan dan versi lama dihentikan.
ACK Nginx Ingress Controller mendukung dua metode pemisahan lalu lintas berbasis anotasi:
| Metode | Status | Catatan |
|---|---|---|
canary-* annotations |
Aktif | Metode resmi dari komunitas. Gunakan metode ini untuk semua konfigurasi baru. |
service-* annotations |
Tidak digunakan lagi | Tidak tersedia lagi di Nginx Ingress Controller v1.12 dan seterusnya. Jangan gunakan. |
Kasus Penggunaan
-
Pemisahan lalu lintas berdasarkan permintaan klien: Arahkan lalu lintas ke versi baru hanya ketika permintaan berisi header atau cookie tertentu—misalnya,
foo=bar. Permintaan lain tetap diarahkan ke versi lama. Setelah stabil, alihkan seluruh lalu lintas. -
Pemisahan lalu lintas berdasarkan bobot layanan: Arahkan persentase tetap lalu lintas—misalnya, 20%—ke versi baru. Tingkatkan persentase secara bertahap hingga seluruh lalu lintas dialihkan ke versi baru.
Dimensi pemisahan lalu lintas yang didukung:
-
Header permintaan — cocok untuk rilis bertahap dan Pengujian A/B
-
Cookie — cocok untuk rilis bertahap dan Pengujian A/B
-
Parameter kueri — cocok untuk rilis bertahap dan Pengujian A/B
-
Bobot layanan — cocok untuk penyebaran biru-hijau
Metode anotasi canary-*
Referensi anotasi
Semua konfigurasi canary memerlukan anotasi nginx.ingress.kubernetes.io/canary: "true". Anotasi lain menentukan logika routing.
| Anotasi | Deskripsi | Versi min. |
|---|---|---|
nginx.ingress.kubernetes.io/canary |
Mengaktifkan fitur canary. Harus diatur ke true agar anotasi canary lain berlaku. Nilai yang valid: true, false.
|
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-by-header |
Mengarahkan permintaan ke layanan canary berdasarkan header permintaan. Nilai khusus: always (selalu diarahkan ke canary), never (tidak pernah diarahkan ke canary). Jika tidak ada nilai yang ditentukan, traffic diteruskan selama header tersebut ada. |
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-by-header-value |
Mengarahkan permintaan ke layanan canary ketika header yang ditentukan oleh canary-by-header sesuai dengan nilai eksak. Harus digunakan bersama canary-by-header. |
>=v0.30.0 |
nginx.ingress.kubernetes.io/canary-by-header-pattern |
Mengarahkan permintaan ke layanan canary ketika header yang ditentukan oleh canary-by-header sesuai dengan ekspresi reguler. Harus digunakan bersama canary-by-header. |
>=v0.44.0 |
nginx.ingress.kubernetes.io/canary-by-cookie |
Mengarahkan permintaan ke layanan canary berdasarkan cookie, misalnya nginx.ingress.kubernetes.io/canary-by-cookie: foo. Nilai cookie: always (foo=always diarahkan ke canary), never (foo=never tidak diarahkan). Traffic diteruskan hanya jika cookie tersebut ada dan nilainya always. |
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-weight |
Mengarahkan persentase permintaan ke layanan canary berdasarkan bobot. Rentang: 0 hingga canary-weight-total (default 100). |
>=v0.22.0 |
nginx.ingress.kubernetes.io/canary-weight-total |
Menetapkan penyebut total bobot. Default: 100. |
>=v1.1.2 |
Prioritas anotasi (menurun):
canary-by-header > canary-by-cookie > canary-weight
Setiap aturan Ingress hanya mendukung satu Ingress canary. Ingress canary tambahan akan diabaikan.
Langkah 1: Penerapan layanan
Terapkan layanan Nginx dan buka akses domain Lapisan 7 melalui Nginx Ingress Controller.
-
Buat Deployment dan Service. Simpan konten berikut ke dalam
nginx.yaml.Terapkan manifes:
kubectl apply -f nginx.yaml -
Buat Ingress. Simpan konten berikut ke dalam
ingress.yaml.Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # Versi lama layanan. - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release spec: rules: - host: www.example.com http: paths: # Versi lama layanan. - path: / backend: serviceName: old-nginx servicePort: 80Terapkan manifes:
kubectl apply -f ingress.yaml -
Verifikasi penerapan. Dapatkan alamat IP eksternal:
kubectl get ingressPeriksa akses routing:
curl -H "Host: www.example.com" http://<EXTERNAL_IP>Output yang diharapkan:
old
Langkah 2: Rilis versi layanan baru
Terapkan versi Nginx baru dan konfigurasikan aturan routing canary.
-
Buat Deployment dan Service baru. Simpan konten berikut ke dalam
nginx1.yaml.Terapkan manifes:
kubectl apply -f nginx1.yaml -
Buat Ingress canary untuk mengarahkan lalu lintas ke versi baru. Tiga strategi tersedia. Strategi A: Routing berdasarkan header permintaan Arahkan permintaan ke versi baru hanya ketika header
foobernilaibar. Permintaan lain diarahkan ke versi lama. Simpan konten berikut ke dalamingress1.yaml. Untuk kluster v1.19 dan yang lebih baru:-
Dengan header `foo: bar`: 100% lalu lintas diarahkan ke
new-nginx(dikendalikan olehcanary-by-headerdancanary-by-header-value). -
Tanpa header `foo: bar`: 50% lalu lintas diarahkan ke
new-nginx(dikendalikan olehcanary-weight).
Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: # Aktifkan routing canary. nginx.ingress.kubernetes.io/canary: "true" # Arahkan ke new-nginx hanya jika header foo bernilai bar. nginx.ingress.kubernetes.io/canary-by-header: "foo" nginx.ingress.kubernetes.io/canary-by-header-value: "bar" spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # Versi baru layanan. - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "foo" nginx.ingress.kubernetes.io/canary-by-header-value: "bar" nginx.ingress.kubernetes.io/canary-weight: "50" spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes dan verifikasi:
kubectl get ingress curl -H "Host: www.example.com" http://<EXTERNAL_IP>Uji tanpa header (diarahkan ke versi lama):
curl -H "Host: www.example.com" http://<EXTERNAL_IP>Output yang diharapkan:
oldUji dengan headerfoo: bar(diarahkan ke versi baru):curl -H "Host: www.example.com" -H "foo: bar" http://<EXTERNAL_IP>Output yang diharapkan:
newStrategi B: Routing berdasarkan header dan membagi sisa lalu lintas berdasarkan bobot
Arahkan semua permintaan dengan
foo=barke versi baru, dan 50% permintaan lain ke versi baru. Perbaruiingress1.yamldengan konten berikut.Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" # Arahkan 50% trafik ke new-nginx. Bobot total default adalah 100. nginx.ingress.kubernetes.io/canary-weight: "50" spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "foo" nginx.ingress.kubernetes.io/canary-by-header-value: "bar" nginx.ingress.kubernetes.io/canary-weight: "50" spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes:
kubectl apply -f ingress1.yamlStrategi C: Routing hanya berdasarkan bobot
Arahkan 50% lalu lintas ke versi baru, terlepas dari header atau cookie. Perbarui
ingress1.yamldengan konten berikut.Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" # Arahkan 50% seluruh traffic ke new-nginx. Bobot total default adalah 100. nginx.ingress.kubernetes.io/canary-weight: "50" spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release-canary annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "50" spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes:
kubectl apply -f ingress1.yamlVerifikasi: jalankan perintah ini beberapa kali. Sekitar 50% tanggapan seharusnya mengembalikan
new.curl -H "Host: www.example.com" http://<EXTERNAL_IP> -
Langkah 3: Selesaikan alih traffic
Setelah versi baru stabil, hentikan versi lama.
-
Perbarui
nginx.yamluntuk mengarahkan Service lama ke Deployment baru.Terapkan pembaruan:
kubectl apply -f nginx.yaml -
Verifikasi seluruh lalu lintas diarahkan ke versi baru:
kubectl get ingress curl -H "Host: www.example.com" http://<EXTERNAL_IP>Output yang diharapkan:
new -
Hapus Ingress canary:
kubectl delete ingress gray-release-canary -
Hapus Deployment lama dan Service baru:
kubectl delete deploy old-nginx kubectl delete svc new-nginx
Metode anotasi service-*
Anotasi service-* tidak tersedia lagi di Nginx Ingress Controller v1.12 dan seterusnya. Jangan gunakan.
Referensi anotasi
| Anotasi | Deskripsi |
|---|---|
nginx.ingress.kubernetes.io/service-match |
Menentukan aturan routing yang memetakan atribut permintaan ke layanan. Sintaks: nginx.ingress.kubernetes.io/service-match: | <service-name>: <match-rule>. Jenis pencocokan yang didukung: header, cookie, query. Format pencocokan: regex /regular expression/, eksak "exact value". Contoh: new-nginx: header("foo", /^bar$/); new-nginx: header("foo", "bar"); new-nginx: cookie("foo", /^sticky-.+$/); new-nginx: query("foo", "bar").
|
nginx.ingress.kubernetes.io/service-weight |
Menetapkan bobot traffic antara versi layanan lama dan baru. Sintaks: nginx.ingress.kubernetes.io/service-weight: | <new-svc-name>:<new-svc-weight>, <old-svc-name>:<old-svc-weight>. Contoh: new-nginx: 20, old-nginx: 60. |
Langkah 1: Penerapan layanan
Terapkan layanan Nginx dan buka akses domain Lapisan 7 melalui Nginx Ingress Controller.
-
Buat Deployment dan Service. Simpan konten berikut ke dalam
nginx.yaml.Terapkan manifes:
kubectl apply -f nginx.yaml -
Buat Ingress. Simpan konten berikut ke dalam
ingress.yaml.Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # Versi lama layanan. - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes:
kubectl apply -f ingress.yaml kubectl get ingress -
Verifikasi penerapan. Dapatkan alamat IP eksternal:
kubectl get ingressPeriksa akses routing:
curl -H "Host: www.example.com" http://<EXTERNAL_IP>Output yang diharapkan:
old
Langkah 2: Rilis versi layanan baru
Terapkan versi Nginx baru dan konfigurasikan aturan routing.
-
Buat Deployment dan Service baru. Simpan konten berikut ke dalam
nginx1.yaml.Terapkan manifes:
kubectl apply -f nginx1.yaml -
Ubah Ingress
gray-release. Tiga strategi tersedia. Strategi A: Routing berdasarkan header permintaan Arahkan permintaan ke versi baru hanya ketika headerfoosesuai denganbar. Perbaruiingress.yamldengan konten berikut. Untuk kluster v1.19 dan yang lebih baru:Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release annotations: # Arahkan ke new-nginx jika header foo sesuai ^bar$. nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # Versi lama layanan. - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecific # Versi baru layanan. - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: old-nginx servicePort: 80 - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes dan verifikasi:
kubectl apply -f ingress.yaml kubectl get ingressUji tanpa header (diarahkan ke versi lama):
curl -H "Host: www.example.com" http://<EXTERNAL_IP>Output yang diharapkan:
oldUji dengan headerfoo: bar(diarahkan ke versi baru):curl -H "Host: www.example.com" -H "foo: bar" http://<EXTERNAL_IP>Output yang diharapkan:
newStrategi B: Routing berdasarkan header dengan pembagian berbasis bobot
Arahkan permintaan yang sesuai
foo=barke kedua versi, dengan 50% masing-masing. Perbaruiingress.yamldengan konten berikut.Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) # Dari permintaan yang sesuai, arahkan 50% ke new-nginx dan 50% ke old-nginx. nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecific - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-match: | new-nginx: header("foo", /^bar$/) nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: old-nginx servicePort: 80 - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes:
kubectl apply -f ingress.yamlJalankan perintah uji beberapa kali. Sekitar 50% permintaan
foo: barseharusnya mengembalikannew.Strategi C: Routing hanya berdasarkan bobot
Arahkan 50% lalu lintas ke versi baru. Perbarui
ingress.yamldengan konten berikut.Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release annotations: # Arahkan 50% seluruh traffic ke new-nginx. nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: ingressClassName: nginx rules: - host: www.example.com http: paths: - path: / backend: service: name: old-nginx port: number: 80 pathType: ImplementationSpecific - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release annotations: nginx.ingress.kubernetes.io/service-weight: | new-nginx: 50, old-nginx: 50 spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: old-nginx servicePort: 80 - path: / backend: serviceName: new-nginx servicePort: 80Terapkan manifes:
kubectl apply -f ingress.yamlVerifikasi: jalankan perintah ini beberapa kali. Sekitar 50% tanggapan seharusnya mengembalikan
new.curl -H "Host: www.example.com" http://<EXTERNAL_IP>
Langkah 3: Selesaikan alih traffic
Setelah versi baru stabil, hentikan versi lama.
-
Untuk kluster v1.19 dan yang lebih baru
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gray-release spec: ingressClassName: nginx rules: - host: www.example.com http: paths: # Versi baru layanan. - path: / backend: service: name: new-nginx port: number: 80 pathType: ImplementationSpecificUntuk kluster sebelum v1.19
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: gray-release spec: rules: - host: www.example.com http: paths: - path: / backend: serviceName: new-nginx servicePort: 80Terapkan pembaruan:
kubectl apply -f ingress.yaml -
Verifikasi seluruh lalu lintas diarahkan ke versi baru:
kubectl get ingress curl -H "Host: www.example.com" http://<EXTERNAL_IP>Output yang diharapkan:
new -
Hapus Deployment dan Service lama:
kubectl delete deploy <Deployment_name> kubectl delete svc <Service_name>