Canary Deployment Menggunakan NGINX Ingress Controller

https://stelligent.com/wp-content/uploads/2020/07/not-a-canary-scaled.jpg
Burung Kenari via https://stelligent.com


Ada banyak strategi deployment yang bisa diterapkan pada sistem yang Anda kelola, seperti blue/green, canary, A/B testing, dsb. Setiap strategi memiliki kekurangan dan kelebihan masing-masing. Namun, apabila Anda memiliki ketidakyakinan yang berlebih dengan apa yang Anda ingin rilis dan mendapatkan kinerja sistem yang lebih stabil, maka mengimplementasikan strategi canary deployment adalah opsi yang bisa digunakan. Cara kerja canary deployment sendiri yaitu dengan memindahan trafik sistem pada lingkungan production secara bertahap dari versi A ke versi B. Biasanya trafik dibagi berdasarkan bobot dan hanya diakses oleh sebagian pengguna. Misalnya, 90 persen request masuk ke versi A, 10 persen ke versi B. Apabila error rate tidak melebihi ambang batas yang ditetapkan dan respon sesuai dengan yang diharapkan, maka versi B akan disebarkan 100 persen pada lingkungan production.

Terhitung mulai versi 0.21.0 Nginx Ingress controller memiliki fitur yang memungkinkan pengguna untuk mengimplementasikan strategi canary deployment. Bagi Anda yang sudah menggunakan Nginx sebagai Ingress controller pada cluster Kubernetes, maka fitur ini bisa Anda coba 🙂

Proses simulasi bisa Anda mulai dengan menjalankan versi stabil dari service yang dikelola pada lingkungan production.

➜  canary-deployment git:(main) ✗ curl https://canary-test.domain.abc/version -s 
{"version":"1.0.0"}

Konfigurasi Ingress yang digunakan:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
  labels:
    app: app
    version: 1.0.0
  name: demo-ingress
  namespace: demo-prod
spec:
  ingressClassName: nginx
  rules:
  - host: canary-test.domain.abc
    http:
      paths:
      - backend:
          service:
             name: demo-prod
             port: 
               number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - canary-test.domain.abc
    secretName: letsencrypt-canary

Untuk melakukan canary deployment siapkan namespace baru dengan menduplikasi manifest yang sama pada namespace versi stabil berjalan. Perbedaannya hanya pada anotasi Nginx Ingress.

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "kenari"
    nginx.ingress.kubernetes.io/canary-by-header-value: "test"
  labels:
    app: demo
  name: demo-ingress
  namespace: demo-canary
spec:
  ingressClassName: nginx
  rules:
  - host: canary-test.domain.abc
    http:
      paths:
      - backend:
          service:
             name: demo-canary
             port:
               number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - canary-test.domain.abc
    secretName: letsencrypt-canary
  • nginx.ingress.kubernetes.io/canary: “true”
    Anotasi yang memungkinkan Ingress bertindak sebagai Ingress alternatif untuk menerima request yang dirutekan tergantung pada config yang diterapkan.
  • nginx.ingress.kubernetes.io/canary-by-header: “kenari”
    Nama header yang digunakan untuk memberi tahu Ingress controller meneruskan trafik yang masuk sesuai dengan konfigurasi canary yang ditetapkan.
  • nginx.ingress.kubernetes.io/canary-by-header-value: “test”
    Nilai header yang digunakan untuk memberi tahu Ingress controller meneruskan trafik yang masuk sesuai dengan konfigurasi canary yang ditetapkan.

Penggunaan anotasi di atas memungkinkan kita menerapkan user-based canary. Artinya, request dari pengguna akan dilayani oleh kandidat service yang akan dirils apabila nama dan nilai header yang dikirim sesuai.

Weight-Based & User-Based Canary via https://golangexample.com/canary-deployments-with-nginx-ingress-controller/

Weight-Based & User-Based Canary via https://golangexample.com

Buat script iterasi sederhana untuk mengirim trafik pada service yang berjalan dan canary.

#!/bin/bash
for i in {1..50}
do
   curl https://canary-test.domain.abc/version -s ; echo '\n'
done

Apabila script di atas dijalankan maka yang akan melayani request trafik tersebut adalah service dengan versi stabil (1.0.0).

➜  canary-deployment git:(main) ✗ sh test.sh 
{"version":"1.0.0"}

{"version":"1.0.0"}

{"version":"1.0.0"}

{"version":"1.0.0"}

{"version":"1.0.0"}

Untuk mengarahkan trafik ke kandidat canary (1.0.1) yang di-set, lakukan penyesuaian berikut:

#!/bin/bash
for i in {1..50}
do
   curl -H "kanari: test" https://canary-test.domain.abc/version -s ; echo '\n'
done
➜  canary-deployment git:(main) ✗ sh test.sh 
{"version":"1.0.1 - canary"}

{"version":"1.0.1 - canary"}

{"version":"1.0.1 - canary"}

{"version":"1.0.1 - canary"}

{"version":"1.0.1 - canary"}

Sampai pada tahap ini Anda sudah sukses melakukan skenario canary deployment. Improvement tambahkan tentu masih perlu dilakukan, seperti melakukan penyebaran secara menyeluruh kandidat rilis yang akan dinaikkan pada pipeline deployment Anda. Canary Deployment hanya satu dari sekian banyak strategi deployment yang mungkin akan membantu Anda memberi keyakinan tambahan untuk merilis versi terbaru pada service yang sudah berjalan. Teknik ini mungkin tidak selalu menjawab kebutuhan organisasi Anda. Sebuah keputusan penting untuk memilih strategi deployment yang tepat dengan mempertimbangkan karakteristik sistem, pengguna, dan alokasi cost tentunya 🙂

Leave a comment