本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
配置容器生命周期挂钩
在容器正常关闭期间,您的应用程序应通过开始关闭来响应SIGTERM
信号,这样客户端就不会遇到任何停机时间。您的应用程序应运行清理程序,如下所示:
保存数据
关闭文件描述符
关闭数据库连接
优雅地完成机上请求
及时退出以满足 pod 终止请求
设置足够长的宽限期以完成清理。要了解如何响应SIGTERM
信号,请参阅用于应用程序的编程语言的文档。
容器生命周期挂钩iptables
更新为不向 pod 发送新流量的连接丢失。
容器生命周期和终端节点 EndpointSlice 是不同的 APIs。精心策划这些 APIs很重要。但是,当 Pod 被终止时,Kubernetes API 会同时通知 kubelet(用于容器生命周期)和控制器。EndpointSlice
有关更多信息(包括图表),请参阅《EKS 最佳实践指南》中的 “优雅地处理客户请求
当kubelet
发送SIGTERM
到 pod 时,EndpointSlice
控制器正在终止EndpointSlice
对象。该终止会通知 Kubernetes API 服务器通知每个要更新的kube-proxy
节点。iptables
尽管这些操作是同时发生的,但它们之间没有依赖关系或顺序。容器收到SIGKILL
信号的可能性很可能比每个节点kube-proxy
上更新本地iptables
规则的时间要早得多。在这种情况下,可能的情况包括以下几种:
-
如果您的应用程序在收到客户端后立即直言不讳地丢弃正在进行的请求和连接,则
SIGTERM,
会看到错误。500
-
如果您的应用程序确保在收到所有进行中的请求和连接后都得到完全处理
SIGTERM
,那么在宽限期内,新的客户端请求仍会发送到应用程序容器,因为iptables
规则可能尚未更新。在清理过程关闭容器上的服务器套接字之前,这些新请求将产生新的连接。宽限期结束后,发送后建立的新连接将SIGTERM
无条件断开。
要解决之前的情况,您可以实现应用内集成或 PreStop生命周期挂钩。有关更多信息(包括图表),请参阅《EKS 最佳实践指南》中的优雅关闭应用程序
注意:无论应用程序是否正常关闭,或者preStop
挂钩的结果如何,应用程序容器最终都会在宽限期结束时终止。SIGKILL
使用带有sleep
命令的preStop
挂钩来延迟发送SIGTERM
。这将有助于在入口对象将新连接路由到 pod 时继续接受这些连接。测试sleep
命令的时间值,确保将 Kubernetes 的任何延迟和其他应用程序依赖关系都考虑在内,如以下示例所示:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: containers: - name: nginx lifecycle: # This "sleep" preStop hook delays the Pod shutdown until # after the Ingress Controller removes the matching Endpoint or EndpointSlice preStop: exec: command: - /bin/sleep - "20" # This period should be turned to Ingress/Service Mesh update latency
有关更多信息,请参阅容器挂钩