0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Kubernetes Pod启动失败的各种场景及其排障方法

马哥Linux运维 来源:马哥Linux运维 2026-04-13 13:53 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

背景

在 Kubernetes 日常运维中,Pod 起不来是最常见的故障形态之一。很多运维工程师看到 Pod 状态不是Running时,第一反应是盯着kubectl get pod的STATUS列反复查看,或者反复执行kubectl describe pod期待找到答案。殊不知,Pod 的非 Running 状态有几十种,每种状态的根因和处理方法完全不同。

本文以 Kubernetes 1.32(2026 年主流版本)为基础,系统讲解 Pod 启动失败的各种场景及其排障方法。内容覆盖 Pod 生命周期的完整解析、容器镜像相关问题、资源不足导致的调度失败、存储挂载异常、网络配置问题、以及使用 kubectl 和 crictl 工具进行深度排障的技巧。

前置知识要求:了解 Kubernetes 基本概念(Pod、Deployment、Service、Namespace)、熟悉 kubectl 基础命令、了解 Docker/容器基础知识。

1. Pod 生命周期与状态解析

1.1 Pod 生命周期阶段

Pod 的生命周期分为多个阶段(phase),通过status.phase字段表示:

# kubectl get pod -o yaml 中的 Pod 状态
status:
phase:Running# Pending | Running | Succeeded | Failed | Unknown
conditions:
 -type:Initialized  # 初始化容器是否完成
  status:"True"
 -type:Ready     # Pod 是否可以接收流量
  status:"True"
 -type:ContainersReady # 所有容器是否就绪
  status:"True"
 -type:PodScheduled  # 是否已调度到节点
  status:"True"

Phase 与 Conditions 的关系:

Pending+PodScheduled=False→ 调度失败

Pending+Initialized=False→ 初始化容器失败

Pending+ContainersReady=False→ 容器启动失败

Running+Ready=False→ 存活探针失败

Failed→ 容器进程退出且未配置 restartPolicy

1.2 Pod 状态快速诊断

#!/bin/bash
# k8s_pod_status_diag.sh
# Pod 状态快速诊断脚本

POD_NAME="${1:-}"
NAMESPACE="${2:-default}"

if[ -z"$POD_NAME"];then
 echo"用法:$0 [命名空间]"
 exit1
fi

echo"========================================"
echo"Pod 状态诊断"
echo"Pod:$POD_NAME"
echo"命名空间:$NAMESPACE"
echo"时间:$(date '+%Y-%m-%d %H:%M:%S')"
echo"========================================"
echo""

# 获取 Pod 概要信息
echo"【Pod 概要】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o wide
echo""

# 获取 Pod 详细信息
echo"【Pod 详细状态】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o yaml | grep -A 20"status:"
echo""

# 获取最近事件
echo"【相关事件】"
kubectl get events -n"$NAMESPACE"
  --field-selector involvedObject.name="$POD_NAME"
  --sort-by='.lastTimestamp'| tail -20
echo""

# 获取容器状态
echo"【容器状态】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.status.containerStatuses[*]}'| python3 -m json.tool 2>/dev/null || 
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.status.containerStatuses}'
echo""

# 检查容器重启次数
echo"【容器重启统计】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.status.containerStatuses[*].restartCount}'
echo""

1.3 常见 Pod 状态速查

STATUS 含义 常见根因
Pending Pod 已创建但未调度到节点 资源不足、节点选择器不匹配、调度器故障
ContainerCreating 容器正在创建中 镜像拉取中、存储挂载中
Running 容器已启动 但需检查Ready状态和探针
CrashLoopBackOff 容器反复崩溃重启 应用启动失败、配置错误、资源不足
ImagePullBackOff 镜像拉取失败 镜像不存在、认证失败、网络不通
ErrImagePull 镜像拉取错误 同上,但处于早期阶段
Evicted Pod 被驱逐 资源压力、节点 drain
Terminating 正在删除 finalizers 未完成、force kill 失败
Unknown 无法获取 Pod 状态 节点网络问题、API Server 连接问题

2. 镜像相关问题

2.1 镜像拉取失败的常见原因

镜像相关问题是 Pod 启动失败最常见的原因之一。ImagePullBackOff和ErrImagePull是两个典型的镜像拉取失败状态。

# 查看 Pod 事件中的镜像相关错误
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 5"ImagePull"

# 示例输出:
# Warning Failed   45s (x4 over 2m)  kubelet      Error: ImagePullBackOff
# Warning Failed   45s         kubelet      Failed to pull image "myregistry.com/myapp:v1":
#                  rpc error: code = Unknown desc = failed to pull and unpack image

# 查看详细的拉取错误
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 10"Warning"

镜像名称拼写错误:

# 错误示例:镜像名拼写错误
# kubectl run myapp --image=myap:v1 # 拼写错误,应该是 myapp

# 正确做法:使用完整的镜像路径
kubectl run myapp --image=registry.example.com/myorg/myapp:v1.0.0

私有镜像认证问题:

