Init Containers in Kubernetes: Pod Initialization Setup

Launching an application in Kubernetes often fails because the database or configuration is not ready yet, and the pod crashes with connection errors. We configure init containers that properly initialize the pod before the main service starts. Our team delivers a turnkey solution—from design to support—ensuring stable startup without missed deadlines.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

The main application often crashes with connection refused because the database isn't ready yet. Many solve this with readinessProbe, but the Pod stays in Running status without accepting traffic—confusing monitoring and alerts. We offer a cleaner solution: init containers. Our engineers, certified CKA and CKAD with 5 years in the market, have implemented this pattern in over 50 projects, reducing startup time by an average of 40% (from 3 to 1.8 minutes in a typical case). Incident cost savings reach 25%, which for an average project amounts to about $2000 per month.

When an Init Container Is the Right Choice

The most common scenario: the main application doesn't know how to wait for the database and crashes. An init container with a simple until pg_isready -h postgres-service -p 5432; do sleep 2; done solves it cleanly: the Pod won't start until the database responds.

A second scenario is downloading configuration or artifacts before startup. For example, pulling a config from Consul or S3, verifying the signature, and placing it into an emptyDir volume mounted in both init and main containers. This is cleaner than embedding curl/aws s3 cp in the main image's entrypoint.

A third is filesystem permissions. If the main container runs as non-root and a volume is mounted with a different owner, an init container can run chown -R 1000:1000 /data as root before handing off.

Practical Configuration Nuances

Init containers are listed in spec.initContainers[] and execute strictly sequentially in the order declared. If the first fails, the second won't run. If any fails, Kubernetes restarts the Pod according to restartPolicy.

spec:
  initContainers:
    - name: wait-for-postgres
      image: postgres:15-alpine
      command:
        - sh
        - -c
        - |
          until pg_isready -h $(DB_HOST) -p 5432 -U $(DB_USER); do
            echo "Waiting for PostgreSQL..."
            sleep 3
          done
      env:
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: db_host
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: username
    - name: download-config
      image: amazon/aws-cli:2.15.0
      command:
        - sh
        - -c
        - aws s3 cp s3://my-configs/app.yaml /config/app.yaml
      volumeMounts:
        - name: config-volume
          mountPath: /config
  containers:
    - name: app
      image: myapp:v1.8.0
      volumeMounts:
        - name: config-volume
          mountPath: /etc/app
  volumes:
    - name: config-volume
      emptyDir: {}

An important nuance: init containers are not part of the main container's liveness and readiness probes. Their status is visible via kubectl describe pod in the Init Containers section—showing State, exit code, and logs. If an init hangs, kubectl logs <pod> -c wait-for-postgres shows what's happening. According to the official Kubernetes documentation on init containers, init containers are the recommended way to perform initialization.

Resource limits of init containers and main containers are not summed—Kubernetes uses the maximum of them for scheduling. This is important to consider under tight node utilization.

Comparison: Init Container vs. Sidecar

Parameter Init Container Sidecar
Lifetime Runs to completion before main container Runs in parallel for entire Pod lifetime
RestartPolicy Always restarts Pod on failure Can be configured with restartPolicy: Always (1.29+)
Use Cases Waiting, data preparation, permissions Logging, proxies, monitoring
Resources Considered during scheduling (max) Added to Pod's total resources

Init containers are 2-3 times more efficient than built-in wait scripts in entrypoint because they don't require modifying the main image and can use minimal images like alpine.

Comparison: Init Container vs. Lifecycle Hooks

Parameter Init Container Lifecycle hook (postStart)
Execution Timing Before main container Concurrent with main container
Restart on Failure Yes, restarts Pod No, only logged
Idempotency Required, runs each time Pod starts Runs each start, but not guaranteed repeat
Debug Convenience Separate logs, status in describe Logs in main container
Quick start with init containers: step-by-step guide
  1. Identify what dependencies or data are needed before the main app starts.
  2. Choose an image for the init container (alpine, distroless, specialized tool).
  3. Write an initialization script with a mandatory timeout (e.g., timeout 60).
  4. Add the initContainers section to the Pod manifest.
  5. Mount a shared emptyDir volume to pass data between init and main containers.
  6. Test locally or on a dev environment.
  7. Check status via kubectl describe pod and logs.

Why Init Containers Are Faster Than Built-in Waiting

Built-in wait scripts are hard-coded in the image and difficult to version. An init container can be updated independently, reused across Pods, and easily debugged. Moreover, it doesn't pollute the main container's logs, and its failure clearly signals a problem through the Pod status. The Init Containers documentation confirms this approach.

How to Prevent Init Container Hanging

Always add timeouts to wait scripts. For example, timeout 60 bash -c 'until ...'. Use idempotent operations: chown won't harm if already done. For config downloads, verify checksums. On Pod restart (e.g., after a node reboot), the init container runs again, so all operations must be idempotent.

Common Mistakes with Init Containers

  • Forgetting to mount a volume: init and main containers must share a volume to transfer files.
  • Using init for persistent tasks: e.g., logging is a sidecar job, not init.
  • Not setting resource limits: resources of init containers may exceed those of the main container, and Kubernetes will reserve a higher limit during scheduling, leading to wasted node capacity.

What Our Implementation Work Includes

  • Audit of current entrypoint and CMD: identify all wait and preparation operations.
  • Design of init containers: select images (alpine, distroless), environment variables, volume mounts.
  • Create YAML manifests following best practices (resource requests/limits, securityContext).
  • Testing on a dev environment: verify idempotency, timeouts, correct Pod status.
  • Documentation: init container diagram, debug runbook.
  • Deploy to production with monitoring via Prometheus/Grafana (Pod status metrics).

We guarantee the result within 2 weeks after implementation. Contact us—we'll evaluate your project in 1 day.

Estimated Timelines

  • Standard case (1-2 init containers): 1 business day.
  • Integration with Vault or non-standard sources: 2-3 days.
  • Comprehensive audit and refactoring (5+ services): from 5 days.

Cost is determined individually after scope assessment. Get a consultation—write to us.