本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
配置容器生命周期挂钩
在容器正常关闭期间,您的应用程序应通过开始关闭来响应SIGTERM信号,这样客户端就不会遇到任何停机时间。您的应用程序应运行清理程序,如下所示:
-
保存数据
-
关闭文件描述符
-
关闭数据库连接
-
优雅地完成机上请求
-
及时退出以满足 pod 终止请求
设置足够长的宽限期以完成清理。要了解如何响应SIGTERM信号,请参阅用于应用程序的编程语言的文档。
容器生命周期挂钩iptables更新为不向 pod 发送新流量的连接丢失。
容器生命周期Endpoint、和EndpointSlice是不同 API 的一部分。编排这些 API 很重要。但是,当 Pod 被终止时,Kubernetes API 会同时通知 kubelet(用于容器生命周期)和控制器。EndpointSlice有关更多信息(包括图表),请参阅 Amazon EKS 最佳实践指南中的优雅处理客户请求。
当kubelet发送SIGTERM到 pod 时,EndpointSlice控制器正在终止EndpointSlice对象。该终止会通知 Kubernetes API 服务器通知每个要更新的kube-proxy节点。iptables尽管这些操作是同时发生的,但它们之间没有依赖关系或顺序。容器收到SIGKILL信号的可能性很可能比每个节点kube-proxy上更新本地iptables规则的时间要早得多。在这种情况下,可能的情况包括以下几种:
-
如果您的应用程序在收到请求和连接后立即直言不讳地丢弃了正在进行的请求和连接
SIGTERM,则客户端会看到错误。500 -
如果您的应用程序确保在收到所有进行中的请求和连接后都得到完全处理
SIGTERM,那么在宽限期内,新的客户端请求仍会发送到应用程序容器,因为iptables规则可能尚未更新。在清理过程关闭容器上的服务器套接字之前,这些新请求将产生新的连接。宽限期结束后,发送后建立的新连接将SIGTERM无条件断开。
要解决之前的情况,您可以实现应用内集成或 PreStop生命周期挂钩。有关更多信息(包括图表),请参阅 Amazon 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
有关更多信息,请参阅 Kubernetes 文档中的容器挂钩