Cách sửa lỗi Init:CrashLoopBackOff: Tại sao Init Container trong Kubernetes bị lỗi

intermediate☸️ Kubernetes2026-05-19| Kubernetes (Mọi phiên bản), Linux-based nodes, Nhà cung cấp Cloud (EKS, GKE, AKS)

Error Message

Init:CrashLoopBackOff
#kubernetes#init-container#crashloopbackoff#khắc phục sự cố#devops

Vấn đề: Pod bị kẹt ở trạng thái Init:CrashLoopBackOff

Bạn đã triển khai manifest của mình, nhưng Pod chỉ đứng yên đó. Trong Kubernetes, initContainers đóng vai trò như những người gác cổng. Container ứng dụng chính sẽ không cố gắng khởi động cho đến khi mọi init container hoàn thành thành công với mã thoát (exit code) là 0. Nếu một container thất bại và rơi vào vòng lặp khởi động lại, Pod của bạn sẽ bị tê liệt ở trạng thái Init:CrashLoopBackOff.

Đây là một điểm nghẽn phổ biến. Vì container chính chưa được tạo, việc chạy các lệnh log thông thường thường không trả về kết quả gì ngoài sự thất vọng. Bạn bị bỏ lại với việc gỡ lỗi một quy trình mà về mặt kỹ thuật thậm chí còn chưa bắt đầu.

Bước 1: Xác định chính xác Container bị lỗi

Các Pod thường chạy nhiều init container theo trình tự. Bước đầu tiên của bạn là xác định mắt xích cụ thể nào trong chuỗi bị hỏng. Sử dụng lệnh describe để kiểm tra trạng thái nội bộ của Pod.

kubectl describe pod <pod-name>

Cuộn xuống phần Init Containers:. Bạn cần tìm một mã thoát khác không hoặc một trạng thái lỗi cụ thể:

Init Containers:
  install-assets:
    Container ID:  containerd://...
    Image:         node:18-alpine
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    127

Trong trường hợp này, container install-assets đang bị lỗi. Mã thoát 127 thường gợi ý lỗi "command not found" (không tìm thấy lệnh) bên trong shell của container.

Bước 2: Trích xuất Log chính xác

Lệnh kubectl logs <pod-name> tiêu chuẩn thường mặc định trỏ vào container ứng dụng chính. Vì container đó chưa tồn tại, lệnh sẽ thất bại. Để xem lỗi thực tế, bạn phải nhắm mục tiêu cụ thể vào init container bằng cách sử dụng flag -c.

kubectl logs <pod-name> -c <init-container-name>

Nếu container bị crash liên tục, các log hiện tại có thể trống rỗng. Hãy sử dụng flag --previous để xem log từ lần thực thi thất bại gần nhất. Đây thường là nơi chứa "bằng chứng thép" (smoking gun).

kubectl logs <pod-name> -c <init-container-name> --previous

Các nguyên nhân phổ biến và cách khắc phục

1. Không tương thích Shell Script và Binary

Nhiều nhà phát triển sử dụng các image nhẹ như alpine hoặc busybox cho các tác vụ init. Nếu script của bạn sử dụng #!/bin/bash nhưng image chỉ chứa /bin/sh, container sẽ bị crash ngay lập tức. Tương tự, việc thiếu quyền thực thi trên tệp script (chmod +x) cũng sẽ gây ra lỗi.

Cách tiếp cận cải tiến: Sử dụng một khối script mạnh mẽ trong YAML của bạn và luôn bao gồm set -e để bắt lỗi sớm.

command:
  - /bin/sh
  - -c
  - |
    set -e
    echo "Đang kiểm tra kết nối cơ sở dữ liệu..."
    # Sử dụng /dev/tcp nếu thiếu nc
    timeout 5 sh -c 'cat < /dev/null > /dev/tcp/db-service/5432'

2. Thiếu ConfigMaps hoặc Secrets

Nếu init container của bạn yêu cầu mật khẩu cơ sở dữ liệu từ một Secret không tồn tại trong namespace hiện tại, Pod sẽ thất bại. Kubernetes thậm chí sẽ không khởi động container nếu tham chiếu valueFrom bị thiếu. Tuy nhiên, nếu secret tồn tại nhưng key bị sai, script của bạn có thể bị crash trong quá trình thực thi.

Cách khắc phục: Xác minh các secret của bạn bằng lệnh kubectl get secret và đảm bảo các key khớp chính xác với định nghĩa env của bạn.

3. Cạn kiệt tài nguyên (OOMKilled)

Các init container thực hiện các tác vụ nặng—như chạy migration cơ sở dữ liệu hoặc biên dịch asset—thường cần nhiều tài nguyên hơn ứng dụng chính. Nếu bạn đặt giới hạn bộ nhớ là 128Mi nhưng công cụ migration đạt đỉnh ở mức 256Mi, kernel sẽ kill tiến trình đó.

Giải pháp: Tìm lỗi Reason: OOMKilled trong đầu ra của lệnh describe pod. Tăng giới hạn tài nguyên cụ thể cho init container:

resources:
  limits:
    memory: "512Mi"
    cpu: "500m"

4. Lỗi RBAC và quyền truy cập

Init container của bạn có sử dụng curl để giao tiếp với Kubernetes API không? Nếu có, nó cần một ServiceAccount với các Role phù hợp. Không có chúng, log của bạn sẽ hiển thị lỗi 403 Forbidden. Luôn kiểm tra xem serviceAccountName của Pod có các quyền cần thiết để thực hiện tác vụ của nó hay không.

Xác minh: Xác nhận bản sửa lỗi

Sau khi cập nhật manifest và áp dụng các thay đổi, hãy theo dõi quá trình chuyển đổi. Một Pod khỏe mạnh sẽ trải qua các giai đoạn sau:

  • Init:0/1 (Init container đầu tiên đang khởi động).
  • PodInitializing (Tất cả init container đã hoàn thành; container chính đang được pull).
  • Running (Thành công).

Kiểm tra log sự kiện bằng lệnh kubectl get events --sort-by='.lastTimestamp' để đảm bảo không còn vấn đề lập lịch (scheduling) tiềm ẩn nào.

Những điểm chính cần lưu ý

  • Init container chạy tuần tự: Chúng chạy từng cái một. Nếu một cái thất bại, toàn bộ Pod sẽ dừng lại.
  • Không có health check: Init container không hỗ trợ liveness hoặc readiness probe. Chúng phụ thuộc hoàn toàn vào mã thoát (exit code).
  • Tính lũy đẳng (Idempotency) là quan trọng: Vì init container có thể khởi động lại nhiều lần, các script của chúng phải đảm bảo an toàn khi chạy lặp lại mà không làm hỏng dữ liệu của bạn.
  • Luôn sử dụng -c: Bạn không thể gỡ lỗi những gì bạn không nhìn thấy. Log mục tiêu là công cụ mạnh mẽ nhất của bạn.

Related Error Notes