Deployment Strategy Overview #

Setiap kali kita meluncurkan versi baru dari aplikasi ke lingkungan produksi, kita sedang memperkenalkan risiko ke dalam sistem kita. Kode baru mungkin saja mengandung bug tersembunyi, performa kueri database dapat menurun drastis di bawah beban lalu lintas nyata, atau terjadi perubahan perilaku API yang tidak sengaja merusak integrasi dengan layanan lain. Strategi deployment adalah metodologi terstruktur yang kita gunakan untuk mengelola dan memitigasi risiko-risiko tersebut. Strategi yang kita pilih akan menentukan seberapa besar dampak kegagalan (blast radius) jika rilis baru bermasalah, seberapa cepat kita bisa mengembalikan sistem ke kondisi stabil (rollback), dan berapa besar biaya infrastruktur yang harus kita tanggung selama proses rilis berlangsung.

Kubernetes didesain secara modular untuk mendukung berbagai strategi rilis, mulai dari yang paling sederhana hingga sistem pengiriman progresif yang kompleks (progressive delivery). Namun, tidak ada satu strategi pun yang bersifat universal dan terbaik untuk semua jenis aplikasi. Memilih strategi deployment yang tepat mengharuskan kita memahami karakteristik beban kerja aplikasi (workload), toleransi downtime bisnis, kesiapan database untuk mendukung multi-version concurrency, serta kapasitas resource cluster yang tersedia.


Spektrum Trade-Off: Risiko vs Kompleksitas #

Dalam merancang strategi deployment, kita selalu dihadapkan pada spektrum trade-off yang saling bertentangan. Kita tidak bisa mendapatkan rollback instan dan tanpa downtime tanpa membayar harga berupa peningkatan kompleksitas infrastruktur dan pemborosan resource.

Secara umum, hubungan antara berbagai strategi deployment utama dapat digambarkan sebagai berikut:

flowchart TD
    subgraph Spec["SPEKTRUM STRATEGI DEPLOYMENT"]
        direction LR
        Canary["Canary<br>- Rilis bertahap ke sebagian kecil user<br>- Downtime & Risiko: Makin Rendah<br>- Kompleksitas & Resource: Makin Tinggi"]
        BlueGreen["Blue/Green<br>- Dua env paralel, cutover instan<br>- Downtime & Risiko: Rendah<br>- Kompleksitas & Resource: Tinggi"]
        RollingUpdate["Rolling Update<br>- Pergantian Pod satu per satu, default k8s<br>- Downtime & Risiko: Sedang<br>- Kompleksitas & Resource: Rendah"]
        Recreate["Recreate<br>- Matikan semua v1, jalankan semua v2<br>- Downtime & Risiko: Makin Tinggi<br>- Kompleksitas & Resource: Makin Rendah"]

        Canary --> BlueGreen --> RollingUpdate --> Recreate
    end
  1. Risiko Paparan (Exposure Risk): Menunjukkan berapa banyak pengguna yang akan langsung terkena dampak jika kode baru memiliki bug kritis saat pertama kali dirilis.
  2. Kebutuhan Resource (Resource Footprint): Berapa banyak kapasitas CPU dan Memory ekstra yang dibutuhkan di cluster selama proses transisi rilis berlangsung.
  3. Kompleksitas Operasional: Tingkat kesulitan dalam mengonfigurasi pipa deployment (CI/CD), melakukan monitoring metrik, dan mengotomatiskan proses rollback.
  4. Kecepatan Rollback: Waktu yang dibutuhkan untuk mengembalikan sistem sepenuhnya ke versi stabil (rollback window) jika terdeteksi anomali.

Membedah Empat Strategi Deployment Utama #

Kubernetes menyediakan mekanisme internal untuk mengelola strategi rilis melalui properti .spec.strategy pada objek Deployment. Mari kita bedah karakteristik arsitektural dari masing-masing pendekatan:

1. Recreate Strategy #

Strategi Recreate adalah pendekatan yang paling primitif sekaligus paling mudah dipahami. Kubernetes akan menghentikan (terminasi) seluruh replika Pod versi lama (v1) secara bersamaan hingga jumlahnya nol, menunggu hingga seluruh volume dilepaskan, dan baru kemudian membuat serta menjalankan seluruh replika Pod versi baru (v2).

