date: 2021-04-20title: k8s之pod、service、ingress常见错误排查 #标题
tags: k8s错误排查 #标签
categories: k8s # 分类

记录下k8s中部分资源对象的运行错误排查思路。

常见pod错误

Pod可能会出现启动和运行时错误。

启动错误包括:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePull
  • ErrImageNeverPull
  • RegistryUnavailable
  • InvalidImageName

运行时错误包括:

  • CrashLoopBackOff
  • RunContainerError
  • KillContainerError
  • VerifyNonRootError
  • RunInitContainerError
  • CreatePodSandboxError
  • ConfigPodSandboxError
  • KillPodSandboxError
  • SetupNetworkError
  • TeardownNetworkError

有些错误比其他错误更常见。

状态 描述
CrashLoopBackOff 容器退出,kubelet正在将它重启
InvalidImageName 无法解析镜像名称
ImageInspectError 无法校验镜像
ErrImageNeverPull 策略禁止拉取镜像
ImagePullBackOff 正在重试拉取
RegistryUnavailable 连接不到镜像中心
ErrImagePull 通用的拉取镜像出错
CreateContainerConfigError 不能创建kubelet使用的容器配置
CreateContainerError 创建容器失败
m.internalLifecycle.PreStartContainer 执行hook报错
RunContainerError 启动容器失败
PostStartHookError 执行hook报错
ContainersNotInitialized 容器没有初始化完毕
ContainersNotRead 容器没有准备完毕
ContainerCreating 容器创建中
PodInitializing pod 初始化中
DockerDaemonNotReady docker还没有完全启动
NetworkPluginNotReady 网络插件还没有完全启动

以下是最常见的错误列表以及如何修复它们的方法。

ImagePullBackOff

当Kubernetes无法获取到Pod中某个容器的镜像时,将出现此错误。

共有三个可能的原因:

  • 镜像名称无效,例如拼错了名称,或者image不存在
  • 为image指定了不存在的标签
  • 尝试检索的image属于一个私有registry,而Kubernetes没有凭据可以访问它

CrashLoopBackOff

如果容器无法启动,则Kubernetes将显示错误状态为:CrashLoopBackOff。

通常,以下情况下容器无法启动:

  • 应用程序中存在错误,导致无法启动
  • 未正确配置容器
  • Liveness探针失败太多次

如果由于容器重新启动太快而看不到日志,则可以使用以下命令:

  1. # --previous 对应的短选项为 “-p”
  2. $ kubectl logs <pod-name> --previous # 打印前一个容器的错误消息。

RunContainerError

当容器无法启动时,出现此错误。

甚至在容器内的应用程序启动之前。

该问题通常是由于配置错误,例如:

  • 挂载不存在的卷,例如ConfigMap或Secrets
  • 将只读卷安装为可读写

应该使用 kubectl describe pod 命令收集和分析错误。

处于Pending状态的Pod

当创建Pod时,该Pod保持Pending状态。

为什么?

假设调度程序组件运行良好,可能的原因如下:

  • 集群没有足够的资源(例如CPU和内存)来运行Pod
  • 当前的命名空间具有ResourceQuota对象,创建Pod将使命名空间超过配额
  • 该Pod绑定到一个处于pending状态的 PersistentVolumeClaim

最好的选择是检查kubectl describe命令输出的“事件”部分内容:

  1. $ kubectl describe pod <pod name>

对于因ResourceQuotas而导致的错误,可以使用以下方法检查集群的日志:

  1. $ kubectl get events --sort-by=.metadata.creationTimestamp

处于未就绪状态的Pod

如果Pod正在运行但未就绪(not ready),则表示readiness就绪探针失败。

当“就绪”探针失败时,Pod未连接到服务,并且没有流量转发到该实例。

就绪探针失败是应用程序的特定错误,因此应检查 kubectl describe 中的 Events 部分以识别错误。

service的故障排除

如果Pod正在运行并处于就绪状态,但仍无法收到应用程序的响应,则应检查服务的配置是否正确。

service旨在根据流量的标签将流量路由到Pod。

因此,应该检查的第一件事是服务关联了多少个Pod。

可以通过检查服务中的端点(endpoint)来做到这一点:

  1. $ kubectl describe service <service-name> | grep Endpoints

端点是一对,并且在服务(至少)以Pod为目标时,应该至少有一个端点。

如果“端点”部分为空,则有两种解释:

  • 没有运行带有正确标签的Pod(提示:应检查自己是否在正确的命名空间中)
  • service的 selector 标签上有拼写错误

如果看到端点列表,但仍然无法访问应用程序,则 targetPort 可能是服务中的罪魁祸首。

如何测试服务?

无论服务类型如何,都可以使用 kubectl port-forward 来连接它:

  1. $ kubectl port-forward service/<service-name> 3000:80
  2. # <service-name> 是服务的名称
  3. # 3000 是你希望在计算机上打开的端口
  4. # 80 是服务公开的端口

查看pod日志的几种姿势

  1. # 追踪名称空间 nsA 下容器组 pod1 的日志
  2. kubectl logs -f pod1 -n nsA
  3. # 追踪名称空间 nsA 下容器组 pod1 中容器 container1 的日志
  4. kubectl logs -f pod1 -c container1 -n nsA
  5. # 查看容器组 nginx 下所有容器的日志
  6. kubectl logs nginx --all-containers=true
  7. # 查看带有 app=nginx 标签的所有容器组所有容器的日志
  8. kubectl logs -lapp=nginx --all-containers=true
  9. # 查看容器组 nginx 最近20行日志
  10. kubectl logs --tail=20 nginx
  11. # 查看容器组 nginx 过去1个小时的日志
  12. kubectl logs --since=1h nginx