# 创建 Secret 保存仓库认证信息
kubectl create secret docker-registry myregistry-secret 
  --docker-server=registry.example.com 
  --docker-username=admin 
  --docker-password=StrongPassword2026! 
  --docker-email=admin@example.com 
  -n mynamespace

# 在 Pod 中引用 Secret
kubectl get pod myapp-abc123 -o yaml | kubectl replace --force -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: myapp-abc123
spec:
  imagePullSecrets:
  - name: myregistry-secret
  containers:
  - name: myapp
    image: registry.example.com/myorg/myapp:v1.0.0
EOF

# 或在 ServiceAccount 中关联(影响该 SA 下所有 Pod)
kubectl patch serviceaccount default 
    -p '{"imagePullSecrets":[{"name":"myregistry-secret"}]}' 
    -n mynamespace

镜像 tag 指向错误:

# 使用 latest tag 的风险
# latest 指向的镜像可能随时变化,导致部署不确定性

# 正确做法:使用不可变的 tag(版本号、commit hash、时间戳)
# good: myapp:v1.2.3
# good: myappabc123...
# good: myapp:2026-04-10
# bad: myapp:latest

2.2 镜像预热与拉取策略

#!/bin/bash
# preload_images.sh
# 节点镜像预热脚本(减少 Pod 启动时间)

set-euo pipefail

IMAGES=(
 "registry.example.com/myorg/base:v1.0"
 "registry.example.com/myorg/app:v2.1"
 "registry.example.com/myorg/nginx:alpine"
)

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1"
}

forimagein"${IMAGES[@]}";do
 log"预热镜像:$image"
  docker pull"$image"
done

log"镜像预热完成"

imagePullPolicy 配置:

# 镜像拉取策略
spec:
containers:
-name:myapp
 image:myapp:v1.0
 imagePullPolicy:Always# Always | IfNotPresent | Never

# 策略说明:
# Always: 每次启动都拉取镜像(默认用于 :latest tag)
# IfNotPresent: 本地存在则使用本地,不存在则拉取(默认用于指定 tag)
# Never: 从不拉取,仅使用本地镜像

2.3 镜像健康检查脚本

#!/bin/bash
# check_images.sh
# 检查集群中所有节点使用的镜像

set-euo pipefail

NAMESPACE="${1:-}"

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1"
}

get_images_from_nodes() {
  kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.containerRuntimeVersion}'
}

get_pod_images() {
 if[ -n"$NAMESPACE"];then
    kubectl get pods -n"$NAMESPACE"-o jsonpath='{range .items[*]}{.spec.containers[*].image}{"
"}{end}'| sort | uniq
 else
    kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"
"}{end}'| sort | uniq
 fi
}

log"===== 所有 Pod 使用的镜像 ====="
get_pod_images

log"===== 节点信息 ====="
kubectl get nodes -o wide

log"===== 镜像 Pod 分布 ====="
forimagein$(get_pod_images);do
  count=$(kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"
"}{end}'| grep -c"$image"||echo"0")
 log"$image:$count个 Pod"
done

3. 资源不足与调度失败

3.1 调度失败的表现

Pod 处于Pending状态且PodScheduled=False,通常是调度失败或资源不足。

# 查看调度失败的原因
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 20"Events:"
# 典型输出:
# Events:
#  Type   Reason      Age  From      Message
#  ----   ------      ---- ----      -------
#  Warning FailedScheduling 32s  default-scheduler 0/5 nodes are available:
#                    3 Insufficient memory, 2 node(s) had taints that the pod didn't tolerate.

# 查看节点资源状态
kubectl describe nodes | grep -A 5"Allocated resources"
# Allocated resources:
#  Resource      Requests   Limits
#  cpu        2500m (62%)  6 (150%)
#  memory       4Gi (80%)   8Gi (160%)

3.2 资源请求与限制

# 查看 Pod 的资源请求和限制
kubectl get pod myapp-abc123 -n mynamespace -o jsonpath='{.spec.containers[*].resources}'
# {"limits":{"cpu":"500m","memory":"256Mi"},"requests":{"cpu":"250m","memory":"128Mi"}}

资源请求(requests)vs 资源限制(limits):

requests:调度时使用的资源量,节点必须满足 requests 才能调度

limits:容器运行时的资源上限,超出 limits 会被限制(CPU)或 OOM Kill(内存)

# 典型的资源配置
apiVersion:v1
kind:Pod
metadata:
name:myapp
spec:
containers:
-name:myapp
 image:myapp:v1
 resources:
  requests:
   cpu:"250m"   # 0.25 核 CPU
   memory:"128Mi" # 128 MB 内存
  limits:
   cpu:"1000m"   # 最多 1 核 CPU
   memory:"512Mi"  # 最多 512 MB 内存

3.3 调度失败排查脚本

#!/bin/bash
# k8s_scheduler_diag.sh
# Kubernetes 调度失败诊断脚本

set-euo pipefail

NAMESPACE="${1:-default}"

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1"
}

