k8s实践指南-排错案例-分析 ExitCode 定位 Pod 异常退出原因

作者: K8S实践指南

分析 ExitCode 定位 Pod 异常退出原因

使用 kubectl describe pod <pod name> 查看异常 pod 的状态:

  
   Containers:
    kubedns:
    Container ID: docker://5fb8adf9ee62afc6d3f6f3d9590041818750b392dff015d7091eaaf99cf1c945
    Image: ccr.ccs.tencentyun.com/library/kubedns-amd64:1.14.4
    Image ID: docker-pullable://ccr.ccs.tencentyun.com/library/kubedns-amd64@sha256:40790881bbe9ef4ae4ff7fe8b892498eecb7fe6dcc22661402f271e03f7de344
    Ports: 10053/UDP, 10053/TCP, 10055/TCP
    Host Ports: 0/UDP, 0/TCP, 0/TCP
    Args:
    --domain=cluster.local.
    --dns-port=10053
    --config-dir=/kube-dns-config
    --v=2
    State: Running
    Started: Tue, 27 Aug 2019 10:58:49 +0800
    Last State: Terminated
    Reason: Error
    Exit Code: 255
    Started: Tue, 27 Aug 2019 10:40:42 +0800
    Finished: Tue, 27 Aug 2019 10:58:27 +0800
    Ready: True
    Restart Count: 1

在容器列表里看 Last State 字段,其中 ExitCode 即程序上次退出时的状态码,如果不为 0,表示异常退出,我们可以分析下原因。

退出状态码的区间

  • 必须在 0-255 之间
  • 0 表示正常退出
  • 外界中断将程序退出的时候状态码区间在 129-255,(操作系统给程序发送中断信号,比如 kill -9  SIGKILLctrl+c  SIGINT)
  • 一般程序自身原因导致的异常退出状态区间在 1-128 (这只是一般约定,程序如果一定要用129-255的状态码也是可以的)

假如写代码指定的退出状态码时不在 0-255 之间,例如: exit(-1),这时会自动做一个转换,最终呈现的状态码还是会在 0-255 之间。我们把状态码记为 code

  • 当指定的退出时状态码为负数,那么转换公式如下:
  
   256 - (|code| % 256)

  • 当指定的退出时状态码为正数,那么转换公式如下:
  
   code % 256

常见异常状态码

  • 137 (被 SIGKILL 中断信号杀死)
    • 此状态码一般是因为 pod 中容器内存达到了它的资源限制(resources.limits),一般是内存溢出(OOM),CPU达到限制只需要不分时间片给程序就可以。因为限制资源是通过 linux 的 cgroup 实现的,所以 cgroup 会将此容器强制杀掉,类似于 kill -9,此时在 describe pod 中可以看到 Reason 是 OOMKilled
    • 还可能是宿主机本身资源不够用了(OOM),内核会选取一些进程杀掉来释放内存
    • 不管是 cgroup 限制杀掉进程还是因为节点机器本身资源不够导致进程死掉,都可以从系统日志中找到记录:

ubuntu 的系统日志在 /var/log/syslog,centos 的系统日志在 /var/log/messages,都可以用 journalctl -k 来查看系统日志

  • 也可能是 livenessProbe (存活检查) 失败,kubelet 杀死的 pod
  • 还可能是被恶意木马进程杀死
  • 1 和 255
    • 这种可能是一般错误,具体错误原因只能看容器日志,因为很多程序员写异常退出时习惯用 exit(1)  exit(-1),-1 会根据转换规则转成 255

状态码参考

这里罗列了一些状态码的含义:Appendix E. Exit Codes With Special Meanings

Linux 标准中断信号

Linux 程序被外界中断时会发送中断信号,程序退出时的状态码就是中断信号值加上 128 得到的,比如 SIGKILL 的中断信号值为 9,那么程序退出状态码就为 9+128=137。以下是标准信号值参考:

  
   Signal Value Action Comment
   ──────────────────────────────────────────────────────────────────────
   SIGHUP 1 Term Hangup detected on controlling terminal
    or death of controlling process
   SIGINT 2 Term Interrupt from keyboard
   SIGQUIT 3 Core Quit from keyboard
   SIGILL 4 Core Illegal Instruction
   SIGABRT 6 Core Abort signal from abort(3)
   SIGFPE 8 Core Floating-point exception
   SIGKILL 9 Term Kill signal
   SIGSEGV 11 Core Invalid memory reference
   SIGPIPE 13 Term Broken pipe: write to pipe with no
    readers; see pipe(7)
   SIGALRM 14 Term Timer signal from alarm(2)
   SIGTERM 15 Term Termination signal
   SIGUSR1 30,10,16 Term User-defined signal 1
   SIGUSR2 31,12,17 Term User-defined signal 2
   SIGCHLD 20,17,18 Ign Child stopped or terminated
   SIGCONT 19,18,25 Cont Continue if stopped
   SIGSTOP 17,19,23 Stop Stop process
   SIGTSTP 18,20,24 Stop Stop typed at terminal
   SIGTTIN 21,21,26 Stop Terminal input for background process
   SIGTTOU 22,22,27 Stop Terminal output for background process

