Runbook cutover & rollback
Runbook yang ditulis saat tenang adalah satu-satunya yang berguna saat tidak tenang. Ini kerangkanya, lengkap dengan hal yang paling sering terlupa.
Intisari
- Tetapkan ambang batal yang numerik sebelum mulai โ bukan "kalau kelihatan buruk".
- Tunjuk satu orang yang berwenang memutuskan rollback. Bukan rapat.
- Rollback harus bisa dilakukan dalam di bawah 60 detik dan sudah pernah dilatih.
- Jangan cutover pada hari Jumat, saat libur, atau saat ada peristiwa berita besar.
- Yang paling sering terlupa: memberi tahu redaksi, dan menonaktifkan cron di sistem lama.
Sebelum hari-H
| Waktu | Pekerjaan | Selesai kalau |
|---|---|---|
| H-14 | Uji paritas seluruh sampel | Semua gerbang hijau |
| H-14 | Uji beban ke angka trafik puncak (Fase 11) | p95 di bawah target |
| H-7 | Verifikasi seluruh peta redirect | Nol 404 di daftar |
| H-7 | Latih rollback di lingkungan uji | Terukur < 60 detik |
| H-3 | Beri tahu redaksi & dukungan pelanggan | Sudah dikonfirmasi terbaca |
| H-1 | Bekukan perubahan di kedua sistem | Tidak ada deploy lain |
| H-1 | Cadangan database, verifikasi bisa dipulihkan | Uji pemulihan berhasil |
| H-1 | Turunkan TTL DNS kalau ada perubahan DNS | โ |
"Verifikasi cadangan bisa dipulihkan" berarti benar-benar memulihkannya ke instance lain. Cadangan yang tidak pernah diuji bukan cadangan โ ia harapan. Ini satu-satunya jaring pengaman untuk kesalahan yang tidak bisa di-rollback dengan mengubah aturan Cloudflare.
Kapan tidak melakukan cutover
| Jangan | Kenapa |
|---|---|
| Jumat sore | Masalah ditemukan Sabtu, tim tidak lengkap |
| Menjelang libur panjang | Sama, lebih parah |
| Saat ada peristiwa berita besar | Trafik puncak, taruhannya paling tinggi |
| Akhir bulan / awal bulan | Siklus penagihan langganan |
| Saat orang kunci sedang cuti | โ |
Waktu terbaik untuk portal berita Indonesia biasanya Selasa atau Rabu pagi โ trafik sedang, tim lengkap, dan masih ada tiga hari kerja untuk menangani apa pun yang muncul.
Hari-H
T-30m Umumkan di kanal tim. Semua orang siap.
T-15m Naikkan jumlah task ECS ke 2ร normal (cache dingin).
T-10m Verifikasi kesehatan Astro: /sehat, /siap, koneksi database.
T-5m Verifikasi rollback siap: Origin Rule tinggal dinonaktifkan.
T-0 Aktifkan Origin Rule untuk 5% trafik.
T+5m Periksa: 5xx, p95, cf-cache-status, log error.
T+15m Kalau bersih โ 25%.
T+30m Kalau bersih โ 50%.
T+60m Kalau bersih โ 100%.
T+2j Turunkan task ECS ke normal setelah cache hangat.
T+4j Kirim sitemap baru di Search Console.
T+24j Tinjau seluruh metrik; putuskan lanjut atau mundur.
Ambang batal โ tetapkan sekarang, bukan nanti
| Metrik | Batalkan kalau | Sumber |
|---|---|---|
| Tingkat 5xx | > 0,5% selama 5 menit | Cloudflare Analytics |
| p95 latensi origin | > 2ร baseline CI3 | ALB / CloudWatch |
| Error webhook pembayaran | Berapa pun | Log aplikasi |
| Kebocoran isi premium | Satu saja | Uji asap otomatis |
| Kegagalan login | > 2ร baseline | Log aplikasi |
| Koneksi database | > 80% max_connections | CloudWatch |
| Laporan dari redaksi | Tidak bisa menerbitkan | Kanal tim |
Angka-angka ini disepakati sebelum cutover dan tidak dinegosiasikan saat berlangsung. Di tengah peluncuran, semua orang punya insentif untuk menafsirkan angka secara optimis โ sudah banyak pekerjaan yang dikeluarkan, dan mundur terasa seperti kegagalan. Ambang yang ditulis lebih dulu menghapus perdebatan itu.
Prosedur rollback
1. Nonaktifkan Origin Rule di dashboard Cloudflare. (~10 detik)
2. Verifikasi: curl -sI https://portal.contoh.id/berita/uji | grep x-dilayani
โ harus "ci3" (~10 detik)
3. Umumkan di kanal tim: "rollback selesai, dilayani CI3".
4. Biarkan ECS tetap berjalan โ jangan matikan apa pun.
5. Kumpulkan bukti SEBELUM memperbaiki: log, metrik, tangkapan layar.
6. Baru cari akar penyebabnya.
Langkah 5 paling sering dilewati dan paling disesali. Setelah rollback, godaan untuk langsung memperbaiki sangat besar โ dan log yang berputar akan menghapus bukti dalam hitungan jam. Ambil salinannya dulu; sepuluh menit di sini menghemat dua hari menebak-nebak.
Yang tidak bisa di-rollback dengan aturan Cloudflare
| Hal | Kenapa | Pencegahan |
|---|---|---|
| Migrasi skema yang menghapus kolom | CI3 tidak bisa jalan lagi | Tunda sampai CI3 mati |
| Data yang ditulis Astro dengan format baru | CI3 tidak memahaminya | Kompatibel dua arah (Fase 2) |
| Sesi yang dibuat dengan skema baru | Member ter-logout saat rollback | Tabel sesi bersama (Fase 5) |
| Webhook yang sudah diproses Astro | Idempotensi menyelamatkanmu | Fase 6 |
| Email yang sudah terkirim | Tidak bisa ditarik | Batasi laju di jam pertama |
Yang paling sering terlupa
| Terlupa | Akibatnya |
|---|---|
| Cron di CI3 masih jalan | Job berjalan dua kali โ email ganda, tagihan ganda |
| Redaksi tidak diberi tahu | Panel berubah tanpa peringatan; artikel gagal terbit |
| Dukungan pelanggan tidak diberi tahu | Tidak tahu harus menjawab apa |
| URL webhook Midtrans belum diarahkan | Pembayaran tidak tercatat |
| Sitemap lama masih diajukan | Google merayapi URL yang sudah dialihkan |
| Alarm pemantauan masih menunjuk CI3 | Tidak ada yang memberi tahu saat Astro bermasalah |
| Aturan skip WAF webhook belum dipasang | Fase 6 โ pembayaran diblokir |
| Rentang IP Cloudflare belum dikunci | Fase 8 โ WAF bisa dilewati |
Baris pertama adalah yang paling merusak dan paling tidak terlihat. Cron CI3 yang mengirim newsletter, menagih langganan, atau membersihkan sesi akan terus berjalan setelah cutover โ bersamaan dengan versi Astro-nya. Hasilnya email ganda ke seluruh basis pembaca, atau lebih buruk, penagihan ganda. Nonaktifkan crontab CI3 sebagai langkah eksplisit di runbook, bukan sebagai hal yang diingat seseorang.
Setelah cutover
| Waktu | Pekerjaan |
|---|---|
| Hari 1โ3 | Pantau intensif; siapkan orang yang siaga |
| Minggu 1 | Tinjau Search Console harian |
| Minggu 2 | Turunkan kapasitas ECS ke ukuran yang sesuai data nyata |
| Minggu 4 | Bandingkan biaya: egress, RDS, ECS, sebelum vs sesudah |
| Minggu 6 | Kalau semua stabil: matikan CI3, simpan cadangannya |
| Bulan 3 | Baru jalankan migrasi skema yang merusak kompatibilitas |
| Bulan 6 | Arsipkan berkas yatim |
Uji asap otomatis, dijalankan tiap deploy
#!/usr/bin/env bash
set -u
U=https://portal.contoh.id
gagal=0
cek() { printf '%-42s ' "$1"; if eval "$2"; then echo "OK"; else echo "GAGAL"; gagal=$((gagal+1)); fi; }
cek "beranda 200" \
'[ "$(curl -s -o /dev/null -w %{http_code} $U/)" = 200 ]'
cek "artikel 200" \
'[ "$(curl -s -o /dev/null -w %{http_code} $U/berita/artikel-uji)" = 200 ]'
cek "artikel ter-cache" \
'curl -sI $U/berita/artikel-uji | grep -qi "cf-cache-status: \(HIT\|MISS\|EXPIRED\|STALE\)"'
cek "tidak ada Set-Cookie di halaman publik" \
'! curl -sI $U/berita/artikel-uji | grep -qi set-cookie'
cek "premium tidak bocor tanpa sesi" \
'[ "$(curl -s $U/berita/artikel-premium-uji | grep -c KALIMAT_PARAGRAF_KESEPULUH)" = 0 ]'
cek "akun tanpa sesi mengalihkan" \
'[ "$(curl -s -o /dev/null -w %{http_code} $U/akun)" = 302 ]'
cek "URL lama dialihkan 301" \
'[ "$(curl -s -o /dev/null -w %{http_code} $U/news/detail/4471)" = 301 ]'
cek "webhook menolak tanda tangan palsu" \
'[ "$(curl -s -o /dev/null -w %{http_code} -X POST $U/api/midtrans-webhook \
-H "Content-Type: application/json" -d "{\"order_id\":\"x\",\"status_code\":\"200\",\
\"gross_amount\":\"1.00\",\"signature_key\":\"$(printf %0128d 0)\",\
\"transaction_status\":\"settlement\",\"transaction_id\":\"x\",\"payment_type\":\"x\"}")" = 403 ]'
cek "sitemap berita valid" \
'curl -s $U/sitemap-berita.xml | grep -q "<urlset"'
echo "Gagal: $gagal"; exit $((gagal > 0))
Latihan: tulis runbook cutover untuk portalmu sendiri dengan angka ambang yang konkret dan nama orang yang berwenang memutuskan rollback. Lalu latih rollback-nya di lingkungan uji dan ukur waktunya dengan stopwatch. Kalau lebih dari 60 detik, sederhanakan prosedurnya sampai tidak. Terakhir, jalankan skrip uji asap di atas dan pastikan semuanya OK sebelum menganggap persiapanmu selesai.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.