echo"===== 调度失败的 Pod ====="
kubectl get pods -n"$NAMESPACE"--field-selector=status.phase=Pending -o wide
echo""

echo"===== 节点资源概览 ====="
kubectl top nodes 2>/dev/null ||echo"metrics-server 未安装或不可用"
echo""

echo"===== 各节点已分配资源 ====="
kubectl describe nodes | grep -A 10"Allocated resources"
echo""

echo"===== 存在资源不足的 Pod 事件 ====="
forpodin$(kubectl get pods -n"$NAMESPACE"--field-selector=status.phase=Pending -o name);do
 echo"---$pod---"
  kubectl describe"$pod"-n"$NAMESPACE"| grep -E"(Insufficient|FailedScheduling|tolerations)"| head -5
done
echo""

echo"===== 节点污点情况 ====="
kubectl get nodes -o custom-columns=NODE:.metadata.name,TAINTS:.spec.taints
echo""

echo"===== 未调度的 Pod 及原因 ====="
kubectl get pods -n"$NAMESPACE"--field-selector=status.phase=Pending -o jsonpath='{range .items[*]}{.metadata.name}{"	"}{.status.conditions[?(@.type=="PodScheduled")].reason}{"
"}{end}'

3.4 资源不足的解决方案

# 方案1: 扩容节点
kubectl scale deployment myapp --replicas=3

# 方案2: 降低 Pod 资源请求
kubectl patch deployment myapp -p'{
  "spec": {
    "template": {
      "spec": {
        "containers":[{
          "name": "myapp",
          "resources": {
            "requests": {
              "cpu": "100m",
              "memory": "64Mi"
            }
          }
        }]
      }
    }
  }
}'

# 方案3: 驱逐低优先级 Pod(为高优先级 Pod 腾出空间)
kubectl get pods --sort-by='.spec.priority'-n"$NAMESPACE"

# 方案4: 添加新节点(配合集群自动扩缩容)
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Node
metadata:
  name: new-node
spec:
  providerID: aws:///i-xxxxx
EOF

# 方案5: 调整 Pod 优先级
kubectl patch deployment myapp -p '{
    "spec": {
        "template": {
            "spec": {
                "priorityClassName": "high-priority"
            }
        }
    }
}'

3.5 污点与容忍诊断

#!/bin/bash
# k8s_taint_diag.sh
# 污点与容忍诊断脚本

set-euo pipefail

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1"
}

log"===== 节点污点 ====="
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"
"}{range .spec.taints[*]} - {.key}={.effect} (Added by {.addedBy}){"
"}{end}{"
"}{end}'
echo""

log"===== Pod 容忍 ====="
kubectl get pods -A -o custom-columns=
NAMESPACE:.metadata.namespace,
NAME:.metadata.name,
TOLERATIONS:.spec.tolerations
echo""

log"===== 无法调度的 Pod(污点原因)====="
forpodin$(kubectl get pods -A --field-selector=status.phase=Pending -o name);do
  reason=$(kubectl get"$pod"-o jsonpath='{.status.conditions[?(@.type=="PodScheduled")].reason}')
  msg=$(kubectl get"$pod"-o jsonpath='{.status.conditions[?(@.type=="PodScheduled")].message}')
 ifecho"$msg"| grep -qi"taint";then
   echo"$pod:$reason-$msg"
 fi
done

4. 存储挂载异常

4.1 存储相关问题

Pod 启动时需要挂载 PersistentVolume(PV)或配置映射(ConfigMap)、密钥(Secret)。存储问题会导致 Pod 停留在ContainerCreating状态。

# 查看存储挂载相关错误
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 10"MountPropagation"
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 5"VolumeMount"
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 10"Volumes:"

# 常见错误:
# "MountVolume.SetUp failed" - 卷挂载失败
# "Unable to attach or mount volumes" - 无法挂载卷
# "multi-attach error" - 卷被多个 Pod 同时挂载

4.2 PVC 状态诊断

#!/bin/bash
# k8s_pvc_diag.sh
# PVC 状态诊断脚本

set-euo pipefail

NAMESPACE="${1:-default}"

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1"
}

log"===== PVC 状态 ====="
kubectl get pvc -n"$NAMESPACE"
echo""

log"===== PVC 详细信息 ====="
kubectl describe pvc -n"$NAMESPACE"
echo""