C/C++ 退出状态码

/usr/include/sysexits.h 试图将退出状态码标准化(仅限 C/C++):

  
   define EX_OK 0 /* successful termination */

   define EX__BASE 64 /* base value for error messages */

   define EX_USAGE 64 /* command line usage error */
   define EX_DATAERR 65 /* data format error */
   define EX_NOINPUT 66 /* cannot open input */
   define EX_NOUSER 67 /* addressee unknown */
   define EX_NOHOST 68 /* host name unknown */
   define EX_UNAVAILABLE 69 /* service unavailable */
   define EX_SOFTWARE 70 /* internal software error */
   define EX_OSERR 71 /* system error (e.g., can't fork) */
   define EX_OSFILE 72 /* critical OS file missing */
   define EX_CANTCREAT 73 /* can't create (user) output file */
   define EX_IOERR 74 /* input/output error */
   define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
   define EX_PROTOCOL 76 /* remote error in protocol */
   define EX_NOPERM 77 /* permission denied */
   define EX_CONFIG 78 /* configuration error */

   define EX__MAX 78 /* maximum listed value */

文章列表

更多推荐

更多
  • Kubenetes扩展教程-三、API 流扩展 忽必烈 API Flow,身份验证网页挂钩,授权网页挂钩,动态准入控制器,关键要点,证明,服务器 API 配置库,服务器 API 配置库,Webhook 配置资源,> —埃隆·马斯克 >> 商业巨头、工业设计师、工程师Kuber
    Apache CN

  • Kubenetes扩展教程-四、扩展 Kubernetes API kuble API 概述,自定义资源定义和控制器,聚合的 API 和扩展服务器,关键要点,API 版本控制,API 组,库 API 中的扩展点,Kubernetes 客户库,Kubernetes 中的运算符模式,kubebuilder
    Apache CN

  • Kubenetes扩展教程-七、即将到来的扩展点 服务目录,集群 API,关键要点,结论,> —西奥多·罗斯福 >> 美国第 26 任总统Kubernetes 凭借其在云原生世界中的强大基础获得了成功。它提供了一组丰富的特性来管理容器化的应用,并提供了各种扩展点来添加新的功能。
    Apache CN

  • Kubenetes扩展教程-六、基础设施扩展 云原生基础架构,存储插件,网络插件,设备插件,关键要点,容器存储接口,kubernetes 中的 CSI 插件,库柏网络模型,容器网络接口(CNI),设备插件 API,设备插件的开发和部署,> —马克·扎克伯格 >> 美国企业家、脸
    Apache CN

  • Kubenetes扩展教程-五、调度扩展 库调度程序概述,配置和管理多个调度程序,调度程序扩展器,关键要点,调度框架,配置详细信息,> —圣雄甘地 >> 印度律师、政治家、社会活动家、作家 调度器是 Kubernetes 的核心部分,用于将工作负载分配给集群中的节点。分
    Apache CN

  • Kubenetes扩展教程-二、`kubectl`插件 二、kubectl插件kubectl 安装和使用,立方插件设计,创建您的第一个 kubectl 插件,插件库:krew,关键要点,> —马歇尔·麦克卢汉 >> 媒体学者和评论家 命令行工具是开发人员的瑞士军刀。您可以连接到后端系
    Apache CN

  • Kubenetes扩展教程-一、简介 忽必烈再世,Kubernetes 扩展模式,关键要点,控制平面组件,节点组件,配置 Kubernetes 集群,控制器,web 手册,二进制插件,立方扩展点,> 卡尔沙堡 >> 美国诗人、传记作家、记者和编辑,三次获得普利策奖K
    Apache CN

  • Azure Kubernetes微服务教程-六、AK 的 CI/CD 介绍,快速浏览 DevOps,本次练习的目标,使用 Azure 门户创建 Azure Kubernetes 服务,使用 Azure 门户创建 Azure 容器实例,使用 Visual Studio 构建示例应用,使用 Azure Dev
    Apache CN

  • Azure Kubernetes微服务教程-五、保护和监控 AKS 上运行的应用 介绍,安全概念,蓝色库柏服务清单,监控概念,摘要,主安全,节点安全性,集群升级,网络安全性,不可告人的秘密,安全概念:结论,容器洞察,Azure 监视器功能,介绍首先,祝贺你完成了本书的 60%。在阅读完架构设计和模式之后,
    Apache CN

  • Azure Kubernetes微服务教程-二、微服务:架构和设计考虑 介绍,微服务架构优势,衍生商业价值,定义面向目标的分层方法,应用面向目标的分层方法,微服务设计,微服务的系统方法,微服务设计流程,目标和原则,平台,文化,摘要,附录,模块性,粘结性,相互关系,微服务架构目标和优势的成熟度模型,服务,解决
    Apache CN

  • 近期文章

    更多
    文章目录

      推荐作者

      更多