🌳
pt0/deployF/k8sF/podPendingStatusAI.mts
1import type { V1Pod } from '@kubernetes/client-node'
4export const pendingTimeoutMs = 90 * 1000 // 90s for pods stuck in Pending (scheduling issues)
5export const pvcPendingTimeoutMs = 180 * 1000 // 180s for PVC binding (dynamic provisioning can be slow)
7type PendingReason = {reason: string, message: string, isPvcPending: boolean}
9export const getPendingReason = (pod: V1Pod | undefined): PendingReason | null => {
10 if (!pod || pod.status?.phase !== 'Pending') return null
11 const conditions = pod.status?.conditions || []
12 const unschedulable = conditions.find(c => c.type === 'PodScheduled' && c.status === 'False')
13 if (!unschedulable) return null
14 const message = unschedulable.message || ''
15 return {reason: unschedulable.reason || 'Unknown', message, isPvcPending: message.includes('unbound immediate PersistentVolumeClaim')}
18type InitContainerInfo = {name: string, status: string, detail?: string}
20export const getInitContainerStatus = (pod: V1Pod | undefined): InitContainerInfo | null => {
21 if (!pod) return null
22 for (const cs of pod.status?.initContainerStatuses || []) {
23 assertDefined(cs.name)
24 const waiting = cs.state?.waiting
25 if (waiting) return {name: cs.name, status: 'waiting', detail: waiting.reason}
26 if (cs.state?.running) return {name: cs.name, status: 'running'}
27 if (cs.state?.terminated?.exitCode !== 0) return {name: cs.name, status: 'failed', detail: cs.state?.terminated?.reason}
28 }
29 return null