log"===== PVC 绑定状态为 Pending 的 Pod ====="
kubectl get pods -n"$NAMESPACE"-o jsonpath='{range .items[*]}
Pod: {.metadata.name}
Status: {.status.phase}
Conditions: {.status.conditions[?(@.type=="PodScheduled")].reason}
Volumes: {.spec.volumes[*].name}
{"
"}{end}'| grep -A 3"Status: Pending"
echo""

log"===== StorageClass 信息 ====="
kubectl get storageclass
kubectl describe storageclass
echo""

log"===== 检查 PV 状态 ====="
kubectl get pv
kubectl describe pv

4.3 ConfigMap 和 Secret 问题

# 查看 ConfigMap 相关错误
kubectl describe pod myapp-abc123 | grep -A 5"ConfigMap"

# 查看 Secret 相关错误
kubectl describe pod myapp-abc123 | grep -A 5"Secret"

# 检查 ConfigMap 是否存在
kubectl get configmap myconfig -n mynamespace

# 检查 Secret 是否存在
kubectl get secret mysecret -n mynamespace

# 检查引用的 ConfigMap/Secret 版本
kubectl get pod myapp-abc123 -o jsonpath='{.spec.volumes[*].configMap.name}'
kubectl get pod myapp-abc123 -o jsonpath='{.spec.volumes[*].secret.secretName}'

# ConfigMap 更新后强制 Pod 重新加载(通常需要重启 Pod)
kubectl rollout restart deployment myapp -n mynamespace

# 或手动删除 Pod 触发重建
kubectl delete pod myapp-abc123 -n mynamespace

4.4 HostPath 问题

# HostPath 卷问题排查
kubectl describe pod myapp-abc123 | grep -A 10"HostPath"

# 检查宿主机路径是否存在
kubectl get pod myapp-abc123 -o jsonpath='{.spec.volumes[*].hostPath.path}'
# 例如:/data/logs

# 在节点上检查
# kubectl exec -it myapp-abc123 -n mynamespace -- sh
# 在节点上检查:
# ls -la /data/logs

# 常见 HostPath 问题:
# 1. 路径不存在
# 2. 路径存在但权限不足
# 3. 路径是文件而非目录

5. 网络配置问题

5.1 网络相关问题表现

Pod 处于ContainerCreating状态但不是网络插件( CNI)问题,就是 Service/NetworkPolicy 配置问题。

# 查看 CNI 相关错误
kubectl describe pod myapp-abc123 -n mynamespace | grep -A 5"NetworkPlugin"
kubectl describe pod myapp-abc123 -n mynamespace | grep -i"cni|network"

# 查看 Pod IP 分配情况
kubectl get pod myapp-abc123 -n mynamespace -o jsonpath='{.status.podIP}'
kubectl get pod myapp-abc123 -n mynamespace -o jsonpath='{.status.podIPs}'

5.2 DNS 问题排查

DNS 是 Kubernetes 网络中最容易出问题的环节之一。

#!/bin/bash
# k8s_dns_diag.sh
# DNS 问题诊断脚本

set-euo pipefail

POD_NAME="${1:-}"
NAMESPACE="${2:-default}"

if[ -z"$POD_NAME"];then
 echo"用法:$0 [命名空间]"
 exit1
fi

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1"
}

log"===== 检查 Pod DNS 配置 ====="
kubectlexec-it"$POD_NAME"-n"$NAMESPACE"-- cat /etc/resolv.conf
echo""

log"===== 测试 DNS 解析 ====="
kubectlexec-it"$POD_NAME"-n"$NAMESPACE"-- nslookup kubernetes.default 2>&1 | head -5
kubectlexec-it"$POD_NAME"-n"$NAMESPACE"-- nslookup google.com 2>&1 | head -5
echo""

log"===== 测试网络连通性 ====="
kubectlexec-it"$POD_NAME"-n"$NAMESPACE"-- ping -c 3 8.8.8.8
echo""

log"===== 查看 CoreDNS Pod 状态 ====="
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=20
echo""

log"===== CoreDNS 配置 ====="
kubectl get configmap coredns -n kube-system -o yaml

5.3 Service 和 Endpoint 问题

# 查看 Service 关联的 Endpoints
kubectl get endpoints myapp-service -n mynamespace

# 如果 Endpoints 为空,说明没有 Pod 匹配 Service 的 selector
kubectl describe service myapp-service -n mynamespace | grep -A 5"Selector"

# 检查 Pod 是否匹配 Service Selector
kubectl get pods -n mynamespace -l app=myapp --show-labels

# 端到端连通性测试
kubectlexec-ittest-pod -n mynamespace -- wget -qO- http://myapp-service.mynamespace.svc.cluster.local:8080/health

5.4 网络策略问题

# 查看 Pod 的网络策略
kubectl get networkpolicy -A

# 检查特定 Pod 是否被 NetworkPolicy 限制
kubectl describe pod myapp-abc123 -n mynamespace | grep -i"policy"

# 测试 Pod 间网络(从测试 Pod 访问目标 Pod)
kubectl runtest-pod --image=busybox:1.36 -n mynamespace --restart=Never --rm -it -- wget -qO- http://myapp-service.mynamespace.svc.cluster.local:8080/

6. 深度排障工具

6.1 kubectl debug 高级用法

Kubernetes 1.20+ 提供了kubectl debug命令,可以在不修改 Pod 的情况下进行调试。

# 在 Pod 所在节点上启动调试容器
kubectl debug myapp-abc123 -n mynamespace -it --image=busybox:1.36 --share-processes --copy-to=myapp-debug

