我有一个 Spring 启动应用程序在由 Kubernetes 管理的 Docker 容器中运行,它的工作是从队列中提取数据,处理它,然后写回队列。最初,此应用程序的部署是使用 1 个副本创建的。但是,在某些时候,我需要扩展该部署,以便更快地处理来自队列的消息。理想情况下,我希望现有的 1 个副本开始处理消息,然后新的副本可以出现并提供帮助。
我发现的问题是,当以编程方式扩展部署时,现有的 1 个副本被破坏,这通常发生在它处理一些数据的过程中,导致该处理的输出丢失。
我希望看到的例子:
- 一个副本处理消息
- 部署扩展到 5 个副本
- 旋转了四个新副本以帮助处理离开现有副本的消息。
这是可能吗?谢谢!
回答1
通常, Kubernetes 会在不重新启动现有 Pod 的情况下进行扩展,这有点不寻常,以至于在您的情况下不会发生这种情况。
除此之外,您的任何 Pod 都不应该以导致消息丢失的方式关闭。这表明您缺少正常关闭的代码。
使用 Spring Boot 和 K8s 你必须做两件事:
- 在 Spring Boot 中引入一个由 K8s 初始 SIGTERM 信号触发的关闭处理程序,并确保应用程序不接受新消息,但有时间处理运行中的消息。 Spring Boot 为此提供了https://www.baeldung.com/spring-shutdown-callbacks。
- 通过充分配置 https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#podspec-v1-core,确保 K8s 为您的应用程序提供充足的正常关闭时间。这是您的应用程序在 K8s 发送 SIGKILL 信号之前有序地自行关闭的时间。
回答2
正如 David Maze 建议的那样,我不仅修补了 replicas
的数量,还修补了 template
中的环境变量,导致重新创建副本以选择新变量。
弗里茨的回答也是优雅关机的一个很好的整体建议。