Init Container #
Init container adalah container khusus yang berjalan sebelum container utama dalam Pod dimulai. Ia harus selesai dengan sukses sebelum container berikutnya dijalankan — menjadikannya mekanisme yang tepat untuk semua pekerjaan persiapan yang harus selesai sebelum aplikasi bisa berjalan. Memahami kapan dan bagaimana menggunakan init container menghindarkan banyak race condition dan masalah startup yang umum terjadi.
Cara Kerja Init Container #
Urutan eksekusi dalam Pod dengan init container sangat deterministik:
Urutan eksekusi Pod:
Init Container 1
│ (harus exit 0)
▼
Init Container 2
│ (harus exit 0)
▼
Init Container 3
│ (harus exit 0)
▼
Container Utama 1 ─┐
Container Utama 2 ─┤ (berjalan bersamaan)
Container Utama 3 ─┘
Beberapa karakteristik penting init container:
- Berjalan secara serial — satu per satu, bukan paralel
- Jika satu init container gagal (exit code != 0), Kubernetes me-restart Pod dari init container pertama
- Container utama tidak akan pernah dimulai sampai semua init container berhasil
- Init container bisa menggunakan image yang berbeda dari container utama — berguna untuk tooling khusus tanpa harus memasukkannya ke image produksi
Perbedaan dengan Container Biasa #
Init Container:
✓ Berjalan serial, satu per satu
✓ Harus selesai (exit 0) sebelum lanjut
✓ Tidak mendukung lifecycle hooks (postStart, preStop)
✓ Tidak mendukung liveness atau readiness probe
✓ Boleh punya resource yang berbeda dari container utama
Container Biasa:
✓ Berjalan paralel (semua sekaligus)
✓ Diharapkan berjalan terus (long-running)
✓ Mendukung semua probe dan lifecycle hooks
✓ Di-restart jika crash (sesuai restartPolicy)
Use Case: Menunggu Dependency Siap #
Ini adalah use case paling umum. Aplikasi sering bergantung pada service lain — database, message queue, external API — yang mungkin belum siap saat Pod pertama kali dijalankan.
apiVersion: v1
kind: Pod
metadata:
name: api-server
spec:
initContainers:
# Init 1: tunggu database siap menerima koneksi
- name: wait-for-postgres
image: busybox:1.35
command:
- sh
- -c
- |
echo "Waiting for PostgreSQL..."
until nc -z postgres-service 5432; do
echo "PostgreSQL not ready, retrying in 3 seconds..."
sleep 3
done
echo "PostgreSQL is ready!"
# Init 2: tunggu Redis siap
- name: wait-for-redis
image: redis:7-alpine
command:
- sh
- -c
- |
until redis-cli -h redis-service ping | grep -q PONG; do
echo "Redis not ready, retrying..."
sleep 2
done
echo "Redis is ready!"
containers:
- name: api
image: my-api:v2
# Baru jalan setelah PostgreSQL DAN Redis siap
Use Case: Database Migration #
Menjalankan database migration sebelum aplikasi dimulai adalah pola yang sangat umum dan tepat untuk init container. Ini memastikan schema selalu up-to-date sebelum ada traffic masuk.
initContainers:
- name: run-migrations
image: my-api:v2 # gunakan image yang sama dengan aplikasi
command:
- sh
- -c
- |
echo "Running database migrations..."
/app/migrate up
echo "Migrations completed successfully"
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secret
key: DATABASE_URL
containers:
- name: api
image: my-api:v2
# Aplikasi baru jalan setelah migration selesai
Pola migration di init container bekerja dengan baik untuk deployment single-replica atau ketika migration bersifat backward-compatible. Jika kamu punya banyak replica yang di-rolling update, beberapa Pod lama mungkin masih berjalan dengan schema baru. Pastikan migration selalu backward-compatible dengan versi aplikasi sebelumnya.
Use Case: Menyiapkan Konfigurasi Dinamis #
Init container bisa menghasilkan konfigurasi yang dibutuhkan container utama, berdasarkan informasi yang baru diketahui saat runtime:
volumes:
- name: config-volume
emptyDir: {}
initContainers:
- name: generate-config
image: my-config-generator:v1
command:
- sh
- -c
- |
# Ambil konfigurasi dari Vault atau secret manager
# Generate file konfigurasi berdasarkan environment
/app/generate-config \
--env production \
--region $(curl -s http://169.254.169.254/latest/meta-data/placement/region) \
--output /etc/config/app.yaml
volumeMounts:
- name: config-volume
mountPath: /etc/config
containers:
- name: app
image: my-app:v1
volumeMounts:
- name: config-volume
mountPath: /etc/config # baca config yang sudah digenerate
readOnly: true
Use Case: Clone Repository atau Asset #
Untuk kasus di mana container utama butuh data yang perlu diambil dari tempat lain:
volumes:
- name: workdir
emptyDir: {}
initContainers:
- name: clone-repo
image: alpine/git:2.40
command:
- git
- clone
- https://github.com/myorg/config-repo.git
- /work
volumeMounts:
- name: workdir
mountPath: /work
containers:
- name: app
image: my-app:v1
volumeMounts:
- name: workdir
mountPath: /app/config
readOnly: true
Resource untuk Init Container #
Init container dan container utama punya resource yang dihitung secara berbeda oleh Kubernetes:
initContainers:
- name: heavy-migration
image: my-migrator:v1
resources:
requests:
cpu: "1000m" # migration butuh lebih banyak resource
memory: "512Mi"
limits:
cpu: "2000m"
memory: "1Gi"
containers:
- name: api
resources:
requests:
cpu: "250m" # aplikasi normal butuh lebih sedikit
memory: "128Mi"
Resource efektif yang di-request Pod untuk scheduling adalah maximum dari: (requests semua init container) dan (jumlah requests semua container utama). Init container berjalan bergantian, jadi tidak dijumlah — hanya diambil nilai terbesarnya.
Contoh perhitungan:
Init container A: request 500m CPU
Init container B: request 300m CPU
Container utama: request 250m CPU
Effective request = max(500m, 300m, 250m) = 500m CPU
Debugging Init Container #
Ketika init container gagal, Pod akan terus me-restart dalam loop. Cara mendiagnosis:
# Lihat status Pod — perhatikan INIT kolom
kubectl get pods
# Output jika init container masih berjalan:
# NAME READY STATUS RESTARTS AGE
# api-server 0/1 Init:0/2 0 30s
# Output jika init container gagal:
# NAME READY STATUS RESTARTS AGE
# api-server 0/1 Init:Error 3 2m
# Lihat log dari init container yang gagal
kubectl logs api-server -c wait-for-postgres
# Lihat log dari init container sebelumnya (setelah restart)
kubectl logs api-server -c wait-for-postgres --previous
# Detail event untuk melihat alasan kegagalan
kubectl describe pod api-server
Ringkasan #
- Serial dan blocking — init container berjalan satu per satu; container utama tidak dimulai sampai semua init container exit 0.
- Dependency wait yang andal — pola yang tepat untuk menunggu database, message queue, atau service lain siap sebelum aplikasi dimulai.
- Database migration yang aman — jalankan migration di init container untuk memastikan schema sudah benar sebelum ada traffic masuk; pastikan migration backward-compatible untuk rolling deployment.
- Gunakan image yang ringan — init container untuk wait-for-dependency tidak perlu image besar;
busyboxataualpinesudah cukup.- Resource dihitung berbeda — scheduler menggunakan nilai maksimum antara init container dan container utama, bukan penjumlahan.
- Debug dengan
-c nama-init-container— log init container bisa dilihat dengan flag-cdiikuti nama init container spesifik.
← Sebelumnya: Single & Multi Container Berikutnya: Sidecar Pattern →