# 查看调试容器的 Shell
kubectlexec-it myapp-debug -n mynamespace -- sh

# 复制 Pod 的网络命名空间进行调试
kubectl debug myapp-abc123 -n mynamespace --image=busybox:1.36 -it --container=myapp --copy-to=myapp-netdebug

# 检查节点级别问题(节点调试)
kubectl debug node/my-node -it --image=busybox:1.36
# 在节点 shell 中执行:
# ls /var/log/pods/
# crictl ps
# crictl logs 

6.2 crictl 工具

crictl 是 container runtime interface(CRI)的 CLI 工具,用于直接与 containerd 或 CRI-O 交互。当 kubectl 无法访问时(如节点网络故障),crictl 是最后一道排障手段。

# 查看容器列表
crictl ps -a

# 查看镜像列表
crictl images

# 查看容器日志
crictl logs 

# 查看容器详细信息
crictl inspect 

# 进入容器(如果支持 exec)
crictlexec-it  sh

# 查看容器挂载
crictl inspect  | grep -A 20"mounts"

# 重启容器(相当于 kubelet 重建)
crictl stop 
crictl rm 
# 然后删除 Pod,kubelet 会重新创建

# 查看沙箱/pause 容器
crictl pods

# 资源统计
crictl stats

6.3 kubelet 日志分析

# 查看 kubelet 日志(systemd 环境)
journalctl -u kubelet -n 100 --no-pager

# 查看特定 Pod 的 kubelet 日志(按 pod UID 过滤)
journalctl --no-pager | grep -E"podUID|myapp-abc123"

# kubelet 日志中的常见信息
# "Container runtime network not ready" - CNI 未就绪
# "Image garbage collection failed" - 镜像垃圾回收失败
# "Failed to start container" - 容器启动失败
# "Failed to kill pod" - 删除 Pod 失败

# 检查 kubelet 配置
kubectl get cm kubelet-config -n kube-system -o yaml

# 查看 kubelet 服务状态
systemctl status kubelet
systemctl restart kubelet

6.4 完整排障脚本

#!/bin/bash
# k8s_deep_diag.sh
# Kubernetes Pod 深度排障脚本

set-euo pipefail

POD_NAME="${1:-}"
NAMESPACE="${2:-default}"

if[ -z"$POD_NAME"];then
 echo"用法:$0 [命名空间]"
 exit1
fi

RED='�33[0;31m'
GREEN='�33[0;32m'
YELLOW='�33[1;33m'
NC='�33[0m'

log_ok() {echo-e"${GREEN}[OK]${NC}$1"; }
log_warn() {echo-e"${YELLOW}[WARN]${NC}$1"; }
log_error() {echo-e"${RED}[ERROR]${NC}$1"; }

echo"========================================"
echo"Kubernetes Pod 深度排障"
echo"Pod:$POD_NAME"
echo"命名空间:$NAMESPACE"
echo"========================================"

# 1. 基本状态
echo""
echo"【1. Pod 基本状态】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o wide
STATUS=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.status.phase}')
log_ok"Pod Phase:$STATUS"

# 2. 事件分析
echo""
echo"【2. Pod 事件】"
EVENTS=$(kubectl get events -n"$NAMESPACE"
  --field-selector involvedObject.name="$POD_NAME"
  --sort-by='.lastTimestamp'| tail -10)

ifecho"$EVENTS"| grep -qi"error|fail|backoff";then
  log_error"发现错误/失败事件"
fi
echo"$EVENTS"

