kubernetes中常见的exited code总结

什么是容器退出码

当容器终止时,容器引擎使用退出码来报告容器终止的原因。如果是 Kubernetes 用户,容器故障是 pod 异常最常见的原因之一,了解常见的容器退出码可以帮助在排查时更快捷找到 pod异常的根本原因。可以参考https://komodor.com/learn/exit-codes-in-containers-and-kubernetes-the-complete-guide/
下面是容器常见的退出码:

退出码 名称 大致含义
0 正常退出 正常退出
1 应用错误 容器因代码程序错误或镜像规范中的错误引用停止
125 容器未能运行 docker run 命令没有执行成功
126 命令调用错误 无法调用镜像中指定的命令
127 找不到文件或目录 指定命令引用了不存在的文件或目录
128 退出时使用的参数无效 退出是用无效的退出码触发的(有效代码是 0-255 之间的整数)
134 异常终止 (SIGABRT) 容器使用 abort() 函数自行中止
137 立即终止 (SIGKILL) 容器被操作系统通过 SIGKILL 信号终止
139 分段错误 (SIGSEGV) 容器试图访问未分配给它的内存并被终止
143 优雅终止 (SIGTERM) 容器收到即将终止的警告,然后终止
255 退出状态 超出范围容器退出,返回可接受范围之外的退出代码,表示错误原因未知

说明:在使用kubernetes时,我们其实不需要记住具体的代码含义,很多时候,我们通过describe中event中的提示信息就能知道容器异常的原因。

下面我们将解释如何在宿主机和 Kubernetes 中对失败的容器进行故障排除,并提供有关上面列出的所有退出代码的更多详细信息。容器生命周期
为了更好地理解容器故障的原因,让我们先要了解容器的生命周期。以 Docker 为例 ,Docker 容器可能会处于以下几种状态之一:

  • Created:Docker 容器已创建但尚未启动(这是运行docker create 后但实际运行容器之前的状态)
  • Up:Docker 容器当前正在运行。这意味着容器管理的操作系统进程正在运行。当使用命令docker start 或docker run 时会发生这种情况,使用docker start 或docker run 可能会发生这种情况。
  • Paused:容器进程正在运行,但 Docker 暂停了容器。通常,当运行docker pause 命令时会发生这种情况
  • Exited:Docker 容器已经被终止,通常是由于容器的进程被杀死了

当一个容器达到 Exited 状态时,Docker 会在日志中报告一个退出码,告诉你容器发生了什么导致它退出。

了解容器退出码

下面我们将详细说明每个退出码。
退出码 0:正常退出
退出代码 0 由开发人员在任务完成后故意停止容器时触发。从技术上讲,退出代码 0 意味着前台进程未附加到特定容器。如果容器以退出码 0 终止怎么办?

  1. 检查容器日志,确定哪个库导致容器退出;
  2. 查看现有库的代码,并确定它触发退出码 0 的原因,以及它是否正常运行。

退出码 1:应用错误
退出代码 1 表示容器由于以下原因之一停止:

  1. 应用程序错误:这可能是容器运行的代码中的简单编程错误,例如“除以零”,也可能是与运行时环境相关的高级错误,例如 Java、Python 等;
  2. 无效引用:这意味着镜像规范引用了容器镜像中不存在的文件。

如果容器以退出码 1 终止怎么办?

  1. 检查容器日志以查看是否找不到映像规范中列出的文件之一。如果这是问题所在,请更正镜像以指向正确的路径和文件名。
  2. 如果您找不到不正确的文件引用,请检查容器日志以查找应用程序错误,并调试导致错误的库。

退出码 125:容器未能运行
退出码 125 表示该命令用于运行容器。例如 docker run 在 shell 中被调用但没有成功执行。以下是可能发生这种情况的常见原因:

  1. 命令中使用了未定义的 标志,例如docker run --margu;
  2. 镜像中用户的定义命令在本机权限不足;
  3. 容器引擎与宿主机操作系统或硬件不兼容。
    如果容器以退出码 125 终止怎么办?
  4. 检查运行容器的命令语法是否正确;
  5. 检查运行容器的用户,或者镜像中执行命令的上下文,是否有足够的权限在宿主机上创建容器;
  6. 如果您的容器引擎提供了运行容器的 option,请尝试它们。例如,在 Docker 中,尝试docker start 而不是docker run;
  7. 测试您是否能够使用相同的用户名或上下文在主机上运行其他容器。如果不能,重新安装容器引擎,或者解决容器引擎和主机设置之间的底层兼容性问题。