[ WAKTU ] ───►
T1: Pod v1 (Aktif)   [ Pod 1 (v1) ] [ Pod 2 (v1) ] [ Pod 3 (v1) ]
T2: Terminasi v1     [ Off (v1) ]   [ Off (v1) ]   [ Off (v1) ]     ◄─── WINDOW DOWNTIME
T3: Startup v2       [ Init (v2) ]  [ Init (v2) ]  [ Init (v2) ]    ◄─── WINDOW DOWNTIME
T4: Pod v2 (Aktif)   [ Pod 1 (v2) ] [ Pod 2 (v2) ] [ Pod 3 (v2) ]
  • Downtime: Ya. Ada celah waktu (downtime window) yang jelas antara saat Pod v1 mati hingga Pod v2 siap menerima lalu lintas data.
  • Resource Ekstra: 0%. Tidak dibutuhkan kapasitas node tambahan karena Pod baru menempati slot resource yang ditinggalkan Pod lama.
  • Rollback: Lambat. Kita harus mengulangi proses terminasi v2 dan menunggu startup v1 dari awal.
  • Kasus Penggunaan Terbaik:
    • Aplikasi warisan (legacy monolith) yang tidak dirancang untuk berjalan lebih dari satu instance secara bersamaan (tidak mendukung concurrent database locks).
    • Perubahan skema database yang melanggar kompatibilitas mundur (non-backward compatible database migration) di mana versi v1 akan langsung crash jika membaca struktur tabel baru.
    • Lingkungan development/sandbox di mana downtime beberapa menit tidak menjadi masalah bisnis.

2. Rolling Update Strategy #

Rolling Update adalah strategi bawaan (default) di Kubernetes. Kubernetes secara bertahap mengganti Pod lama dengan Pod baru satu per satu atau dalam kelompok kecil. Proses ini diatur oleh dua parameter utama: maxSurge (berapa banyak Pod tambahan yang boleh dibuat di atas jumlah replika yang diinginkan) dan maxUnavailable (berapa banyak Pod yang boleh tidak tersedia selama transisi).

T1: Mulai            [ Pod 1 (v1) ] [ Pod 2 (v1) ] [ Pod 3 (v1) ]
T2: Surge Pod v2     [ Pod 1 (v1) ] [ Pod 2 (v1) ] [ Pod 3 (v1) ] + [ Pod 4 (v2) ]
T3: Terminasi Pod 1  [ Term (v1) ]  [ Pod 2 (v1) ] [ Pod 3 (v1) ] + [ Pod 4 (v2) ]
T4: Penggantian      [ Pod 5 (v2) ] [ Pod 2 (v1) ] [ Pod 3 (v1) ] + [ Pod 4 (v2) ]
...
T_Akhir: Selesai     [ Pod 5 (v2) ] [ Pod 6 (v2) ] [ Pod 7 (v2) ]
  • Downtime: Tidak. Ketersediaan layanan tetap terjaga selama proses update karena selalu ada Pod yang siap melayani trafik.
  • Resource Ekstra: Minimal (tergantung konfigurasi maxSurge, biasanya berkisar antara 25% hingga 50%).
  • Rollback: Sedang (membutuhkan waktu beberapa menit bagi Kubernetes untuk melakukan rolling update terbalik kembali ke versi sebelumnya).
  • Karakteristik Kunci: Selama masa transisi, versi v1 dan v2 akan berjalan secara bersamaan (concurrent runtime) di dalam cluster. Aplikasi kita harus dirancang untuk toleran terhadap kondisi ini (backward-compatible).

3. Blue/Green Deployment (Red/Black) #

Pada strategi Blue/Green, kita menjalankan dua lingkungan terpisah yang identik secara fisik di dalam cluster. Lingkungan “Blue” adalah versi produksi aktif saat ini (v1) yang melayani seluruh trafik pengguna. Lingkungan “Green” adalah versi baru (v2) yang kita deploy secara penuh di samping lingkungan Blue.

Kita dapat melakukan pengujian kelayakan (smoke testing) secara menyeluruh pada lingkungan Green tanpa mengganggu trafik pengguna nyata. Setelah lingkungan Green dipastikan sehat dan lulus uji, kita memindahkan (cutover) seluruh trafik secara instan ke lingkungan Green dengan mengubah rujukan pada Service selector atau aturan routing di Ingress/Gateway API.

