본문으로 건너뛰기

Init Container 패턴

2026-02-12 작성2026-09-17 수정3분 읽기
문서 도구
AI용 문서 안내

Pod 라이프사이클 개요 · 체크리스트와 참고 자료

Init Container 모범 사례

Init Container는 메인 컨테이너가 시작되기 전에 실행되어 초기화 작업을 수행합니다.

Init Container 동작 원리

  • Init Container는 순차적으로 실행됩니다 (동시 실행 불가)
  • 각 Init Container는 성공적으로 종료해야 다음 Init Container가 시작됩니다
  • 모든 Init Container가 완료되어야 메인 컨테이너가 시작됩니다
  • Init Container 실패 시 Pod의 restartPolicy에 따라 재시작됩니다
글씨가 작으면 확대해서 확인할 수 있습니다.

Init Container 사용 사례

사례 1: 데이터베이스 마이그레이션

apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
template:
spec:
# Init Container: DB 마이그레이션
initContainers:
- name: db-migration
image: myapp/migrator:v1
command:
- /bin/sh
- -c
- |
echo "Running database migrations..."
/app/migrate up
echo "Migrations completed"
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
# 메인 애플리케이션
containers:
- name: app
image: myapp/web-app:v1
ports:
- containerPort: 8080

사례 2: 설정 파일 생성 (ConfigMap 변환)

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-template
data:
config.template: |
server:
port: {{ PORT }}
host: {{ HOST }}
database:
url: {{ DB_URL }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-config
spec:
template:
spec:
initContainers:
- name: config-generator
image: busybox
command:
- /bin/sh
- -c
- |
# 템플릿에서 실제 설정 파일 생성
sed -e "s/{{ PORT }}/$PORT/g" \
-e "s/{{ HOST }}/$HOST/g" \
-e "s|{{ DB_URL }}|$DB_URL|g" \
/config-template/config.template > /config/config.yaml
echo "Config file generated"
cat /config/config.yaml
env:
- name: PORT
value: "8080"
- name: HOST
value: "0.0.0.0"
- name: DB_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
volumeMounts:
- name: config-template
mountPath: /config-template
- name: config
mountPath: /config
containers:
- name: app
image: myapp/app:v1
volumeMounts:
- name: config
mountPath: /app/config
volumes:
- name: config-template
configMap:
name: app-config-template
- name: config
emptyDir: {}

사례 3: 종속 서비스 대기

apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-api
spec:
template:
spec:
initContainers:
# Init Container 1: DB 연결 대기
- name: wait-for-db
image: busybox
command:
- /bin/sh
- -c
- |
echo "Waiting for database..."
until nc -z postgres-service 5432; do
echo "Database not ready, sleeping..."
sleep 2
done
echo "Database is ready"
# Init Container 2: Redis 연결 대기
- name: wait-for-redis
image: busybox
command:
- /bin/sh
- -c
- |
echo "Waiting for Redis..."
until nc -z redis-service 6379; do
echo "Redis not ready, sleeping..."
sleep 2
done
echo "Redis is ready"
containers:
- name: api
image: myapp/backend-api:v1
ports:
- containerPort: 8080
더 나은 대안: readinessProbe

종속 서비스 대기는 Init Container보다 메인 컨테이너의 Readiness Probe에서 처리하는 것이 더 유연합니다. Init Container는 한 번만 실행되므로, 메인 컨테이너 실행 중 종속 서비스가 다운되면 대응할 수 없습니다.

사례 4: 볼륨 권한 설정

apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-volume
spec:
template:
spec:
securityContext:
fsGroup: 1000
initContainers:
- name: volume-permissions
image: busybox
command:
- /bin/sh
- -c
- |
echo "Setting up volume permissions..."
chown -R 1000:1000 /data
chmod -R 755 /data
echo "Permissions set"
volumeMounts:
- name: data
mountPath: /data
securityContext:
runAsUser: 0 # root로 실행 (권한 변경 위해)
containers:
- name: app
image: myapp/app:v1
securityContext:
runAsUser: 1000
runAsNonRoot: true
volumeMounts:
- name: data
mountPath: /app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: app-data-pvc

Init Container vs Sidecar Container (Kubernetes 1.29+)

Kubernetes 1.29+에서는 Native Sidecar Container가 도입되었습니다.

특성Init ContainerSidecar Container (1.29+)
실행 타이밍메인 컨테이너 전 순차 실행메인 컨테이너와 동시 실행
라이프사이클완료 후 종료메인 컨테이너와 함께 실행
재시작실패 시 Pod 전체 재시작개별 재시작 가능
사용 사례일회성 초기화 작업지속적인 보조 작업 (로그 수집, 프록시)

Sidecar Container 예시 (K8s 1.29+):

apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
initContainers:
# Native sidecar: restartPolicy를 Always로 설정
- name: log-collector
image: fluent/fluent-bit:2.0
restartPolicy: Always # Sidecar로 동작
volumeMounts:
- name: logs
mountPath: /var/log/app
containers:
- name: app
image: myapp/app:v1
volumeMounts:
- name: logs
mountPath: /app/logs
volumes:
- name: logs
emptyDir: {}