退出码 126:命令调用错误
退出码 126 表示无法调用容器镜像中使用的命令。这通常是用于运行容器的持续集成脚本中缺少依赖项或错误的原因。如果容器以退出码 126 终止怎么办?

  1. 检查容器日志,查看无法调用哪个命令;
  2. 尝试在没有命令的情况下运行容器以确保隔离问题;
  3. 对命令进行故障排除以确保您使用正确的语法,并且所有依赖项都可用;
  4. 更正容器规范并重试运行容器。

退出码 127:找不到文件或目录
退出码 127 表示容器中指定的命令引用了不存在的文件或目录。如果容器以退出码 127 终止怎么办?
与退出码 126 相同,识别失败的命令,并确保容器镜像中引用的文件名或文件路径真实有效。退出码

128:退出时使用的参数无效
退出码 128 表示容器 内的代码触发了退出命令,但没有提供有效的退出码。 Linux exit 命令只允许 0-255 之间的整数,因此如果进程以退出码 3.5 (小数)退出,则日志将报告退出代码 128。如果容器以退出码 128 终止怎么办?

  1. 检查容器日志以确定哪个库导致容器退出。
  2. 确定有问题的库在哪里使用了exit 命令,并更正它以提供有效的退出代码。

退出码 134:异常终止 (SIGABRT)
退出码 134 表示容器自身异常终止,关闭进程并刷新打开的流。此操作是不可逆的,类似 SIGKILL(请参阅下面的退出码 137)。进程可以通过执行以下操作之一来触发 SIGABRT:

1.调用libc 库中的abort() 函数;
2.调用assert() 宏,用于调试。如果断言为假,则该过程中止。

如果容器以退出码 134 终止怎么办?
1.检查容器日志,查看哪个库触发了SIGABRT 信号;
2. 检查中止进程是否是预期内的(例如,因为库处于调试模式),如果不是,则对库进行故障排除,并修改以避免中止容器。

退出码 137:立即终止 (SIGKILL)
退出码 137 表示容器已收到来自主机操作系统的 SIGKILL 信号。该信号指示进程立即终止,没有宽限期。可能的原因是:
1.当通过容器引擎杀死容器时触发,例如使用docker kill 命令时;
2.由 Linux 用户向进程发送kill -9 命令触发;
3.在尝试终止容器并等待 30 秒的宽限期后由 Kubernetes 触发(默认情况下);
4.由主机自动触发,通常是由于内存不足。在这种情况下,docker inspect 命令将指示OOMKilled 错误。

如果容器以退出码 137 终止怎么办?

  1. 检查主机上的日志,查看在容器终止之前发生了什么,以及在接收到SIGKILL 之前是否之前收到过SIGTERM 信号(优雅终止);
  2. 如果之前有SIGTERM 信号,请检查您的容器进程是否处理SIGTERM 并能够正常终止;
  3. 如果没有SIGTERM 并且容器报告了OOMKilled 错误,则排查主机上的内存问题。

退出码 139:分段错误 (SIGSEGV)
退出码 139 表示容器收到了来自操作系统的 SIGSEGV 信号。这表示分段错误 —— 内存违规,由容器试图访问它无权访问的内存位置引起。SIGSEGV 错误有三个常见原因:
1.编码错误:容器进程没有正确初始化,或者它试图通过指向先前释放的内存的指针来访问内存
2.二进制文件和库之间不兼容:容器进程运行的二进制文件与共享库不兼容,因此可能会尝试访问不适当的内存地址
3.硬件不兼容或配置错误:如果您在多个库中看到多个分段错误,则主机上的内存子系统可能存在问题或系统配置问题

如果容器以退出码 139 终止怎么办?

  1. 检查容器进程是否处理SIGSEGV。在 Linux 和 Windows 上,您都可以处理容器对分段错误的响应。例如,容器可以收集和报告堆栈跟踪;
  2. 如果您需要对SIGSEGV 进行进一步的故障排除,您可能需要将操作系统设置为即使在发生分段错误后也允许程序运行,以便进行调查和调试。然后,尝试故意造成分段错误并调试导致问题的库;
  3. 如果您无法复现问题,请检查主机上的内存子系统并排除内存配置故障。