flowchart TD
    subgraph Sebelum["Sebelum Cutover"]
        Traffic1["Traffic"] --> Ingress1["Service / Ingress"]
        Ingress1 --> Blue1["Lingkungan BLUE (Pod v1, v1)"]
        Ingress1 -.-> Green1["Lingkungan GREEN (Pod v2, v2)"]
    end
    subgraph Setelah["Setelah Cutover"]
        Traffic2["Traffic"] --> Ingress2["Service / Ingress"]
        Ingress2 -.-> Blue2["Lingkungan BLUE (Standby v1)"]
        Ingress2 --> Green2["Lingkungan GREEN (Pod v2, v2)"]
    end
  • Downtime: Tidak. Perpindahan trafik terjadi secara instan (sub-detik) di tingkat routing proxy/DNS.
  • Resource Ekstra: 100%. Kita membutuhkan kapasitas resource dua kali lipat selama proses rilis karena kedua lingkungan harus berjalan penuh secara paralel.
  • Rollback: Instan. Jika terjadi kegagalan di versi Green, kita cukup mengubah rujukan routing kembali ke lingkungan Blue yang masih dalam kondisi siaga (standby).

4. Canary Deployment #

Canary Deployment mengambil analogi dari burung kenari yang digunakan penambang batu bara untuk mendeteksi gas beracun. Pada strategi ini, kita mendeploy versi baru (v2) ke sebagian kecil Pod kontainer, lalu mengarahkan sebagian kecil trafik pengguna nyata (misalnya 5% atau 10%) ke Pod tersebut.

Kita memantau performa versi Canary ini dengan cermat menggunakan metrik observabilitas (seperti persentase error HTTP, latensi kueri, dan penggunaan CPU). Jika metrik menunjukkan hasil yang baik, kita meningkatkan porsi trafik secara bertahap (25% -> 50% -> 100%) hingga seluruh cluster berjalan dengan versi v2.

flowchart LR
    Traffic["Trafik Masuk (100%)"]
    Traffic -->|"90% Trafik"| Stable["Pod v1 (Stabil)"]
    Traffic -->|"10% Trafik"| Canary["Pod v2 (Canary - Dipantau Ketat)"]
  • Downtime: Tidak.
  • Resource Ekstra: Sangat Sedikit (hanya membutuhkan kapasitas untuk Pod Canary awal, bertambah seiring peningkatan skala rilis).
  • Rollback: Cepat dan Terkontrol. Jika Pod Canary menunjukkan error, kita hanya perlu menghapus Pod Canary atau menghentikan rute trafik ke arahnya. Hanya sebagian kecil pengguna yang sempat merasakan dampak bug.

Framework Keputusan (Decision Tree) #

Guna membantu tim memilih strategi deployment yang paling sesuai untuk masing-masing workload aplikasi, kita dapat merujuk pada diagram alur keputusan berikut:

flowchart TD
    Start["Identifikasi Karakteristik Aplikasi & Bisnis"] --> Q1{"Apakah aplikasi mendukung<br>dua versi berjalan bersamaan<br>'(Concurrent Database Lock/State)'?"}
    
    Q1 -- "Tidak (Monolit / Skema Kaku)" --> Q2{"Apakah bisnis menoleransi<br>downtime singkat?"}
    
    Q2 -- "Ya" --> RecreateObj["PILIH: RECREATE STRATEGY"]
    Q2 -- "Tidak" --> BlueGreenObj["PILIH: BLUE/GREEN DEPLOYMENT<br/>'(Cutover Instan)'"]
    
    Q1 -- "Ya (Stateless / Backward Compatible)" --> Q3{"Seberapa besar risiko rilis<br>dan tuntutan SLA?"}
    
    Q3 -- "Risiko Rendah / Rilis Rutin" --> RollingObj["PILIH: ROLLING UPDATE<br/>'(Default Kubernetes)'"]
    Q3 -- "Risiko Tinggi / Fitur Mayor" --> Q4{"Apakah infrastruktur memiliki<br>kapasitas resource ekstra (CPU/RAM)?"}
    
    Q4 -- "Terbatas" --> CanaryReplica["PILIH: CANARY (Pod Replica Weighting)"]
    Q4 -- "Mencukupi" --> CanaryIngress["PILIH: CANARY (Ingress Traffic Shifting)<br/>atau BLUE/GREEN"]
    
    style RecreateObj stroke:#f57c00,stroke-width:2px
    style BlueGreenObj stroke:#0288d1,stroke-width:2px
    style RollingObj stroke:#388e3c,stroke-width:2px
    style CanaryReplica stroke:#f57c00,stroke-width:2px
    style CanaryIngress stroke:#388e3c,stroke-width:2px