# 3. 容器状态
echo""
echo"【3. 容器状态】"
CONTAINERS=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{range .status.containerStatuses[*]}
名称: {.name}
状态: {.state}
重启: {.restartCount}
{"
"}{end}')
echo"$CONTAINERS"

# 4. 镜像检查
echo""
echo"【4. 镜像状态】"
IMAGES=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{range .spec.containers[*]}Container: {.name}, Image: {.image}{"
"}{end}')
echo"$IMAGES"

# 5. 资源配置
echo""
echo"【5. 资源请求与限制】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.spec.containers[*].resources}'| python3 -m json.tool

# 6. 节点状态
echo""
echo"【6. 调度的节点】"
NODE=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.spec.nodeName}')
if[ -n"$NODE"];then
  log_ok"节点:$NODE"
  kubectl describe node"$NODE"| grep -A 5"Allocated resources"
  kubectl top node"$NODE"2>/dev/null || log_warn"metrics-server 不可用"
else
  log_error"Pod 未调度到任何节点"
fi

# 7. PVC 挂载
echo""
echo"【7. PVC 挂载】"
PVS=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{range .spec.volumes[*]}{if .persistentVolumeClaim}PVC: {.persistentVolumeClaim.claimName}{"
"}{end}{end}')
if[ -n"$PVS"];then
 echo"$PVS"
 forpvcin$(echo"$PVS"| grep PVC | awk'{print $2}');do
    kubectl get pvc"$pvc"-n"$NAMESPACE"
 done
else
  log_ok"无 PVC 挂载"
fi

# 8. ConfigMap/Secret
echo""
echo"【8. ConfigMap/Secret】"
CM_COUNT=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{len .spec.volumes}'2>/dev/null ||echo"0")
if["$CM_COUNT"-gt 0 ];then
  kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{range .spec.volumes[*]}{.name}: {.configMap.name}{.secret.secretName}{"
"}{end}'
fi

# 9. 网络状态
echo""
echo"【9. 网络状态】"
POD_IP=$(kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.status.podIP}')
log_ok"Pod IP:$POD_IP"

# 10. 存活探针
echo""
echo"【10. 探针配置】"
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.spec.containers[*].livenessProbe}'| python3 -m json.tool 2>/dev/null || 
kubectl get pod"$POD_NAME"-n"$NAMESPACE"-o jsonpath='{.spec.containers[*].readinessProbe}'| python3 -m json.tool

echo""
echo"========================================"
echo"排障完成"
echo"========================================"

7. 常见故障场景与处理

7.1 CrashLoopBackOff

CrashLoopBackOff 表示容器启动后立即崩溃,kubelet 反复尝试重启。

# 查看容器退出原因
kubectl logs myapp-abc123 -n mynamespace --previous

# 查看容器退出码
kubectl get pod myapp-abc123 -n mynamespace -o jsonpath='{.status.containerStatuses[*].lastState.terminated.exitCode}'

# 常见退出码:
# 0: 正常退出(可能是 main 进程提前退出)
# 1: 一般错误(应用崩溃)
# 137: 被 SIGKILL(内存不足或 OOM)
# 139: 段错误(SIGSEGV)
# 143: 优雅退出(SIGTERM)

# 典型原因分析
# 1. 应用启动失败(配置错误、依赖不可用)
# 2. 内存不足被 OOM Kill
# 3. 健康检查失败
# 4. 权限问题

OOM Kill 处理:

# 检查节点是否存在 OOM
dmesg | grep -i"oom"| tail -20

# 检查 Pod 的内存限制
kubectl get pod myapp-abc123 -o jsonpath='{.spec.containers[*].resources.limits.memory}'

# 增加内存限制
kubectl patch deployment myapp -n mynamespace -p'{
  "spec": {
    "template": {
      "spec": {
        "containers":[{
          "name": "myapp",
          "resources": {
            "limits": {"memory": "1Gi"}
          }
        }]
      }
    }
  }
}'

7.2 Init 容器失败

# Init 容器失败会导致主容器永远无法启动
kubectl get pod myapp-abc123 -o jsonpath='{.status.initContainerStatuses}'

# 查看 Init 容器日志
kubectl logs myapp-abc123 -n mynamespace -c my-init-container --previous

# 常见 Init 容器问题:
# 1. Init 容器镜像拉取失败
# 2. Init 容器执行失败(exit code != 0)
# 3. Init 容器超时

# 解决方案
# 1. 检查 Init 容器配置
kubectl get pod myapp-abc123 -o yaml | grep -A 10"initContainers"

# 2. 延长 Init 容器超时时间
kubectl patch deployment myapp -n mynamespace -p'{
  "spec": {
    "template": {
      "spec": {
        "initContainers":[{
          "name": "my-init",
          "resources": {},
          "imagePullPolicy": "IfNotPresent"
        }]
      }
    }
  }
}'

7.3 存活探针失败

# 存活探针失败会导致 Pod 被重启
kubectl describe pod myapp-abc123 | grep -A 5"Liveness"

# 临时禁用探针进行测试
kubectl run myapp-test --image=myapp:v1 --restart=Never -- 
  /bin/sh -c"sleep 3600"

# 常见探针问题:
# 1. 探针路径错误(应用未提供 /health 端点)
# 2. 探针端口错误
# 3. 应用启动过慢(需要 initialDelaySeconds)
# 4. 探针超时时间过短

# 调整探针配置
kubectl patch deployment myapp -n mynamespace -p'{
  "spec": {
    "template": {
      "spec": {
        "containers":[{
          "name": "myapp",
          "livenessProbe": {
            "httpGet": {"path": "/health", "port": 8080},
            "initialDelaySeconds": 30,
            "periodSeconds": 10,
            "failureThreshold": 3
          }
        }]
      }
    }
  }
}'

7.4 Evicted(被驱逐)

Pod 被驱逐通常是因为节点资源压力或运维操作。

# 查看被驱逐的 Pod
kubectl get pods -n mynamespace --field-selector=status.phase=Failed | grep Evicted

# 驱逐原因
kubectl describe pod myapp-abc123 | grep -A 3"Reason: Evicted"

# 常见驱逐原因:
# 1. 节点内存压力 (MemoryPressure)
# 2. 节点磁盘压力 (DiskPressure)
# 3. 节点 PID 压力 (PIDPressure)
# 4. 运维主动驱逐 (kubectl drain)

# 处理:删除被驱逐的 Pod,Deployment 会创建新的
kubectl delete pod myapp-abc123 -n mynamespace --grace-period=0 --force

