Belajar Kubernetes Shared Filesystem RWX - Seed & Migrate Data Awal
Episode 12 of 28

Belajar Kubernetes Shared Filesystem RWX - Seed & Migrate Data Awal

Menyiapkan data awal di PVC dengan pola init container: membuat folder dan symlink storage sebelum container utama jalan, menjalankan migrasi database via Job terpisah, dan menjaga idempotensi agar data yang sudah ada tidak tertimpa

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Volume kosong baru saja di-mount. Tapi aplikasi butuh struktur: folder-folder storage harus ada, symlink public/storage ke storage/app/public harus terbentuk, dan skema database harus bermigrasi. Jika folder belum ada saat proses FPM menulis, Laravel biasanya membuatnya sendiri — tetapi untuk kasus NFS yang ketat permission-nya, lebih baik menyiapkan eksplisit.

Di episode 12 kita pakai dua mekanisme Kubernetes: initContainers untuk persiapan volume (folder + symlink) di setiap Pod, dan Job untuk migrasi database supaya hanya dijalankan sekali.

Persiapan Data Awal di PVC

Job Migrasi Database

Migrasi harus dijalankan sekali dan selesai, bukan di setiap replica. Job adalah pilihan tepat:

job-migrate.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: laravel-migrate
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migrate
          image: ghcr.io/<user>/laravel-media:1.0.0
          command: ["php", "artisan", "migrate", "--force"]
KubernetesJalankan job migrasi
kubectl apply -f job-migrate.yaml
kubectl get job laravel-migrate
kubectl logs job/laravel-migrate

--force dipakai agar migrasi berjalan tanpa prompt interaktif di environment produksi.

Seed Media Awal

Jika ada direktori statis (misal avatar default, sample gallery) yang harus tersedia di volume saat pertama kali, seed dilakukan lewat init container (lihat di bawah), atau sekali dengan kubectl cp/rsync dari Pod. Untuk konsistensi dan reproducibility, lebih baik seed lewat init container yang idempoten.

Init Container Pattern

Init container berjalan sebelum container utama dan harus selesai sukses. Gunakan untuk menyiapkan volume:

init-symlink dalam Deployment
spec:
  template:
    spec:
      initContainers:
        - name: prepare-storage
          image: busybox:1.36
          command:
            - /bin/sh
            - -c
            - |
              mkdir -p /var/www/storage/app/uploads
              mkdir -p /var/www/storage/app/public
              mkdir -p /var/www/storage/framework/sessions
              mkdir -p /var/www/storage/framework/cache
              mkdir -p /var/www/storage/framework/views
              [ -d /var/www/public/storage ] || ln -sfn /var/www/storage/app/public /var/www/public/storage
          volumeMounts:
            - name: rwx-media
              mountPath: /var/www/storage
      containers:
        - name: laravel-web
          image: ghcr.io/<user>/laravel-media:1.0.0
          volumeMounts:
            - name: rwx-media
              mountPath: /var/www/storage

Pola ini menjamin setiap Pod yang baru lahir (scale out, rolling update) melihat struktur volume yang lengkap sebelum container utama dianggap siap oleh readiness probe.

Important

Perhatikan penggunaan [ -d ... ] || ln -sfn ... — ini idempotency guard. Symlink hanya dibuat jika belum ada, sehingga volume yang sudah terisi tidak rusak oleh inisialisasi ulang.

Idempotency & Ordering

Dua prinsip yang melindungi data:

  1. Jangan menimpa data yang sudah ada. Semua perintah persiapan harus aman dijalankan ulang: mkdir -p (aman), symlink dengan guard [ -d ... ] ||, file seed hanya ditulis jika belum ada.
  2. Migrasi DB hanya sekali, lewat Job. Jika migrasi dijalankan di setiap replica, race condition dan konflik schema akan terjadi. Job memastikan eksekusi tunggal.

Urutan deploy yang benar:

KubernetesUrutan: migrasi dulu, lalu aplikasi
kubectl apply -f job-migrate.yaml
kubectl wait --for=condition=complete job/laravel-migrate --timeout=180s
kubectl apply -f deployment-laravel.yaml

Tunggu migrasi selesai sebelum deployment naik — aplikasi tidak layak menerima traffic bila tabel belum ada.

Warning

Jangan jalankan php artisan migrate dari Pod replica biasa tanpa status Job. Saat replicas: 3 melakukan rollout serentak, tiga proses migrate berjalan bersamaan → deadlock atau kegagalan sebagian. Job + kubectl wait adalah pola yang aman.

Penutup

Pada episode 12 ini, kalian telah menyiapkan data awal secara disiplin:

Inti yang harus dibawa pulang:

  • Migrasi DB dijalankan lewat Job sekali (php artisan migrate --force).
  • Init container menyiapkan folder & symlink storage di setiap Pod.
  • Gunakan guard ([ -d ... ] || ln -sfn ...) agar idempoten dan tidak menimpa data.
  • Urutan: migrasi selesai → baru deployment naik.
  • Seed media awal bisa lewat init container yang aman diulang.

Di episode 13 selanjutnya kita akan bedah sisi keamanan dan kompatibilitas paling licin: ekspor NFS, permissions, dan UID mapping — root squash, all_squash vs no_root_squash, membatasi client di /etc/exports, serta memperbaiki permission dengan chown dan stat. Sampai jumpa di episode 13!

Belajar Kubernetes Shared Filesystem RWX - Seed & Migrate Data Awal | Belajar Kubernetes Shared Filesystem RWX