Runbook Upgrade Kubernetes
Panduan operasional upgrade rilis AlurKerja pada cluster Kubernetes on-premise — persiapan, backup, pre-flight checks, migrasi skema database, rollout bertahap 5 tahap, verifikasi, hingga prosedur rollback.
Ringkasan & Prinsip Upgrade
Runbook ini memandu operator infrastruktur dalam melakukan upgrade versi AlurKerja pada cluster Kubernetes on-premise secara terencana dan minim downtime.
Berbeda dengan instalasi awal (lihat Instalasi Kubernetes), proses upgrade melibatkan pembaruan skema database relasional yang sedang berjalan dan pembaruan image container pada banyak deployment mikroservis.
Prinsip Utama Upgrade AlurKerja
- Skema Database Bersifat Aditif: Perubahan skema pada rilis AlurKerja umumnya dirancang aditif (hanya menambah tabel, kolom, constraint, atau indeks). Kolom atau tabel lama tidak langsung dihapus. Ini memungkinkan image aplikasi versi lama tetap berjalan normal di atas database baru, sehingga proses migrasi database dapat diselesaikan sebelum image baru dinaikkan.
- Rollout Bertahap (5 Tahap): Jangan me-restart seluruh namespace sekaligus. Layanan AlurKerja memiliki ketergantungan erat pada layer proxy dan identitas. Komponen harus dinaikkan berurutan mulai dari gateway proxy, layanan autentikasi & tenant, layanan backend, engine proses Camunda, hingga aplikasi frontend.
- Database Pertama, Image Kemudian: Migrasi SQL harus selalu berhasil dan terverifikasi sebelum image container baru di-rollout, karena container baru langsung membutuhkan tabel dan kolom baru saat inisialisasi.
Prasyarat & Persiapan
Pastikan operator memiliki:
- Akses CLI
kubectldengan context yang mengarah ke cluster dan namespace target AlurKerja (misalnya namespacealurkerja). - Izin RBAC untuk membaca, mengubah, dan me-restart
Deployment,ConfigMap, serta menjalankanJobatau Pod debug di namespace tersebut. - Akses koneksi jaringan ke PostgreSQL (baik lewat
psqllokal atau lewat pod sementara di dalam cluster). - Akses ke container registry jika menggunakan mode deployment berbasis image digest.
Tentukan variabel lingkungan kerja untuk memudahkan eksekusi:
export NS=alurkerja
export DB_HOST="<postgres-host>"
export DB_PORT="5432"
export DB_NAME="alur_onprem"
export DB_USER="<postgres-user>"
export PGPASSWORD="<postgres-password>"Langkah 1 — Backup (Wajib)
Jangan pernah memulai upgrade tanpa backup database dan snapshot konfigurasi deployment.
1. Backup Database PostgreSQL
Lakukan backup full database ke file dump biner:
pg_dump -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME \
-Fc -f alurkerja-backup-$(date +%Y%m%d-%H%M).dumpPastikan file dump berhasil terbentuk dan ukurannya tidak 0 byte sebelum melanjutkan.
2. Snapshot Manifest Deployment
Simpan seluruh manifest deployment saat ini sebagai catatan status awal (state before):
kubectl -n $NS get deploy -o yaml > deployments-before-$(date +%Y%m%d).yaml
# Catat pula image dan digest yang sedang berjalan
kubectl -n $NS get pods -o custom-columns=\
'NAME:.metadata.name,IMAGE:.spec.containers[0].image,IMAGE_ID:.status.containerStatuses[0].imageID' \
> pods-before-$(date +%Y%m%d).tsvLangkah 2 — Pre-Flight Checks
Pre-flight checks dilakukan hanya dengan membaca database (SELECT). Tujuannya memastikan lingkungan siap dan mendeteksi kondisi data yang berpotensi menggagalkan migrasi.
1. Cek Ekstensi PostgreSQL
AlurKerja membutuhkan ekstensi vector (pgvector) dan pg_trgm:
SELECT ae.name,
(ae.name IS NOT NULL) AS available,
(e.extname IS NOT NULL) AS installed
FROM (VALUES ('vector'), ('pg_trgm')) AS want(name)
LEFT JOIN pg_available_extensions ae ON ae.name = want.name
LEFT JOIN pg_extension e ON e.extname = want.name;Pastikan kolom installed bernilai true untuk kedua ekstensi.
2. Cek Tabel Dasar
Pastikan tabel fondasi versi sebelumnya sudah ada di schema public:
SELECT t.name AS tabel, to_regclass('public.' || t.name) IS NOT NULL AS ada
FROM (VALUES
('queue_jobs'), ('bpmn_personalizations'), ('tenants'), ('users'),
('report_schedules'), ('drive'), ('simulation_result')
) AS t(name);Semua tabel di atas harus bernilai ada = true. Jika ada yang false, database belum berada di baseline versi prasyarat.
3. Deteksi Bloker Data Lama
Beberapa rilis menambahkan constraint atau indeks unik pada tabel yang sudah berisi data produksi. Dua potensi bloker umum:
A. Bloker Indeks Unik Antrean (queue_jobs)
Pada penambahan indeks unik queue_jobs_pending_task_reminder_unique, migrasi akan gagal jika ada lebih dari satu baris pending dengan topic task.active.reminder untuk pasangan (tenant_id, instance_id) yang sama.
SELECT tenant_id, instance_id, count(*) AS jumlah_duplikat
FROM public.queue_jobs
WHERE status = 'pending' AND topic = 'task.active.reminder'
GROUP BY tenant_id, instance_id
HAVING count(*) > 1;Tindakan jika ditemukan duplikat: Jalankan pembersihan di dalam transaksi dengan menyisakan ID terbesar:
BEGIN;
DELETE FROM public.queue_jobs q
WHERE q.status = 'pending' AND q.topic = 'task.active.reminder'
AND q.id NOT IN (
SELECT max(id) FROM public.queue_jobs
WHERE status = 'pending' AND topic = 'task.active.reminder'
GROUP BY tenant_id, instance_id
);
COMMIT;B. Bloker Constraint Format Kolom (drive.file_type)
Pada penambahan constraint drive_file_type_normalized_chk, PostgreSQL memvalidasi seluruh baris lama. Nilai berupa huruf kapital (misalnya PDF), spasi tepi ('pdf '), atau string kosong ('') akan memicu violation error.
SELECT file_type, count(*) AS baris_melanggar
FROM public.drive
WHERE file_type IS NOT NULL
AND (file_type = '' OR file_type <> btrim(lower(file_type)))
GROUP BY file_type;Tindakan jika ditemukan baris melanggar: Jalankan normalisasi di dalam transaksi:
BEGIN;
UPDATE public.drive
SET file_type = NULLIF(btrim(lower(file_type)), '')
WHERE file_type IS NOT NULL
AND (file_type = '' OR file_type <> btrim(lower(file_type)));
COMMIT;Langkah 3 — Migrasi Skema Database
Migrasi database harus dijalankan secara atomik (dalam transaksi) dengan opsi ON_ERROR_STOP=1.
Opsi A: Migrasi Bulk Kumulatif (Direkomendasikan)
Jika Anda melompati beberapa rilis minor, gunakan berkas migrasi bulk gabungan yang mencakup seluruh rentang versi:
# Eksekusi langsung dari operator workstation
psql -v ON_ERROR_STOP=1 --single-transaction \
-h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME \
-f sql/upgrade_2026.08.4.1_to_2026.09.2.1.sqlBila database PostgreSQL berada di jaringan private cluster yang tidak dapat diakses langsung dari luar, jalankan melalui Pod ephemeral:
kubectl -n $NS run psql-upgrade --rm -i --restart=Never \
--image=postgres:16-alpine \
--env="PGPASSWORD=$PGPASSWORD" \
--command -- psql -v ON_ERROR_STOP=1 \
-h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -f - \
< sql/upgrade_2026.08.4.1_to_2026.09.2.1.sqlOpsi B: Migrasi Terpisah Per Rilis
Jika ingin menjalankan berkas migrasi per sub-versi secara berurutan:
for rel in 2026.08.4.2 2026.08.5.5 2026.09.1.1 2026.09.2.1; do
for f in sql/migrations/$rel/*.up.sql; do
echo ">> Menjalankan $f"
psql -v ON_ERROR_STOP=1 --single-transaction \
-h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -f "$f"
done
doneUntuk detail implementasi runner otomatis, lihat dokumentasi Database Migration.
Langkah 4 — Konfigurasi Environment (ConfigMap)
Jika rilis yang dinaikkan memperkenalkan environment variable baru, perbarui ConfigMap terkait sebelum pod di-restart.
Sebagai contoh, pada rilis 2026.09.1.1, report-service mewajibkan penyetelan 5 kunci antrean:
kubectl -n $NS patch configmap configmap-report --type merge -p '{
"data": {
"ENABLE_QUEUE_PROCESSOR": "true",
"ENBALE_QUEUE_PROCESSOR": "true",
"QUEUE_POLLING_INTERVAL": "5s",
"QUEUE_BATCH_SIZE": "200",
"QUEUE_WORKER_COUNT": "3"
}
}'Pastikan ENBALE_QUEUE_PROCESSOR (typo upstream) ikut disetel sama persis dengan ENABLE_QUEUE_PROCESSOR.
Langkah 5 — Rollout Bertahap 5 Tahap
Untuk mencegah kegagalan autentikasi dan race condition antar-mikroservis, lakukan rollout dalam 5 tahap terstruktur. Tunggu hingga deployment pada tahap sebelumnya mencapai status Available sebelum melangkah ke tahap berikutnya.
| Tahap | Kategori Layanan | Komponen / Deployment | Alasan Urutan |
|---|---|---|---|
| Tahap 1 | Gateway / Proxy | proxy | Titik masuk utama trafik dan gateway identitas terluar. |
| Tahap 2 | Identitas & Tenant | auth, tenant | Menyediakan token autentikasi dan metadata tenant yang dibutuhkan seluruh service backend. |
| Tahap 3 | Layanan Backend | bpm, integration, notification, report, compro-be, simulation-be, migration, generate-test | Pemroses logika bisnis dan konsumen antrean data. |
| Tahap 4 | Engine Workflow | camunda | Mesin orkestrasi proses yang terhubung ke database dan backend worker. |
| Tahap 5 | Aplikasi Frontend | studio, compro, simulation, apps, microsite | Antarmuka pengguna; diperbarui paling akhir setelah seluruh API stabil. |
Prosedur Rollout Per Tahap
Pastikan imagePullPolicy disetel ke Always jika menggunakan tag mengambang seperti :latest:
# Fungsi bantu restart dan tunggu status
rollout_and_wait() {
local dep=$1
if kubectl -n $NS get deploy "$dep" >/dev/null 2>&1; then
echo ">> Rolling out $dep..."
kubectl -n $NS rollout restart deploy/"$dep"
kubectl -n $NS rollout status deploy/"$dep" --timeout=600s
else
echo "-- Deployment $dep tidak ditemukan di namespace $NS, dilewati."
fi
}
# --- TAHAP 1: Proxy ---
rollout_and_wait "deployment-proxy"
# --- TAHAP 2: Auth & Tenant ---
rollout_and_wait "deployment-auth-be"
rollout_and_wait "deployment-tenant-be"
# --- TAHAP 3: Backend Services ---
rollout_and_wait "deployment-bpm-be"
rollout_and_wait "deployment-integration-be"
rollout_and_wait "deployment-notification-be"
rollout_and_wait "deployment-report-be"
rollout_and_wait "deployment-compro-be"
rollout_and_wait "deployment-simulation-be"
# --- TAHAP 4: Camunda ---
rollout_and_wait "deployment-camunda"
# --- TAHAP 5: Frontend Apps ---
rollout_and_wait "deployment-studio-fe"
rollout_and_wait "deployment-app-fe"
rollout_and_wait "deployment-compro-fe"
rollout_and_wait "deployment-simulation-fe"
rollout_and_wait "deployment-microsite-fe"Nama deployment di atas dapat disesuaikan dengan konvensi penamaan yang digunakan pada cluster Anda (misal alurkerja-bpm-be, onprem-bpm, dsb).
Langkah 6 — Verifikasi Pasca-Upgrade
1. Verifikasi Objek Skema Database
Jalankan skrip pemeriksaan verifikasi skema:
psql -v ON_ERROR_STOP=1 -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -f sql/99_verify.sqlSemua baris objek yang diperiksa harus bernilai OK.
2. Verifikasi Pod & Status Image
Pastikan seluruh pod berstatus Running dan Ready:
kubectl -n $NS get pods -o wideSimpan snapshot after untuk mendokumentasikan Image ID/digest yang aktif:
kubectl -n $NS get pods -o custom-columns=\
'NAME:.metadata.name,IMAGE:.spec.containers[0].image,IMAGE_ID:.status.containerStatuses[0].imageID' \
> pods-after-$(date +%Y%m%d).tsvBandingkan pods-after-*.tsv dengan pods-before-*.tsv untuk memastikan image digest benar-benar berubah.
3. Smoke Test Fungsional
Lakukan pengujian fungsional kritis:
- Login melalui SSO / Keycloak berhasil dan sesi user aktif.
- Buka Studio, buka satu diagram BPMN, pastikan form dan metadata termuat.
- Buat dan mulai satu instance proses baru (Start Process), submit nilai form.
- Buka Task List pengguna, ambil task (claim), lalu selesaikan (complete).
- Coba batalkan satu task pada proses yang mendukung fitur pembatalan (cancellable task).
- Buka modul Drive, unggah dokumen, dan verifikasi dokumen dapat diunduh.
- Buka modul Report, buka dashboard, dan jalankan ekspor laporan terjadwal.
Prosedur Rollback
Jika ditemukan kendala kritis selama atau setelah proses upgrade:
Mengapa kubectl rollout undo Tidak Bekerja pada Tag :latest?
Banyak instalasi on-premise mengonfigurasi manifest Kubernetes dengan tag mengambang seperti :latest.
Jebakan Rollout Undo: Ketika Anda menjalankan kubectl rollout undo deploy/<nama>, Kubernetes akan mengembalikan konfigurasi pod template ke ReplicaSet sebelumnya. Namun, jika ReplicaSet sebelumnya juga mereferensikan tag :latest, kubelet akan menarik kembali image terbaru dari registry yang sama! Rollback tidak terjadi dan pod baru tetap menjalankan kode yang bermasalah.
Cara Rollback yang Benar
1. Rollback Berbasis Digest SHA256 (Direkomendasikan)
Gunakan Image ID (digest) yang tercatat di pods-before-*.tsv sebelum upgrade dimulai:
kubectl -n $NS set image deploy/deployment-bpm-be \
bpm=registry.internal/alurkerja/alurkerja-bpm-be@sha256:7f83...abc1
kubectl -n $NS rollout status deploy/deployment-bpm-be2. Rollback Berbasis Tag Versi Spesifik
Ubah image deployment secara eksplisit ke tag rilis sebelumnya (misalnya :2026.08.4.1):
kubectl -n $NS set image deploy/deployment-bpm-be \
bpm=registry.internal/alurkerja/alurkerja-bpm-be:2026.08.4.1Penanganan Skema Database Saat Rollback Image
Skema database TIDAK PERLU di-rollback. Karena perubahan skema AlurKerja bersifat aditif:
- Tabel dan kolom baru tidak diakses oleh image lama.
- Data lama yang dinormalisasi pada tabel
drivetetap valid untuk image lama. - Rollback database (
DROP TABLE,DROP COLUMN) berisiko menghapus data produksi secara permanen. Hanya lakukan rollback skema jika diinstruksikan secara eksplisit oleh tim platform / DBA setelah melakukan backup ulang.
Troubleshooting
| Gejala Masalah | Kemungkinan Penyebab | Tindakan Perbaikan |
|---|---|---|
preflight cek tabel dasar bernilai false | Posisi database belum berada di versi baseline yang disyaratkan. | Hentikan proses. Hubungi tim teknis AlurKerja dengan menyertakan log lengkap preflight. |
could not create unique index ... is duplicated | Terdapat duplikat entri task reminder pada queue_jobs. | Jalankan query pembersihan duplikat sesuai panduan Langkah 2 (Bagian 3.A), lalu jalankan ulang migrasi. |
check constraint "drive_file_type_normalized_chk" ... is violated by some row | Kolom file_type pada tabel drive memuat huruf besar, spasi tepi, atau string kosong. | Jalankan normalisasi SQL sesuai panduan Langkah 2 (Bagian 3.B), lalu ulangi migrasi. |
Pod berstatus ImagePullBackOff atau ErrImagePull | Kredensial secret registry kedaluwarsa atau nama digest image salah. | Periksa konfigurasi dengan kubectl describe pod <nama-pod>. Pastikan imagePullSecrets terpasang dengan benar. |
Pod berstatus CrashLoopBackOff setelah rollout | Konfigurasi ConfigMap kurang, atau urutan rollout salah (dependency belum siap). | Cek log pod: kubectl logs deploy/<nama> --tail=100. Jika error mengindikasikan koneksi atau token auth, pastikan service auth dan tenant sudah sehat lebih dulu. |
rollout status mengalami timeout | Resource cluster tidak mencukupi (CPU/Memory limits) atau liveness probe gagal. | Periksa event pod: kubectl get events --sort-by=.lastTimestamp. Sesuaikan resource request atau periksa kestabilan koneksi database. |
| Login gagal pasca-upgrade | Rollout pada layer identitas belum rampung atau proxy belum mengarahkan trafik dengan benar. | Pastikan pod deployment-proxy, deployment-auth-be, dan deployment-tenant-be sudah berstatus Ready 1/1. |
Kubernetes
Runbook instalasi AlurKerja di cluster Kubernetes on-premise. Berurutan 1..47, satu nomor satu aksi, setiap langkah memiliki validasi observable.
Konsolidasi JWT via Proxy
Runbook aktivasi dan rollback RESOLVE_JWT_VIA_PROXY & PROXY_RESOLVE_JWT — dua mode verifikasi identitas, kontrak header X-User-*/X-Tenant-*, cara menyetel dan merotasi GATEWAY_SHARED_SECRET, serta troubleshooting gejala ke penyebab.