# 检查节点资源状态
kubectl describe node | grep -E"MemoryPressure|DiskPressure|PIDPressure|Conditions"

7.5 Terminating 状态卡住

Pod 删除后一直处于Terminating状态。

# 查看 Terminating 原因
kubectl describe pod myapp-abc123 | grep -A 10"Conditions"

# 常见原因:
# 1. Finalizers 未完成
# 2. 存储卷未卸载
# 3. 网络插件问题
# 4. 容器未响应 SIGTERM

# 强制删除(谨慎使用)
kubectl delete pod myapp-abc123 -n mynamespace --grace-period=0 --force

# 检查 finalizers
kubectl get pod myapp-abc123 -o jsonpath='{.spec.finalizers}'

# 如果是 finalizers 问题,移除 finalizers
kubectl patch pod myapp-abc123 -n mynamespace -p'{"metadata":{"finalizers":[]}}'--type=merge

# 检查 NFS 等存储挂载是否卡住
mount | grep nfs

8. 排障流程图与总结

8.1 Pod 排障决策树

Pod 状态不是 Running?
  │
  ├── Pending
  │  ├── 检查 kubectl describe pod Events
  │  │  ├──"FailedScheduling"→ 资源不足/调度失败 → 参见调度诊断
  │  │  ├──"Unschedulable"→ 资源不足 → 增加节点或减少请求
  │  │  └──"didn't have free ports"→ 端口冲突
  │  └── kubectl get events --field-selector involvedObject.name=
  │
  ├── ContainerCreating
  │  ├── 检查 kubectl describe pod
  │  │  ├──"ImagePullBackOff"→ 镜像拉取失败 → 检查镜像地址/认证
  │  │  ├──"ErrImagePull"→ 同上,早期阶段
  │  │  ├──"MountVolume.SetUp failed"→ 存储问题 → 检查 PVC/PV
  │  │  └──"NetworkPlugin"→ CNI 问题 → 检查网络插件
  │  └── crictl ps -a 查看容器状态
  │
  ├── CrashLoopBackOff
  │  ├── kubectl logs  --previous 查看崩溃日志
  │  ├── 检查退出码
  │  │  ├── 137 → 内存不足 OOM
  │  │  ├── 1 → 应用错误
  │  │  └── 0 → 进程正常退出但不应该退出
  │  └── 检查资源限制和实际使用
  │
  ├── ImagePullBackOff
  │  ├── 检查镜像名称是否正确
  │  ├── 检查 imagePullSecrets 是否配置
  │  ├── 手动测试 docker pull 镜像
  │  └── 检查私有仓库认证
  │
  ├── Running 但 Ready=False
  │  ├── 检查存活探针和就绪探针
  │  ├── kubectl logs 查看探针路径
  │  └── 检查应用 /health 端点
  │
  ├── Evicted
  │  ├── 检查节点资源状态
  │  └── 重新调度 Pod
  │
  └── Terminating 卡住
    ├── 检查 finalizers
    ├── 检查存储挂载
    └── 强制删除

8.2 核心排障命令速查

# Pod 基本信息
kubectl get pod  -o wide
kubectl describe pod 
kubectl get pod  -o yaml

# 日志
kubectl logs  --tail=100
kubectl logs  --previous # 上一次运行的日志

# 事件
kubectl get events -n  --field-selector involvedObject.name= --sort-by='.lastTimestamp'

# 资源使用
kubectl top pod 
kubectl top node 

# 调度
kubectl get pods -n  --field-selector=status.phase=Pending

# 存储
kubectl get pvc -n 
kubectl describe pvc 

# 网络
kubectl get svc -n 
kubectl get endpoints  -n 

# 节点级调试
kubectl debug  -it --image=busybox -- sh
crictl ps -a
crictl logs 
journalctl -u kubelet -n 50 --no-pager

8.3 预防措施

资源配置合理:requests 和 limits 根据实际负载设置,避免资源耗尽和 OOM

镜像预热:在 Pod 调度前预先拉取镜像,减少启动时间

健康检查合理:探针路径、端口、超时时间需与应用实际情况匹配

监控告警:对 Pod 非 Running 状态设置告警,及时发现问题

定期演练模拟各类故障,验证排障流程的有效性

9. 总结

Pod 启动失败是 Kubernetes 运维中最常见的故障形态,但并非所有非 Running 状态都需要紧急处理。运维工程师需要建立系统的排障思路:

首先确认状态:通过kubectl get pod确认 Pod 的实际状态和所属阶段

其次查看事件:通过kubectl describe pod的 Events 部分获取第一手错误信息

然后定位根因:根据事件中的 Reason 和 Message 判断问题类别(镜像、资源、存储、网络、探针)

最后实施修复:根据根因选择对应的修复方案,并验证结果

本文覆盖了从基础状态诊断到深度节点级排障的完整工具链。在实际工作中,建议运维团队将这些脚本整理成工具库,配合监控告警形成完整的故障响应体系。

