前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[译] SIGTERM:Linux 容器的优雅终止(退出代码 143)

[译] SIGTERM:Linux 容器的优雅终止(退出代码 143)

作者头像
CS实验室
发布于 2022-08-01 12:17:11
发布于 2022-08-01 12:17:11
12.3K0
举报
文章被收录于专栏:CS实验室CS实验室

❝翻译自 《SIGTERM: Graceful termination of Linux containers (exit code 143)》 原文链接:https://komodor.com/learn/sigterm-signal-15-exit-code-143-linux-graceful-termination/ ❞

什么是 SIGTERM(信号 15)

SIGTERM(信号 15)在基于 Unix 的操作系统(如 Linux)中用于终止进程。SIGTERM 信号提供了一种优雅的方式来终止程序,使其有机会准备关闭并执行清理任务,或者在某些情况下拒绝关闭。Unix/Linux 进程可以以多种方式处理 SIGTERM,包括阻塞和忽略。

SIGTERM 是 Unix/Linux kill 命令的默认行为,当用户执行 kill 时,操作系统会在后台向进程发送 SIGTERM。如果过程不在 Docker 容器中,通过 SIGTERM 信号终止的容器在其日志中显示退出码 143。如果您是 Kubernetes 用户,本文将帮助您了解 Kubernetes 终止容器时幕后发生的情况,以及如何在 Kubernetes 中使用 SIGTERM 信号。

SIGTERM 与 SIGKILL

SIGTERM(Unix 信号 15)是一个“礼貌”的 Unix 信号,默认情况下会终止进程,但可以被进程处理或忽略。这使进程有机会在关闭之前完成基本操作或执行清理。目的是不管它是否成功结束,都要杀死进程,但是给它一个机会先清理进程。

SIGKILL(Unix 信号 9)是一个“残酷”的 Unix 信号,它会立即终止进程。无法处理或忽略 SIGKILL,因此进程没有机会进行清理。SIGKILL 应该被 Unix/Linux 用户用作最后的手段,因为它可能导致错误和数据损坏。

在某些情况下,即使发送了 SIGKILL,内核也可能无法终止进程。如果一个进程正在等待网络或磁盘 I/O,而内核无法阻止它,它就会成为僵尸进程。需要重新启动才能从系统中清除僵尸进程。

退出码 143 和 137 与 Docker 容器中的 SIGTERMSIGKILL 一一对应:

  • Docker 退出码 143 – 表示容器收到底层操作系统的 SIGTERM
  • Docker 退出码 137 - 表示容器收到底层操作系统的 SIGKILL

在 Linux 中发送 SIGTERM

在 Unix/Linux 中结束进程最常用的方法是使用 kill 命令,如下所示:kill [ID]。默认情况下,kill 命令会向进程发送 SIGTERM 信号。

如需找到 [ID](进程 ID),请使用命令 ps -aux,它会列出所有正在运行的进程。

如何发送 SIGKILL

在极端情况下,您可能需要立即使用 SIGKILL 终止进程。使用此命令发送 SIGKILLkill -9 [ID]

处理僵尸进程

当您列出正在运行的进程时,您可能会发现在 CMD 列中显示 defunct 的进程。这些是没有正确终止的僵尸进程。僵尸进程的特征是:

  • 不再执行
  • 没有分配系统空间
  • 但是保留一个进程ID

僵尸进程会一直出现在进程表中,直到其父进程关闭或操作系统重新启动。在许多情况下,僵尸进程会在进程表中累积,因为多个子进程被父进程 fork 出来,但没有被成功杀死。为避免这种情况,请确保您的应用程序的 sigaction 事务忽略 SIGCHLD 信号。

Kubernetes 中的 SIGTERM

如果您是 Kubernetes 用户,您可以通过终止 pod 向容器发送 SIGTERM。每当 pod 终止时,默认情况下,Kubernetes 都会向 pod 中的容器发送 SIGTERM 信号。

由于扩容或部署操作,Pod 通常会自动终止。要手动终止 pod,您可以发送 kubectl delete 命令或 API 调用来终止 pod。

请注意,在默认为 30 秒的宽限期之后,Kubernetes 会发送 SIGKILL 以立即终止容器。

优雅终止和 SIGTERM

