דלגו לתוכן

PVC, StorageClass ו-probes

PVC ו-StorageClass: default מול בשם

Section titled “PVC ו-StorageClass: default מול בשם”

PVC מבקש גודל ו-StorageClass. ה-StorageClass יודע ליצור את ה-PV. אם ב-PVC לא כתוב storageClassName, Kubernetes משתמש ב-StorageClass שמסומן כ-default — ואם אין כזה, ה-PVC נשאר בלי class ולא נקשר.

runs on: VM
kubectl get sc
example: kubectl get sc (lab VM)
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
course-hostpath kubernetes.io/no-provisioner Retain WaitForFirstConsumer false 26d
course-local-path rancher.io/local-path Delete WaitForFirstConsumer false 26d
  • ב-class שמסומן default מופיע (default) ליד השם. כאן אין — לכן חייבים לציין class בשם ב-values: storage.className: course-local-path.
  • course-local-path: יוצר PV דינמית (provisioner). course-hostpath: no-provisioner — צריך PV שנוצר ידנית.
  • RECLAIMPOLICY: Delete — מחיקת ה-PVC מוחקת את ה-data; Retain — ה-PV נשאר.

עם VOLUMEBINDINGMODE: WaitForFirstConsumer ה-PVC נשאר Pending עד שמופיע Pod שמשתמש בו. זה נורמלי, לא תקלה. אם ה-PVC Pending וגם ה-Pod שלו Pending, הבעיה היא במקום אחר — בדרך כלל ב-class.

Pod Pending בגלל PVC: סולם האבחון

Section titled “Pod Pending בגלל PVC: סולם האבחון”

המקרה האמיתי: App Degraded, postgres-0 ב-Pending, ו-signal-processor ב-CrashLoopBackOff (כי אין DB).

runs on: VM
kubectl -n argocd get applications # 1. which App is Degraded
kubectl -n <NS> get pods # 2. which Pod is stuck
kubectl -n <NS> describe pod postgres-0 # 3. read Events
kubectl -n <NS> get pvc # 4. PVC state, STORAGECLASS column
kubectl get sc # 5. does the class exist, is it default

מה רואים בכל שלב:

שלבמה רואיםמשמעות
1App Degradedמשהו ברמת האובייקטים, לא ב-render
2postgres-0 0/1 Pendingה-Pod לא שובץ
3pod has unbound immediate PersistentVolumeClaimsה-PVC לא נקשר
4postgres-data-postgres-0 Pending, עמודת STORAGECLASS ריקהל-PVC אין class
5course-local-path קיים, לא defaultאף אחד לא נותן class אוטומטית
file: gitops/apps/postgres/base.yaml (storage block)
storage:
className: course-local-path
requestedSize: 1Gi

אחרי הוספת className: sync נכשל על volumeClaimTemplates

Section titled “אחרי הוספת className: sync נכשל על volumeClaimTemplates”

ה-StatefulSet כבר קיים עם ה-volumeClaimTemplates הישן, והשדה immutable. Argo נכשל עם:

example: Argo sync error
StatefulSet.apps "postgres" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden

התיקון: למחוק את ה-StatefulSet ואת ה-PVC שלו. Argo יוצר מחדש את שניהם מ-Git, והפעם עם ה-class.

runs on: VM
kubectl -n <NS> get pvc # 1. name of the PVC, STATUS, STORAGECLASS
kubectl -n <NS> delete statefulset <SERVICE> --dry-run=client
kubectl -n <NS> delete statefulset <SERVICE> # TRIDENT: <SERVICE> = postgres
kubectl -n <NS> delete pvc <PVC> --dry-run=client
kubectl -n <NS> delete pvc <PVC> # TRIDENT: postgres-data-postgres-0
kubectl -n <NS> get pvc,pods -w # Ctrl+C when Bound / Running
  • מוחקים StatefulSet + PVC, לא את ה-Pod ולא את ה-StorageClass (course-local-path נשאר).
  • אם ה-sync כבר נכשל אחרי retries ×5, Argo לא ינסה שוב אותו revision: manual sync.

איך מוודאים: get pvc — Bound ו-STORAGECLASS = course-local-path; postgres-0 — 1/1 Running; ה-App Synced/Healthy.