退出码 143:优雅终止 (SIGTERM)
退出码 143 表示容器收到来自操作系统的 SIGTERM 信号,该信号要求容器正常终止,并且容器成功正常终止(否则您将看到退出码 137)。该退出码可能的原因是:
1.容器引擎停止容器时触发,例如使用docker stop 或docker-compose down 命令时;
2.由 Kubernetes 将 Pod 设置为 Terminating 状态触发,并给容器 30 秒的时间以正常关闭。

如果容器以退出码 143 终止怎么办?
1.检查主机日志,查看操作系统发送 SIGTERM 信号的上下文。如果您使用的是 Kubernetes,请检查 kubelet 日志,查看 pod 是否以及何时关闭。一般来说,退出码 143 不需要故障排除。这意味着容器在主机指示后正确关闭。

退出码 255:退出状态超出范围
当您看到退出码 255 时,意味着容器的 entrypoint 以该状态停止。这意味着容器停止了,但不知道是什么原因。如果容器以退出码 255 终止怎么办?

  1. 如果容器在虚拟机中运行,首先尝试删除虚拟机上配置的 overlay 网络并重新创建它们。
  2. 如果这不能解决问题,请尝试删除并重新创建虚拟机,然后在其上重新运行容器。
  3. 如果上述操作失败,则 bash 进入容器并检查有关 entrypoint 进程及其失败原因的日志或其他线索。

哪些 Kubernetes 错误与容器退出代码有关?
每当 pod 中容器发生故障,或者 Kubernetes 指示 pod 出于任何原因终止时,容器将关闭并记录退出代码。识别退出代码可以帮助您了解 pod 异常的根本原因。
可以使用以下命令查看 pod 错误:kubectl describe pod
如下所示:

[root@k8s-m1 k8s-volumes]# kubectl describe pod -n metallb-system  speaker-76lcc 

    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Mon, 24 Jul 2023 15:44:08 +0800
      Finished:     Mon, 24 Jul 2023 15:44:08 +0800
    Ready:          False
    Restart Count:  7876
    Environment:
      METALLB_NODE_NAME:       (v1:spec.nodeName)
      METALLB_HOST:            (v1:status.hostIP)
      METALLB_ML_BIND_ADDR:    (v1:status.podIP)
      METALLB_ML_LABELS:      app=metallb,component=speaker
      METALLB_ML_SECRET_KEY:  <set to the key 'secretkey' in secret 'memberlist'>  Optional: false
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from speaker-token-z5mww (ro)

使用kubectl提供的退出代码解决问题:
如果退出代码为 0:容器正常退出,无需排查
如果退出代码在 1-128 之间:容器因内部错误而终止,例如镜像规范中缺少或无效的命令
如果退出代码在 129-255 之间:容器因操作信号而停止,例如 SIGKILL 或 SIGINT
如果退出代码是exit(-1)或 0-255 范围之外的另一个值,kubectl将其转换为 0-255 范围内的值。

如上,Exit Code为1 ,大致推断为程序内部错误。可以结合kubectl logs进行排查

[root@k8s-m1 k8s-volumes]# kubectl logs  -n metallb-system  speaker-76lcc 
{"branch":"HEAD","caller":"level.go:63","commit":"v0.11.0","goversion":"gc / go1.16.9 / amd64","level":"info","msg":"MetalLB speaker starting version 0.11.0 (commit v0.11.0, branch HEAD)","ts":"2023-07-24T07:49:13.848664833Z","version":"0.11.0"}
{"caller":"level.go:63","error":"Could not set up network transport: failed to obtain an address: Failed to start UDP listener on \"192.168.2.142\" port 7946: listen udp 192.168.2.142:7946: bind: address already in use","level":"error","msg":"failed to create memberlist","op":"startup","ts":"2023-07-24T07:49:13.84936419Z"}

发现是由于端口冲突造成。解决了端口冲突即可解决问题。

更多关于kubernetes的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出

你可能感兴趣的:(Kubernetes,kubernetes,容器)