Kubernetes 管理容器集群,会在您的应用程序上执行许多自动化操作。例如,它可以对应用程序扩容或缩容、更新以及删除。因此,在很多情况下 Kubernetes 需要关闭一个 pod(带有一个或多个容器),即使它们运行正常。

在某些情况下,Kubernetes 会因为 Pod 出现故障,或者因为主机上的资源不足(称为驱逐)而关闭 Pod。每当 Kubernetes 出于任何原因需要终止 pod 时,它都会向 pod 中运行的容器发送 SIGTERM

Kubernetes 终止 pod 的完整过程如下:

  1. Pod 设置为 Terminating 状态:然后 Kubernetes 将其从所有服务中删除,并停止接收新流量。此时,在 pod 上运行的容器并不会感知到这一变化。
  2. preStop hook:这是一个特殊的命令,在 pod 开始终止之前发送到 pod 中的容器。您可以在容器中使用此 hook 来启动正常关闭。虽然最好直接处理 SIGTERM 信号(在下一步中发送),但如果由于任何原因无法执行,则可以使用 preStop hook,且无需更改应用程序的代码。
  3. SIGTERM 信号发送到 pod:Kubernetes 将 SIGTERM 发送到 pod 中的所有容器。理想情况下,您的应用程序应该处理 SIGTERM 信号并启动干净的关闭过程。请注意,即使处理了 preStop hook,您仍然需要测试并了解您的应用程序如何处理 SIGTERM。对 preStop 和 SIGTERM 的冲突或重复反应可能导致生产问题。
  4. 宽限期:发送 SIGTERM 后,Kubernetes 会等待 TerminationGracePeriod,默认为 30 秒,以允许容器关闭。您可以在每个 pod 的 YAML 模板中自定义宽限期。注意:Kubernetes 不会等待 preStop hook 完成,它从发送 SIGTERM 信号的那一刻开始计算宽限期。如果容器在宽限期结束之前自行退出,Kubernetes 将停止等待并进入下一步。
  5. 向 pod 发送 SIGKILL 信号:所有正在运行的容器进程在主机上立即终止,并且 kubelet 将清理所有相关的 Kubernetes 对象。

处理 SIGTERM 和 preStop

为确保 pod 终止不会中断您的应用程序并影响最终用户,您应该处理 pod 的终止。

实际上,这意味着需要确保您的应用程序处理 SIGTERM 信号并在收到信号时执行有序的关闭过程。这应该包括完成事务、保存临时数据、关闭网络连接和清理不需要的数据。

请注意,与常规 Linux 系统不同,在 Kubernetes 中,在宽限期后,SIGTERM 后面跟着 SIGKILL。所以你必须准备关闭容器,不能简单地忽略它。

处理优雅终止的另一个选项是 preStop hook,允许您在不更改应用程序代码的情况下执行关闭过程。如果您使用 preStop hook,请确保其执行的操作不会与应用程序在收到 SIGTERM 信号时执行的操作重复或冲突。通常最好处理 SIGTERM 或 preStop 其中之一,以避免冲突。

与 SIGTERM 相关的错误

任何导致 pod 关闭的 Kubernetes 错误都会触发 SIGTERM 信号发送到 pod 内的容器:

  • 在 Kubernetes 级别,您将通过运行 kubectl describe pod 看到 Kubernetes 错误。
  • 在容器级别,您可以看到退出代码:如果容器使用 SIGTERM 正常终止,则为 143,如果在宽限期后强制终止,则为 137。
  • 在主机级别,您可以看到发送到容器进程的 SIGTERMSIGKILL 信号。

一个例外是 OOMKilled 错误。这是由于容器或 pod 超出主机上分配给它们的内存而发生的 Kubernetes 错误。当容器或 Pod 因 OOMKilled 而终止时,Kubernetes 会立即发送 SIGKILL 信号,而不使用 SIGTERM 和宽限期。

SIGTERM 如何影响 NGINX Ingress Controllers?

在 Kubernetes 上运行应用程序时,您必须确保 ingress controllers 不会出现停机。否则,每当 controller 重新启动或重新部署时,用户都会遇到速度变慢或服务中断的情况。如果一个 ingress pod 被终止,可能会导致连接断开,在生产中必须避免这种情况。

问题:NGINX 没有在 SIGTERM 上执行优雅终止