prod: אם התיקון ב-Git נכנס לפני ה-sync הראשון, אין StatefulSet ואין PVC. אין מה למחוק; ה-PVC נוצר ישר עם ה-class (כך קרה ב-prod).

הערה: storage: {} (כמו ב-redis) משאיר volume זמני — ה-data נעלם עם ה-Pod. לפי ה-contract, postgres דורש storage מתמשך.

StatefulSet מול Deployment: מתי מוחקים Pod ומתי StatefulSet

Section titled “StatefulSet מול Deployment: מתי מוחקים Pod ומתי StatefulSet”

שני מקרים שנראים דומים והם שונים לגמרי:

מצבמה קורהמה עושים
Pod של StatefulSet שבור, ותיקנת את ה-template (למשל mountPath)ה-rolling update מחכה שה-Pod הישן יהיה Ready, אז Pod שבור לא מוחלף לעולםkubectl -n <NS> delete pod <POD>: ה-StatefulSet יוצר אותו מחדש עם ה-spec החדש
שינוי ב-volumeClaimTemplatesהשדה immutable: ה-sync נכשללמחוק StatefulSet + PVC (הסעיף למעלה)
  • template מותר לשינוי, לכן אין מחיקת StatefulSet: רק Pod.
  • Deployment מחליף Pods לבד: ה-Pod הישן יורד אחרי שהחדש Ready. אל תמחק אותם ידנית.
runs on: VM
kubectl -n <NS> delete pod postgres-0 # StatefulSet only, <POD> = postgres-0
kubectl -n <NS> rollout status sts/<SERVICE> # TRIDENT: postgres

איך מוודאים: get pods — ה-Pod החדש 1/1, ו-describe pod מראה את ה-mountPath/image החדש.

ל-Kubernetes שלושה סוגי בדיקות. ב-TRIDENT כל השירותים חושפים /live ו-/ready (ops או http).

probeשואלכשנכשלנתיב ב-TRIDENT
startupProbeהאם האפליקציה סיימה לעלות?ה-container נהרג ומופעל מחדש (אחרי failureThreshold); עד שעוברת, live ו-ready מושהים/live
livenessProbeהאם התהליך חי ולא תקוע?ה-container נהרג ומופעל מחדש/live
readinessProbeהאם מוכן לקבל בקשות?ה-Pod מוסר מה-endpoints של ה-Service; לא נהרג/ready
file: gitops/apps/trident/base.yaml (probes of one container)
startupProbe: {httpGet: {path: /live, port: ops}, periodSeconds: 5, failureThreshold: 12}
livenessProbe: {httpGet: {path: /live, port: ops}, periodSeconds: 10, failureThreshold: 6}
readinessProbe: {httpGet: {path: /ready, port: ops}, periodSeconds: 10, failureThreshold: 6}
  • port מתייחס לשם הפורט שב-ports: של ה-container (ops/http). שם שגוי — ה-probe נכשל תמיד.
  • זמן הסבלנות של ה-startup: periodSeconds × failureThreshold = 5 × 12 = 60 שניות.

READY 0/1 עם STATUS Running אומר שה-readiness נכשל. ב-TRIDENT, /ready מחזיר 503 כשתלות (redis/postgres) לא זמינה — by design: ה-Pod חי, אבל לא ראוי לתעבורה.

runs on: VM
kubectl -n <NS> get pods
kubectl -n <NS> describe pod -l trident.dev/service=<SERVICE> # Events: "Readiness probe failed: HTTP probe failed with statuscode: 503"
kubectl -n <NS> logs deploy/<SERVICE> --tail=30 # which dependency is down
kubectl -n <NS> get endpointslices -l kubernetes.io/service-name=<SERVICE> # empty while not Ready

איך מוודאים: הלוג אומר איזו תלות חסרה (REDIS_HOST שגוי, postgres לא עלה). אחרי שהתלות חוזרת, ה-Pod הופך 1/1 בלי הפעלה מחדש.

מצבסיבה סבירהבדיקה
Running, 0/1readiness נכשל (תלות למטה)describe Events + logs
CrashLoopBackOffliveness נכשל / האפליקציה מתרסקתlogs --previous
restarts עולים בלי קריסהstartup/liveness איטיים מדיdescribe — Liveness probe failed

טבלת symptom → cause מלאה: debugging/symptoms.