本文基于 Kubernetes 1.32、containerd 2.0、crictl 1.32 环境编写,测试于 Ubuntu 24.04 LTS 和 CentOS Stream 9。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    535

    浏览量

    23024
  • Docker
    +关注

    关注

    0

    文章

    537

    浏览量

    14393
  • kubernetes
    +关注

    关注

    0

    文章

    273

    浏览量

    9530

原文标题:Pod 一直起不来,运维排障别只会盯着 Running

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Kubernetes的Device Plugin设计解读

    ,无需修改Kubelet主干代码,就可以实现支持GPU、FPGA、高性能 NIC、InfiniBand 等各种设备的扩展。该能力在Kubernetes 1.8和1.9版本处于Alpha版本,在1.10会
    发表于 03-12 16:23

    阿里云容器Kubernetes监控(二) - 使用Grafana展现Pod监控数据

    kubernetes中承担的责任远不止监控数据的采集,还包括控制台的监控接口、HPA的POD弹性伸缩等都依赖于Heapster的功能。简介在kubernetes的监控方案中
    发表于 05-10 15:28

    从零开始入门 K8s| 详解 Pod 及容器设计模式

    ?它会把四个独立的进程分别用四个独立的容器启动起来,然后把它们定义在一个 Pod 里面。所以当 Kubernetes 把 Helloworld 给拉起来的时候,你实际上会看到四个容器,它们共享了某些资源
    发表于 09-20 15:12

    Pod资源配置

    Kubernetes进阶实战》第四章《管理Pod资源对象》
    发表于 10-22 14:39

    电动机故障方法

    电动机故障方法   电动机运行或故障时,可通过看、听、闻、摸四种方法来及时预防和排除故障,保证电动机的安全运行。
    发表于 01-14 10:39 1241次阅读

    iPod秘技!

    iPod秘技! 拥有了iPod的你,是否想知道一些排除故障的方法呢?你又是否想知道在iPod身上存在的一些特殊设置呢?如果你的回答是肯定的话,
    发表于 02-02 11:55 976次阅读

    LTE流程及典型案例

    LTE流程及典型案例分享。
    发表于 05-25 15:57 6次下载

    Kubernetes组件pod核心原理

    1. 核心组件原理 —— pod 核心原理 1.1 pod 是什么 pod 也可以理解是一个容器,装的是 docker 创建的容器,也就是用来封装容器的一个容器; pod 是一个虚拟化
    的头像 发表于 09-02 09:27 2573次阅读

    Kubernetes中的Pod简易理解

    PodKubernetes中非常重要的概念,也是Kubernetes管理的基本单位。正如其名,Pod像一个豌豆荚,可以容纳多个container,拥有相同的IP地址。
    的头像 发表于 02-15 10:44 2205次阅读

    Kubernetes Pod如何独立工作

    在学习 Kubernetes 网络模型的过程中,了解各种网络组件的作用以及如何交互非常重要。本文就介绍了各种网络组件在 Kubernetes 集群中是如何交互的,以及如何帮助每个
    的头像 发表于 05-16 14:29 1276次阅读
    <b class='flag-5'>Kubernetes</b> <b class='flag-5'>Pod</b>如何独立工作

    Kubernetes Pod如何获取IP地址呢?

    Kubernetes 网络模型的核心要求之一是每个 Pod 都拥有自己的 IP 地址并可以使用该 IP 地址进行通信。很多人刚开始使用 Kubernetes 时,还不清楚如何为每个 Pod
    的头像 发表于 07-21 10:00 1595次阅读
    <b class='flag-5'>Kubernetes</b> <b class='flag-5'>Pod</b>如何获取IP地址呢?

    Kubernetes Pod常用管理命令详解

    Kubernetes Pod常用管理命令详解
    的头像 发表于 02-17 14:06 1628次阅读
    <b class='flag-5'>Kubernetes</b> <b class='flag-5'>Pod</b>常用管理命令详解

    详解Kubernetes中的Pod调度亲和性

    Kubernetes(K8s)中,Pod 调度亲和性(Affinity) 是一种高级调度策略,用于控制 Pod 与节点(Node)或其他 Pod 之间的关联(亲和)或反关联(反亲和
    的头像 发表于 06-07 13:56 1082次阅读

    Kubernetes Pod调度策略原理与落地指南

    Pod调度是Kubernetes的核心机制之一,决定了Pod最终运行在哪个节点上。默认调度器kube-scheduler通过一系列预选(Filtering)和优选(Scoring)算法完成调度决策,但默认行为在生产环境中往往不够
    的头像 发表于 02-27 11:08 288次阅读

    Kubernetes Pod异常问题排查实战

    集群跑着跑着,Pod 挂了。Slack 告警一刷屏,脑子一片空白。打开终端敲 kubectl get pods,看到一堆 CrashLoopBackOff、ImagePullBackOff、Pending,不知道从哪下手。这是每个刚接触 Kubernetes 运维的人都会
    的头像 发表于 03-18 15:43 241次阅读