Legacy Migration Toolkit
On this page
- Sekilas
- Yang dikerjakannya
- A. Mengekspor tanpa mengubah data sumber
- B. Mengimpor tiap store dengan cara yang diizinkan versinya
- C. Menolak sebelum merusak apa pun
- D. Memverifikasi apa yang benar-benar ada
- E. Mengganti nama modul tanpa kehilangan datanya
- Cara saya memakainya
- Keputusan rancangan
- Spesifikasi
- Terkait
- Istilah
Legacy Migration Toolkit adalah empat perintah yang memindahkan stack yang sedang berjalan dari layout lamanya ke struktur baru, melintasi versi mayor database dan mesin pencarinya. Satu perintah mengekspor semuanya dari server lama; satu mengimpornya ke struktur baru, tiap store dengan cara yang diizinkan versinya; satu memverifikasi apa yang benar-benar tiba; dan satu mengganti nama folder modul tanpa kehilangan data yang bergantung pada nama itu.
Migrasi seperti ini tak bisa berupa salin folder. PostgreSQL menolak menyala di atas data directory yang ditulis versi mayor lebih lama, upgrade mesin pencari di tempat tak bisa dibatalkan, dan catatan yang dipindahkan mencakup log tanda tangan yang wajib bertahan sepanjang masa retensinya.
Sekilas
| Tools | export-legacy-data, import-legacy-data, verify-migration, rename-modules |
|---|---|
| Bentuk | Script command-line |
| Bahasa | Bash, yang mengendalikan Docker, pg_dump dan pg_restore, snapshot API Elasticsearch, rsync, dan openssl |
| Status | Stabil, sudah dipakai untuk migrasi yang selesai |
| Kode sumber | Privat |
Yang dikerjakannya
A. Mengekspor tanpa mengubah data sumber
Export men-dump tiap database, menyalin object storage, mengambil snapshot indeks telemetry lewat API milik mesin pencari itu sendiri, dan mengumpulkan runtime state yang tak pernah dipegang version control, misalnya daftar pencabutan milik certificate authority. Ia menulis manifest berisi checksum dan jumlah tabel untuk tiap dump, ukurannya, serta versi image sumber. Ruang disk diperiksa lebih dulu, dan ia memperingatkan bila object storage tak akan muat, lalu hasilnya bisa ditulis ke disk lain atau object storage-nya ditinggalkan. Folder export dikunci hanya untuk pemiliknya. Ia memastikan sumbernya memang tampak seperti folder production lama, dan sengaja mempertahankan nama container layout lama, dengan catatan agar tak disatukan, karena sumber tak ikut berubah hanya karena tujuannya berubah. Database di-dump dalam format custom tanpa owner dan privilege, yang toleran terhadap server yang lebih baru dan role yang berbeda di sana. Snapshot telemetry hanya mencakup indeks telemetry, tanpa global state cluster; bila mesin pencari lama belum punya path repository, export mencetak baris compose dan perintah persis untuk menambahkannya, dan repository-nya diserahkan ke user mesin itu lalu disalin keluar lewat container berumur pendek, karena file-nya milik user itu, bukan milik saya. Daftar pencabutan disalin dengan checksum, wajib terbaca sebagai file DER yang sah, diperiksa masa berlakunya, dan dijelaskan bila keliru berbentuk direktori. File environment dan konfigurasi dibawa sebagai rujukan saja, bukan untuk ditimpakan ke struktur baru, yang kuncinya berbeda; log aplikasi ikut dibawa. Progres salinan hanya ditampilkan di terminal, jadi file log tak dipenuhi carriage return.
B. Mengimpor tiap store dengan cara yang diizinkan versinya
Database di-restore dari dump-nya ke versi mayor yang baru. Mesin pencari me-restore snapshot, sesudah data stream yang akan bertabrakan dengannya dibuang. Object storage disalin sebagai file, karena format on-disk-nya tetap terbaca di versi berikutnya. Store cache dan queue ditinggalkan, sebab bukan sumber kebenaran. Daftar pencabutan dipasang di tempatnya, sesudah direktori yang tertinggal di posisinya dihapus, lalu tanggal berlakunya dicetak. Database di-restore dengan opsi clean, if-exists, no-owner, dan no-privileges, jadi restore aman diulang. Policy bucket dipasang ulang sebagai langkah tersendiri; run ini menyalin lewat container bila folder milik root menolak salinan biasa, dan bisa dibatasi ke database, object storage, atau telemetry untuk migrasi bertahap.
C. Menolak sebelum merusak apa pun
Import memvalidasi setiap checksum sebelum menyentuh satu database pun, jadi dump yang rusak menghentikan run selagi tujuan masih utuh. Bila export mencatat indeks pencarian yang terlalu tua bagi mesin baru, restore telemetry dilewati dan reindex diminta lebih dulu, sementara tahap lainnya tetap berjalan. Sesudah tiap restore, jumlah tabel dibandingkan dengan angka yang dicatat export, dan perbedaannya ditandai untuk diperiksa. Kegagalan di dalam satu tahap — database yang tak kunjung siap dalam semenit, error dari tool restore, restore snapshot yang gagal — dilaporkan dan tahap-tahap selebihnya tetap berjalan; perintah verifikasi yang memberi putusan akhir.
D. Memverifikasi apa yang benar-benar ada
Perintah verifikasi memeriksa tujuan, bukan sekadar percaya bahwa script sudah selesai: data ada di tiap store, file terbaca oleh user yang menjalankan tiap container, folder dimiliki user yang dibutuhkan mesin pencari, dan user telemetry sudah tersedia. Satu pemeriksaan yang gagal tak menghentikan yang lain, dan container yang mati dilaporkan sebagai dilewati, bukan gagal, supaya perintah ini tetap berguna selama migrasi dikerjakan bertahap. Prefix container dibaca dari file environment, bukan ditebak dari nama folder, setelah prefix tebakan yang tak pernah ada mengubah setiap pemeriksaan menjadi "dilewati" dan menyembunyikan kerusakan nyata. Ia memastikan server database minimal versi 18, bukti bahwa upgrade mayor sungguh terjadi, dan bahwa daftar pencabutan adalah file yang sah dan belum kedaluwarsa, bukan file yang hilang atau malah direktori. Keterbacaan file diperiksa untuk dua file konfigurasi milik certificate authority: user yang menjalankan tiap image diterjemahkan ke id angkanya dengan bertanya di dalam image, dibaca dari file compose bila container-nya belum ada, dan diperiksa sebelum apa pun dinyalakan, jadi izin yang salah ketahuan tanpa menunggu tiga puluh percobaan health check. Modul yang lahir sesudah export lama tak punya entri di manifest dan cukup punya tabel. Ia diakhiri dengan hitungan lolos, peringatan, dan gagal, lalu keluar dengan 1 bila ada yang gagal.
E. Mengganti nama modul tanpa kehilangan datanya
Folder modul dulu memakai garis bawah dan kini memakai tanda hubung. Karena path data tiap modul memuat namanya, mengganti nama folder ikut memindahkan tempat Docker mencari datanya, jadi perintah rename memindahkan folder data dalam langkah yang sama, dan menjaga riwayat folder bila version control melacaknya. Cakupannya development, production, dan setiap versi staging. Akses root diperiksa sebelum apa pun berubah, setelah prompt password yang butuh terminal pernah meninggalkan folder project ter-rename sementara data-nya belum. Ukuran folder data dibandingkan sebelum dan sesudah dipindah, dan tujuan yang sudah ada tak pernah ditimpa. Nama project compose tiap modul yang di-rename ditulis ulang, jadi yang lama dan yang baru tak dianggap dua project. Nama project jatuh ke nama folder bila kosong, setelah ketiadaannya pernah membuat rename tetap jalan sementara container development masih hidup. Tabel nama yang di-rename membawa peringatan berbingkai agar tak pernah dikenai cari-ganti global garis bawah, setelah satu sapuan seperti itu membuat kedua kolomnya sama dan rename diam-diam tak mengerjakan apa pun sampai production membutuhkannya. Penulisan ulang kunci yang tak menemukan apa pun tak lagi menghentikan run sesudah modul pertama, dan path dihitung saat dipakai, jadi prefix data yang diatur belakangan tetap dihormati.
Cara saya memakainya
| Store | Lama | Baru | Cara pindahnya |
|---|---|---|---|
| PostgreSQL | 14 | 18 | dump lalu restore; data directory terikat versi mayornya |
| Elasticsearch | 8 | 9 | snapshot lalu restore; upgrade di tempat hanya satu arah |
| Object storage | tak dipatok | rilis yang dipatok | salin folder; formatnya tetap terbaca |
| Redis | tak dipatok | rilis yang dipatok | tak dimigrasi; hanya cache dan queue |
| Store | Container-nya harus | Alasan |
|---|---|---|
| Object storage | mati | menyalin ke folder storage yang hidup bisa merusak backend-nya |
| PostgreSQL | hidup | restore butuh server yang menerima koneksi |
| Elasticsearch | hidup | snapshot di-restore lewat API-nya |
Keputusan rancangan
Export dan import terpisah, dan data sumber tak pernah diubah. Data biasanya harus diamankan sebelum struktur baru siap menerimanya, jadi kedua bagian berjalan di hari berbeda dan bertemu lewat satu folder. Export men-dump, menyalin, dan mengambil snapshot, dan satu-satunya yang ia tambahkan di samping data lama adalah repository snapshot yang dibutuhkan mesin pencari untuk menulis snapshot-nya. Manifest-lah yang membuat import bisa memercayai folder itu: checksum diperiksa sebelum database tujuan mana pun di-drop, jumlah tabel dibandingkan sesudah tiap restore, dan versi image sumber tercatat. Folder itu hanya bisa dibaca pemiliknya, dan export memperingatkan sebelum menggandakan puluhan gigabyte object storage di disk yang terlalu kecil.
Tiap store menyeberangi jarak versi dengan caranya sendiri. PostgreSQL 18 tak mau menyala di atas direktori yang ditulis versi 14, jadi database berpindah sebagai dump. Elasticsearch 9 hanya membaca indeks buatan versi 8, dan begitu ia menyentuh folder data, versi 8 tak bisa lagi membacanya, jadi telemetry berpindah sebagai snapshot, yang portabel lintas versi dan menyisakan titik untuk kembali. Indeks buatan versi 7 sudah tertangkap saat export dan menghentikan restore kecuali dipaksa. Object storage cukup dibawa file-nya, dan Redis, yang hanya menyimpan cache dan queue, ditinggalkan.
Ia tak pernah menyalakan atau mematikan stack sendiri. Kebutuhan tiap store bertolak belakang — object storage mati, PostgreSQL dan mesin pencari hidup — dan import memeriksa masing-masing. Bila keadaannya salah, ia berhenti dan mencetak perintah yang akan membetulkannya, serta menunggu hingga satu menit sampai database menerima koneksi sebelum melaporkan database itu dan beralih ke berikutnya. Kendali atas stack production tetap di tangan orang yang menjalankan migrasi. Perintah rename mengikuti aturan yang sama, dan menolak berjalan selama container terkait masih hidup.
Verifikasi mencari kegagalan yang tampak seperti sukses. File konfigurasi yang hanya bisa dibaca pemiliknya berjalan lancar di laptop saya, karena user id saya kebetulan 1000, sama dengan user di dalam image certificate authority; di server dengan id berbeda, authority itu restart tanpa henti, dan dua service yang menunggunya tampil unhealthy, menunjuk ke mana-mana kecuali ke penyebabnya. User telemetry yang hilang lebih senyap lagi: setiap service tetap sehat, dashboard tetap terbuka, tapi setiap log, trace, dan metrik dibuang — dan itu terjadi selama dua hari di production. Karena itu verifikasi memeriksa keterbacaan file terhadap user id tiap container, kepemilikan folder, dan user telemetry, sebelum ada yang menyatakan migrasi selesai. Pemeriksaan terakhir saya kerjakan sendiri: satu dokumen ditandatangani dari awal sampai selesai.
Spesifikasi
| Masukan | Folder production lama untuk diekspor; folder export dan environment tujuan untuk diimpor |
|---|---|
| Keluaran | Folder export berisi dump, file object storage, snapshot pencarian, runtime state, dan manifest; store yang sudah di-restore di tujuan; laporan verifikasi |
| Keamanan | Dry run untuk export, import, dan rename; checksum dump database divalidasi sebelum tujuan mana pun di-drop; jumlah tabel dibandingkan; tak pernah menyalakan atau mematikan stack; data ikut berpindah bersama folder-nya saat rename, dengan ukuran dibandingkan dan tanpa menimpa; kegagalan di dalam tahap export dan import dilaporkan, dan verifikasi yang memberi putusan akhir |
| Prasyarat | Docker; struktur tujuan sudah terpasang; ruang disk untuk export, atau disk kedua; akses jaringan untuk menarik image pembantu kecil saat berjalan |
Terkait
Cerita tentang memindahkan database dan arsip log melintasi versi mayor.
Toolkit yang mengambil alih begitu data sudah berpindah; repository snapshot-nya termasuk tempat yang diperiksa verifikasi.
Toolkit yang memberi environment tujuan network-nya sebelum apa pun diimpor ke sana.
Setiap script mengikuti bentuk yang saya berikan pada setiap tool kecil, dalam varian Bash-nya.
Toolkit yang membuat user telemetry production — langkah yang hasilnya diperiksa verifikasi di sini.
Kenapa migrasi diperlakukan seperti pemulihan: titik untuk kembali dulu, baru pindah.
Kenapa telemetry yang kehilangan user-nya dibuang tanpa sepatah kata.
Istilah
- Versi mayor
- Rilis yang boleh mengubah format on-disk, sehingga data tulisan satu versi mayor belum tentu terbaca versi berikutnya.
- Dump dan restore
- Mengekspor database sebagai file portabel lalu memuatnya ke server lain, dengan versi yang sama atau lebih baru.
- Repository snapshot
- Lokasi tempat Elasticsearch menulis snapshot-nya, yang bisa di-restore oleh node lain.
- Manifest
- File yang mendaftar isi satu export, dengan checksum untuk tiap dump database supaya kerusakan terdeteksi sebelum dipakai.
- User id
- Angka yang dipakai kernel untuk memutuskan siapa boleh membaca file; namanya tak berpengaruh, hanya angkanya.
- Data stream
- Rangkaian indeks Elasticsearch yang hanya ditambah, di sini dipakai untuk telemetry.
Technologies covered
- Bash
- Elasticsearch
- PostgreSQL
- Docker
- MinIO