وقتی چیزی در Kubernetes کار نمیکند، پیامهای وضعیت (CrashLoopBackOff، Pending، ImagePullBackOff) فقط علامتاند. عیبیابی سریع یعنی یک مسیر ثابت داشتن: وضعیت را بخوانید، رویدادها را ببینید، لاگ را بخوانید و در صورت نیاز از داخل Pod بررسی کنید. این راهنما همین مسیر را همراه با علتها و راهحلهای رایج هر وضعیت فهرست میکند.
مسیر ثابت عیبیابی
kubectl get pods -o wide # 1) وضعیت، نود، IP
kubectl describe pod <pod> # 2) Events انتهای خروجی را بخوانید
kubectl logs <pod> [-c <container>] [--previous] # 3) لاگ کانتینر
kubectl get events --sort-by=.lastTimestamp # 4) رویدادهای namespace
kubectl exec -it <pod> -- sh # 5) بررسی از داخل
اگر مانیفستها را دستی مینویسید، پیش از apply ساختار YAML را بررسی کنید؛ بخش بزرگی از مشکلها (تورفتگی، نام فیلد اشتباه) همانجا پیدا میشود.
راهنمای سریع وضعیتها
| وضعیت | یعنی | اول چه ببینید |
|---|---|---|
| Pending | زمانبندی نشده یا هنوز منتظر منبع است | Events: منابع نود، PVC، taint |
| ContainerCreating | در حال ساخت (دانلود ایمیج، mount volume) | Events: خطای mount یا pull |
| ErrImagePull / ImagePullBackOff | دانلود ایمیج شکست خورده | نام و تگ، imagePullSecrets، دسترسی شبکه |
| CrashLoopBackOff | کانتینر بالا میآید و میمیرد | logs --previous، exit code |
| CreateContainerConfigError | ConfigMap یا Secret موجود نیست | Events: نام منبع و کلید |
| Running ولی 0/1 Ready | readinessProbe شکست میخورد | مسیر و پورت probe |
| OOMKilled | حافظه از limit بیشتر شد | limits.memory، نشتی حافظه |
| Evicted | نود منابع (حافظه/دیسک) کم آورد | kubectl describe node |
| Terminating (گیرکرده) | finalizer یا کانتینر پاسخ نمیدهد | finalizers، terminationGracePeriodSeconds |
Pending: چرا Pod جایی برای اجرا پیدا نمیکند؟
خروجی kubectl describe pod معمولاً دلیل را در Events مینویسد، مثلاً:
Warning FailedScheduling 0/3 nodes are available: 3 Insufficient cpu.
Warning FailedScheduling 0/3 nodes are available: 3 node(s) had untolerated taint {dedicated: gpu}.
Warning FailedScheduling 0/3 nodes are available: pod has unbound immediate PersistentVolumeClaims.
- Insufficient cpu/memory: مجموع requests از ظرفیت نودها بیشتر است. requests را واقعبینانه کنید یا نود اضافه کنید. (
kubectl describe nodeبخش «Allocated resources».) - untolerated taint: نودها taint دارند و Pod toleration مناسب ندارد.
- nodeSelector / affinity: برچسب خواستهشده روی هیچ نودی نیست.
- unbound PVC:
kubectl get pvc؛ StorageClass وجود ندارد یا provisioner کار نمیکند.
ImagePullBackOff: دانلود ایمیج شکست خورده
kubectl describe pod <pod> | grep -A5 -i "failed to pull"
پیام Events علت را میگوید. رایجترین علتها:
- نام یا تگ اشتباه: «manifest unknown» یا «not found». نام را روی یک ماشین دیگر با
docker pullامتحان کنید. - رجیستری خصوصی بدون احراز هویت: «unauthorized». Secret از نوع docker-registry بسازید و در
imagePullSecretsPod یا ServiceAccount بگذارید. - محدودیت نرخ یا دسترسی رجیستری: «toomanyrequests» یا «403» یا timeout. روی سرورهای ایران، دسترسی نودها به رجیستریهای خارجی ممکن است قطع باشد؛ از آینهی رجیستری یا رجیستری خصوصی داخلی استفاده کنید.
- تگ latest و
imagePullPolicy: با تگ ثابت و سیاستIfNotPresentفشار روی رجیستری و احتمال خطا کم میشود.
# امتحان دانلود مستقیم روی خود نود (containerd)
sudo crictl pull registry.example.com/app:1.8.2
برای شبکهی نودها و رفع خطای 403 هنگام نصب بستههای سیستمی، راهنمای نصب از مخزن داخلی را ببینید.
CrashLoopBackOff: کانتینر بالا میآید و میمیرد
kubectl logs <pod> --previous
kubectl describe pod <pod> | grep -A6 "Last State"
مقدار Exit Code در Last State سرنخ خوبی است:
| Exit code | معنی معمول |
|---|---|
| 1 | خطای برنامه؛ لاگ را بخوانید |
| 126 / 127 | فرمان قابلاجرا نیست / پیدا نشد (Command یا Entrypoint اشتباه) |
| 137 | SIGKILL؛ اغلب OOMKilled (یا شکست liveness) |
| 139 | Segmentation fault |
| 143 | SIGTERM؛ توقف عادی یا شکست liveness probe |
علتهای رایج: متغیر محیطی یا فایل پیکربندی گمشده، اتصال به دیتابیس که هنوز آماده نیست، livenessProbe خیلی سختگیرانه که برنامه را قبل از بالاآمدن میکشد (initialDelaySeconds یا startupProbe اضافه کنید)، و تنظیم command که ENTRYPOINT ایمیج را اشتباه جایگزین کرده است.
Running ولی Ready نیست
Pod اجرا شده ولی ستون READY مثل 0/1 است؛ یعنی readinessProbe موفق نمیشود و Pod از Service کنار گذاشته میشود. بررسی کنید مسیر و پورت probe درست باشد، برنامه روی 0.0.0.0 گوش بدهد (نه 127.0.0.1) و initialDelaySeconds کافی باشد. از داخل Pod آزمایش کنید:
kubectl exec -it <pod> -- wget -qO- http://localhost:8080/healthz
Service به Pod نمیرسد
اگر درخواستها به Service جواب نمیگیرند، اول endpoints را ببینید؛ فهرست خالی یعنی Service هیچ Pod آمادهای پیدا نکرده:
kubectl get endpoints web
kubectl get pods -l app=web --show-labels
kubectl describe svc web
- selector با برچسب Pod نمیخواند (رایجترین علت): مقدار
spec.selectorService را باlabelsPod مقایسه کنید. - Pod آماده نیست: Podهای Not Ready در endpoints نمیآیند.
- targetPort اشتباه: باید پورتی باشد که برنامه واقعاً در آن گوش میدهد.
با یک Pod موقت از داخل کلاستر آزمایش کنید و سپس از بیرون:
kubectl run tmp --rm -it --image=busybox:1.36 --restart=Never -- wget -qO- http://web.default.svc
kubectl port-forward svc/web 8080:80 # دسترسی از ماشین خودتان
اگر نام سرویس resolve نمیشود، مشکل از CoreDNS است: kubectl -n kube-system get pods -l k8s-app=kube-dns و لاگ آن را بخوانید. برای مرور اصول DNS، راهنمای عیبیابی DNS و SSL را ببینید.
Ingress: خطای 404، 502 و 503
- 404: هیچ rule با Host/path درخواست نمیخواند، یا
ingressClassNameبا کنترلر نصبشده یکی نیست. باkubectl get ingressوdescribeبررسی کنید. - 503: Service endpoint ندارد (بخش قبل).
- 502/504: کنترلر به Pod وصل شده ولی پاسخ نگرفته؛ پورت یا پروتکل backend (HTTP در برابر HTTPS) را بررسی کنید و لاگ کنترلر را بخوانید:
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller.
برای آزمایش بدون DNS، هدر Host را دستی بفرستید:
curl -sI -H "Host: example.com" http://<ingress-ip>/
HTTPHTTP Headers Viewerکد وضعیت، ریدایرکت و هدرهای پاسخ یک آدرس را از بیرون ببینید.
دیباگ داخل Pod و نود
ایمیجهای کمحجم (distroless) shell ندارند و kubectl exec کار نمیکند. با کانتینر موقت میتوانید ابزار خودتان را کنار کانتینر اصلی اجرا کنید:
kubectl debug -it pod/<pod> --image=busybox:1.36 --target=<container>
kubectl debug node/<node> -it --image=busybox:1.36 # دسترسی به نود (فایلسیستم میزبان در /host)
وقتی استقرار جدید مشکل ساخت
kubectl rollout status deployment/web
kubectl rollout history deployment/web
kubectl rollout undo deployment/web # بازگشت به نسخهی قبلی
اگر rollout گیر کرده، معمولاً Pod جدید Ready نمیشود (readinessProbe یا ایمیج اشتباه)؛ Deployment بهخاطر maxUnavailable: 0 نسخهی قبلی را نگه میدارد و سرویس قطع نمیشود. مشکل را رفع یا با rollout undo برگردید.
جمعبندی و مطالعهی بعدی
بیشتر مشکلها با describe و Events پیدا میشوند، نه با حدس زدن. مسیر ثابت (وضعیت، Events، لاگ، endpoints) را تمرین کنید و فهرست وضعیتها را کنار دست نگه دارید. برای پیشگیری از Pendingهای ناشی از منابع و OOMKilled، تنظیم requests، limits و HPA را بخوانید و اگر هنوز مانیفستها را مینویسید، راهنمای Deployment، Service و Ingress نقطهی شروع است.
پرسشهای متداول
اولین دستوری که باید برای یک Pod مشکلدار بزنم چیست؟
kubectl describe pod <name> و بخش Events انتهای خروجی. بیشتر خطاها (نبود منابع، خطای دانلود ایمیج، شکست probe) همانجا با پیام روشن نوشته میشوند. بعد سراغ kubectl logs بروید.فرق ErrImagePull و ImagePullBackOff چیست؟
لاگ Podی که مدام ریاستارت میشود را چطور ببینم؟
kubectl logs <pod> --previous لاگ اجرای قبلی (کانتینر کرشکرده) را میخوانید. لاگ اجرای فعلی اغلب خالی یا ناقص است، چون تازه شروع شده.وقتی ایمیج shell ندارد چطور داخل Pod دیباگ کنم؟
kubectl debug -it pod/<name> --image=busybox --target=<container> یک کانتینر موقت (ephemeral) کنار کانتینر اصلی اضافه میشود که فضای نام فرایندها را به اشتراک میگذارد و میتوانید با ابزار خودتان بررسی کنید.