Matriks Perbandingan Strategi #

Tabel komparatif berikut merangkum seluruh parameter teknis dan operasional untuk masing-masing strategi:

Dimensi Evaluasi Recreate Rolling Update Blue/Green Canary
Downtime Ya (Tergantung waktu startup Pod) Tidak Tidak Tidak
Kebutuhan Resource Ekstra Nol (0%) Rendah (Tergantung maxSurge) Tinggi (100% tambahan) Rendah (Bertahap)
Kecepatan Rollback Lambat (Startup ulang v1) Sedang (Proses rolling bertahap) Instan (Hanya ganti routing) Sangat Cepat (Hapus Pod Canary)
Blast Radius (Paparan Bug) Seluruh Pengguna (100%) Seluruh Pengguna (Secara bertahap) Seluruh Pengguna (Saat cutover) Sangat Terbatas (Hanya subset user)
Kompleksitas Implementasi Sangat Rendah Rendah (Native k8s) Menengah (Butuh Service/Ingress switch) Tinggi (Butuh monitoring & traffic shifing)
Persyaratan Aplikasi Dapat berjalan single-instance Harus backward-compatible (v1 & v2 co-exist) Dapat berjalan single-instance Harus backward-compatible (v1 & v2 co-exist)
Mekanisme Validasi Uji pasca-ddeploy Uji bertahap di produksi Uji terisolasi di Green sebelum rilis Uji dengan trafik nyata skala kecil

Anti-Pattern vs Solusi Terbaik #

Mari kita pelajari beberapa kesalahan fatal yang sering terjadi akibat pemilihan atau implementasi strategi deployment yang salah, beserta solusi terbaik untuk mengatasinya.

Anti-Pattern 1: Rolling Update pada Stateful Application dengan Volume Kunci Eksklusif (ReadWriteOnce) #

Melakukan rolling update pada aplikasi yang menggunakan Persistent Volume (PV) dengan mode akses ReadWriteOnce (RWO) di cloud provider. Saat Kubernetes mencoba menjalankan Pod v2 sebelum mematikan Pod v1 (karena pengaturan maxSurge), Pod v2 akan gagal melakukan startup karena volume disk masih dikunci oleh Pod v1.

Pod v2 stuck di status: ContainerCreating
Log Error: "Multi-Attach error for volume ... Volume is already used by Pod v1"

Solusi Terbaik #

Gunakan strategi Recreate untuk menjamin bahwa Pod v1 dilepas sepenuhnya dari host node dan volume dilepaskan (detached) sebelum Pod v2 mencoba menempelkan (attach) volume tersebut.

# ✓ SOLUSI: Konfigurasi strategi Recreate untuk aplikasi stateful pengunci volume
apiVersion: apps/v1
kind: Deployment
metadata:
  name: database-app
  namespace: database
spec:
  replicas: 1
  # Menggunakan Recreate untuk memastikan pelepasan volume disk secara bersih
  strategy:
    type: Recreate
  template:
    spec:
      containers:
      - name: db
        image: postgres:15-alpine
        volumeMounts:
        - name: db-data
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: db-data
        persistentVolumeClaim:
          claimName: postgres-pvc # PVC dengan mode ReadWriteOnce

Anti-Pattern 2: Melakukan Rolling Update Tanpa Mendefinisikan Readiness Probes #

Meluncurkan update aplikasi menggunakan strategi Rolling Update tetapi membiarkan properti readinessProbe kontainer kosong. Kubernetes akan berasumsi kontainer langsung siap menerima trafik begitu proses utama berjalan (status Running). Akibatnya, Kubernetes akan mematikan Pod lama (v1) saat Pod baru (v2) baru saja melakukan inisialisasi awal (startup) dan belum benar-benar siap melayani kueri. Hal ini memicu terjadinya downtime masif di produksi meskipun kita menggunakan strategi Rolling Update.

# ✗ ANTI-PATTERN: Rolling update tanpa readiness probe
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
  template:
    spec:
      containers:
      - name: app
        image: company/payment-api:v2.0.0 # ← Jika proses inisiasi butuh 20 detik, user akan menerima error 502/503

Solusi Terbaik #

Selalu definisikan readinessProbe dan livenessProbe yang akurat agar Kubernetes dapat menunda pematian Pod lama hingga Pod baru benar-benar mengembalikan status sukses (200 OK) pada endpoint kesehatan aplikasi.