如果你使用的是官方的 NGINX Ingress Controller,当 controller Pod 被终止时,Kubernetes 会像往常一样发送一个 SIGTERM 信号。

然而,NGINX controller 并没有按照 Kubernetes 期望的方式处理 SIGTERM

  • 当 NGINX 收到 SIGTERM 时,它会立即关闭。基本上,NGINX 将 SIGTERM 视为 SIGKILL
  • 当 NGINX 收到 SIGQUIT 信号时,它会执行正常关闭。

解决方案:使用 preStop 挂钩

正如我们在上面的处理 SIGTERM 和 preStop 部分中所讨论的,Kubernetes 提供了第二个处理优雅终止的方案 - preStop hook。您可以在发送 SIGTERM 之前使用 preStop 挂钩向 NGINX 发送 SIGQUIT 信号。这避免了 NGINX 突然关闭,并使其有机会优雅地终止。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CS实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何利用termination GracePeriodSeconds 优雅地关闭你的服务
当涉及到分布式系统,处理故障是关键。Kubernetes通过利用可以监视系统状态并重新启动已停止执行的服务的控制器(controllers)来解决这个问题。另一方面,Kubernetes通常可以强制终止您的应用程序,作为系统正常运行的一部分。
kubernetes中文社区
2019/08/15
17.6K0
K8s Pod优雅关闭,没你想象的那么简单!
更新部署服务时,旧的 Pod 会终止,新 Pod 上位。如果在这个部署过程中老 Pod 有一个很长的操作,我们想在这个操作成功完成后杀死这个 pod(优雅关闭),如果无法做到的话,被杀死的 pod 可能会丢失一定的流量,或者外界无法感知到该 Pod 被杀死。特别是,如果我们有一个接收大量流量的 API,错误率在部署过程中会显著增加。
用户5166556
2023/03/18
2.7K0
K8s Pod优雅关闭,没你想象的那么简单!
Kubernetes 如何优雅的重启Pod
在应用程序的整个生命周期中,正在运行的 pod 会由于多种原因而终止。在某些情况下,Kubernetes 会因用户输入(例如更新或删除 Deployment 时)而终止 pod。在其他情况下,Kubernetes 需要释放给定节点上的资源时会终止 pod。无论哪种情况,Kubernetes 都允许在 pod 中运行的容器在可配置的时间内正常关闭。
kubernetes中文社区
2022/10/27
4.5K0
Kubernetes 终止信号:确保应用程序正常关闭
在容器编排领域,Kubernetes 已成为领先的平台,可实现容器化应用程序的高效管理、扩展和部署。当应用程序在容器内运行时,正确终止这些容器对于维持系统的整体健康和可靠性至关重要。在本文中,我们将深入研究 Kubernetes 终止信号的概念,并了解它们如何确保应用程序正常关闭,避免数据丢失或用户体验中断。
DevOps云学堂
2023/09/11
7290
Kubernetes 终止信号:确保应用程序正常关闭
[译] 容器和 Kubernetes 中的退出码完整指南
当容器终止时,容器引擎使用退出码来报告容器终止的原因。如果您是 Kubernetes 用户,容器故障是 pod 异常最常见的原因之一,了解容器退出码可以帮助您在排查时找到 pod 故障的根本原因。
CS实验室
2022/08/01
6.1K0
[译] 容器和 Kubernetes 中的退出码完整指南
k8s容器的钩子与优雅停机
在 Kubernetes 中,每次微服务的代码发布都意味着创建新版本的 pod 并删除旧 pod,如果部署不够优雅的话,可能出现如下两个问题:
SRE运维手记
2024/09/25
2950
k8s容器的钩子与优雅停机
如何优雅地关闭Kubernetes集群中的Pod
这是我们实现 Kubernetes 集群零停机时间更新的第二部分。在本系列的第一部分中,我们列举出了简单粗暴地使用kubectl drain 命令清除集群节点上的 Pod 的问题和挑战。在这篇文章中,我们将介绍解决这些问题和挑战的手段之一:优雅地关闭 Pod。
KevinYan
2021/03/16
3.2K0
Kubernetes 中容器的退出状态码参考指南
当容器终止时,容器引擎使用退出码来报告容器终止的原因。如果您是 Kubernetes 用户,容器故障是 pod 异常最常见的原因之一,了解容器退出码可以帮助您在排查时找到 pod 故障的根本原因。
公众号: 云原生生态圈
2024/01/23
5730
Kubernetes 中容器的退出状态码参考指南
优雅地终止:Graceful Shutdown指南
您是否曾经因沮丧而拔掉电脑的电源线?虽然这似乎是一个快速解决方案,但它会导致数据丢失和系统不稳定。在软件世界中,存在类似的概念:硬关闭。这种突然的终止会导致与物理对应物相同的问题。值得庆幸的是,有一种更好的方法:优雅关闭。
云云众生s
2024/07/18
1970
优雅地终止:Graceful Shutdown指南
K8s中优雅停机和零宕机部署
创建、删除 Pod 是 K8s 中最常见的任务之一。本文介绍了 Pod 在响应创建、删除请求时发生的内部流程,还讨论了如何在 Pod 启动或关闭时防止断开连接,以及如何正常关闭长时间运行的任务。
CNCF
2020/08/20
4K0
K8s中优雅停机和零宕机部署
容器化后无损上下线解决方案
绝大数事故发生在应用上下线发布阶段,所以要尽可能避免发布过程中由于应用自身代码问题对用户造成的影响。
SRE运维进阶之路
2023/11/21
5240
容器化后无损上下线解决方案
闲聊k8s的优雅关闭连接
当数据在进行交互的时候,如果连接发生了改变,就必然会涉及到是否是无损关闭连接,主要就是看结束连接的时候是否是四次挥手关闭,短连接其实还好,最关键的是长连接如何关闭。
SRE运维实践
2024/12/09
1730
闲聊k8s的优雅关闭连接
PHP 容器化引发线上 502 错误状态码的修复
笔者所在公司技术栈为 Golang + PHP,目前部分项目已经逐步转 Go 语言重构,部分 PHP 业务短时间无法用 Go 重写。
仁扬
2023/08/01
3900
kubernetes 最佳实践: 优雅终止
Pod 销毁时,会停止容器内的进程,通常在停止的过程中我们需要执行一些善后逻辑,比如等待存量请求处理完以避免连接中断,或通知相关依赖进行清理等,从而实现优雅终止目的。本文介绍在 Kubernetes 场景下,实现容器优雅终止的最佳实践。
imroc
2021/06/04
3.5K0
Kubernetes Pod优雅停机分析
业务容器化上云之后,时常会有版本的动态变更,如何无损升级越发重要。结合底层技术原理,本文将对Pod优雅停机展开分析,供业务团队参考。
白鹏飞
2023/06/14
9190
Kubernetes 运维遇到的问题记录(4)
Kubernetes 集群网络有很多种实现,有很大一部分都用到了 Linux 网桥:每个 Pod 的网卡都是 veth 设备,veth pair 的另一端连上宿主机上的网桥。由于网桥是虚拟的二层设备,同节点的 Pod 之间通信直接走二层转发,跨节点通信才会经过宿主机 eth0。
后端云
2023/02/10
1K0
Kubernetes 运维遇到的问题记录(4)
K8S 滚动更新如何优雅停止 Pod
优雅停止(Graceful shutdown) 这个说法来自于操作系统,我们执行关机之后都得 OS 先完成一些清理操作,而与之相对的就是硬中止(Hard shutdown),比如拔电源。
YP小站
2020/06/04
6K0
K8S 滚动更新如何优雅停止 Pod
如何在容器中执行多条指令并能优雅退出
本文主要围绕k8s command展开讨论。(deployment.spec.template.spec.containers[n].command) 主要聊聊平台在接入用户业务时,如何保证满足业务基本需求情况下增强平台易用性。
你算哪块香橙夹心饼干
2021/08/04
4.5K0
如何在容器中执行多条指令并能优雅退出
Kubernetes运维之容器编排高级Pod编写
创建 Pod 时,可以为其下的容器设置环境变量。通过配置文件的 env 或者 envFrom 字段来设置环境变量。
王先森sec
2023/04/24
6880
kubernetes集群之Pod说能不能让我体面的消亡呀?
由于 Pod 所代表的是在集群中节点上运行的进程,当不再需要这些进程时允许其体面地终止。
囧么肥事
2022/03/14
6780
kubernetes集群之Pod说能不能让我体面的消亡呀?
推荐阅读
相关推荐
如何利用termination GracePeriodSeconds 优雅地关闭你的服务
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档