配置容器生命周期挂钩 - AWS 规范性指导

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

配置容器生命周期挂钩

在容器正常关闭期间,您的应用程序应通过开始关闭来响应SIGTERM信号,这样客户端就不会遇到任何停机时间。您的应用程序应运行清理程序,如下所示:

  • 保存数据

  • 关闭文件描述符

  • 关闭数据库连接

  • 优雅地完成机上请求

  • 及时退出以满足 pod 终止请求

设置足够长的宽限期以完成清理。要了解如何响应SIGTERM信号,请参阅用于应用程序的编程语言的文档。

容器生命周期挂钩使容器能够感知其管理生命周期中的事件。当执行相应的生命周期挂钩时,容器可以运行在处理程序中实现的代码。容器生命周期挂钩为 Kubernetes 和云的异步性质提供了一种解决方法。这种方法可以防止在入口资源之前转发到终止的 pod 并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

有关更多信息,请参阅容器挂钩EKS 最佳实践-负载平衡(优雅地关闭应用程序)