# ✓ SOLUSI: Terapkan probe kesehatan untuk menjamin zero-downtime rolling update
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%          # Maksimal 1 Pod ekstra dibuat di atas replika (total 5)
      maxUnavailable: 25%    # Maksimal 1 Pod boleh tidak aktif selama transisi
  template:
    spec:
      containers:
      - name: app
        image: company/payment-api:v2.0.0
        readinessProbe:
          httpGet:
            path: /healthz/ready
            port: 8080
          initialDelaySeconds: 15 # Berikan waktu bagi aplikasi untuk memuat library
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /healthz/live
            port: 8080
          periodSeconds: 10

Anti-Pattern 3: Menjalankan Rilis Blue/Green Tanpa Melakukan Smoke Testing #

Menggunakan strategi Blue/Green dan memindahkan rute Service selector secara langsung sesaat setelah Pod Green berada di status Running, tanpa melakukan verifikasi atau pengujian fungsional khusus pada lingkungan Green.

Solusi Terbaik #

Siapkan Service khusus pengujian (test/smoke service) yang secara eksklusif mengarah ke label kontainer lingkungan Green. Tim QA atau pipa CI/CD kita harus menjalankan skrip pengujian otomatis (smoke test) terhadap service pengujian tersebut terlebih dahulu. Setelah tes dinyatakan lulus, barulah kita memperbarui Service produksi utama untuk diarahkan ke lingkungan Green.

# ✓ SOLUSI: Service Uji (Staging/Smoke Service) yang terisolasi
apiVersion: v1
kind: Service
metadata:
  name: payment-api-test-service
  namespace: payment
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: payment-api
    # Mengarah eksklusif ke lingkungan Green yang sedang diuji
    version: v2.0.0-green 

Rencana Implementasi Section 8 #

Di sisa bagian dari bab ini, kita akan mempelajari penerapan taktis dari masing-masing konsep di atas:

  • Rolling Update: Memahami secara matematis kalkulasi batas surge/unavailable, optimalisasi probe, serta kontrol CLI rollout.
  • Blue/Green Deployment: Panduan membangun lingkungan ganda dengan Ingress weighting, Service update, dan manajemen session database.
  • Canary Deployment: Penerapan pengalihan trafik tingkat lanjut menggunakan Service Mesh dan otomatisasi rilis dengan Argo Rollouts.
  • Recreate: Menghindari attach-detach disk deadlock pada kluster dan meminimalkan celah downtime rilis.
  • Database Migration Strategy: Orkestrasi skema database tanpa downtime menggunakan pola Expand-Contract dan Kubernetes Job.
  • Rollback Strategy: Penanganan pemulihan pasca kegagalan rilis secara otomatis berbasis metrik anomali.
  • GitOps: Mendeklarasikan state cluster menggunakan repositori Git sebagai pusat kendali rilis produksi.
  • Anti-Pattern Deployment: Evaluasi kasus-kasus kegagalan deployment nyata di industri untuk mencegah downtime di cluster kita.

Ringkasan #

  • Tidak ada strategi terbaik universal — Pemilihan strategi deployment adalah hasil penimbangan trade-off antara toleransi downtime bisnis, risiko kegagalan, dan biaya infrastruktur.
  • Gunakan Rolling Update untuk update rutin — Strategi bawaan Kubernetes ini menjamin zero-downtime dan hemat resource, tetapi menuntut kode aplikasi kita kompatibel saat v1 dan v2 berjalan bersamaan.
  • Pilih Recreate untuk skema DB kaku dan Stateful — Jika aplikasi tidak mendukung konkurensi database atau mengunci volume secara eksklusif, gunakan Recreate untuk menghindari kegagalan attach volume.
  • Terapkan Blue/Green untuk rollback instan — Dengan memelihara dua lingkungan identik secara paralel, kita mendapatkan kemampuan untuk membalikkan trafik kembali ke versi stabil dalam hitungan sub-detik jika rilis baru rusak.
  • Maksimal minimalkan blast radius dengan Canary — Salurkan trafik nyata secara bertahap ke versi baru guna membatasi dampak kegagalan rilis hanya pada sebagian kecil pengguna awal.
  • Wajib pasang Probes — Seluruh strategi zero-downtime (Rolling Update, Blue/Green, Canary) tidak akan berfungsi jika kita tidak mengonfigurasi readinessProbe secara akurat pada kontainer aplikasi.

← Sebelumnya: Anti-Pattern Configuration   Berikutnya: Rolling Update →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact