如何在 Kubernetes 中按特定顺序配置 Pod 初始化?

Posted

技术标签:

【中文标题】如何在 Kubernetes 中按特定顺序配置 Pod 初始化?【英文标题】:How to Configure Pod initialization in a specific order in Kubernetes? 【发布时间】:2019-11-17 23:42:07 【问题描述】:

我想知道如何按特定顺序开始我的部署。我知道initContainers 但这对我不起作用。我有一个巨大的平台,有大约 20 个部署和 5 个状态集,每个都有自己的服务、环境变量、卷、水平自动缩放器等。所以不可能(或者我不知道如何)在另一个中定义它们yaml 部署为initContainers

还有其他选项可以按特定顺序启动部署吗?

【问题讨论】:

您能否举例说明您目前是如何启动它们的,以及您要解决的实际错误或问题是什么?如前所述,这不是一个真正的编程问题,对 serverfault.com 来说会更好。 假设我有 4 个部署(每个部署都有自己的服务和自动缩放器),并且 dep B 和 C 依赖于 A,D 依赖于 B。目前我有一个 bash 脚本按顺序启动这些组件,在该脚本中我等待 10-15 秒,然后再启动下一个部署。我在这里问过其他与 k8s 相关的问题,但如果你认为我必须在 serverfault 上问这个问题,我会移动它。 您好,您可以检查就绪条件是否为真,然后您可以部署下一个部署https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#wait @SureshVishnoi 很好的答案,请将其作为答案发布,以便我接受它作为解决方案。 【参考方案1】:

可以在 Pod 或属于同一 StatefulSet 的 Pod 中订购 initContainers 的启动。但是,这些解决方案不适用于您的情况。

这是因为排序初始化不是解决问题的标准方法。在微服务架构中,更具体地说是 Kubernetes,您将编写容器,以便它们尝试调用它们所依赖的服务(无论它们是否启动),如果它们不可用,则让您的容器崩溃。这是因为 Kubernetes 提供了一个self-healing mechanism,如果容器失败,它会自动重启容器。这样,您的容器将尝试连接到它们所依赖的服务,如果后者不可用,容器将崩溃并稍后使用指数退避重试。

通过消除服务之间不必要的依赖关系,您可以简化应用程序的部署并减少不同服务之间的耦合。

【讨论】:

【参考方案2】:

要在部署之间创建依赖关系,需要有一系列特定条件为真。

例如,等待 pod "busybox1" 包含 "Ready" 类型的状态条件。

kubectl wait --for=condition=Ready pod/busybox1

之后,您可以推出下一个部署。

更多详情见kubectl-wait

这是来自@Michael Hausenblas job-dependencies 的另一个示例,在作业对象之间存在依赖关系。

如果您想在工人完成后开始另一份工作?给你:

$ kubectl -n waitplayground \
             wait --for=condition=complete --timeout=32s \     
             job/worker
job.batch/worker condition met

【讨论】:

【参考方案3】:

只需并行启动它们并让它们崩溃。 Kubernetes 将在延迟一段时间后重新启动失败的那些。

假设你有服务 A,它依赖于 B,它依赖于 C。A 首先启动,并作为其启动序列的一部分尝试调用 B。失败(因为 B 未启动)和 pod更改为错误状态。它可能会重试一次或两次,然后进入 CrashLoopBackOff 状态。 Kubernetes 暂停几秒钟,然后再次重试。 B也会发生同样的事情。

最终服务 C(在堆栈的底部)会出现,一段时间后自动重启将启动 B(紧邻它的上方)。这一次B会启动成功。一段时间后,自动重启将启动 A,这一次将成功启动。

您需要注意的一件事是,如果 Pod 确实以 CrashLoopBackOff 状态结束,可能是因为代码错误、配置错误,或者只是因为它所依赖的服务尚未启动.您需要查看kubectl logs(并确保您的服务代码写出可用的诊断信息)以了解您所处的情况。

【讨论】:

【参考方案4】:

k8s 中没有“depends_on-like”选项,我认为它没有实现只是因为在云原生(=微服务)环境中,应用程序应该是无状态的。无状态也意味着任何应用程序都不应该知道另一个应用程序的状态:每个应用程序都应该能够随时启动、终止、恢复而不影响其他应用程序,当然平台服务可能会出现质量下降!

如果您有这种限制(如果您部署消息代理并且每个消费者都必须等待它启动并运行才能建立连接,这是合理的),您必须以“无状态方式”管理它:例如,您可以阻止引导过程,直到未建立代理连接,然后定期重试。使用 kubernetes healthcecks,您甚至可以在该时间窗口内声明您的服务“未准备好”,或者在多次重试失败时声明“不健康”

您可以在其他上下文中翻译此模式,尝试举例说明您要实现的目标

【讨论】:

【参考方案5】:

我希望你的容器已经定义了liveness probe。在依赖部署中使用它们来创建一个 initContainer 来检查应用程序是否准备就绪。 initContainer 验证其他容器就绪后,依赖容器启动。

您在使用 initContainer 时遇到的具体问题是什么?使用 initContainer 启动依赖容器的示例链接是here。

另一种方法是编写一个外壳包装器,然后创建初始部署。然后使用 until 循环等待初始部署状态就绪。然后触发依赖于初始部署的部署。

【讨论】:

【参考方案6】:

正如许多其他答案所述,如果 pod/服务不可用,微服务架构中的应用不应中断

但是,即使是这样,Kubernetes 也应该足够聪明,可以自动尝试从故障中恢复并重新启动 pod。这应该重复,直到应用程序的依赖项得到满足。

Kubernetes 本质上不是发布管理器,而是一个平台。如果您需要按顺序或特定顺序部署 pod 或服务,您可能需要查看实际的发布管理器,例如 Helm,使用特定的部署/设计模式,例如伞形图模式 (@ 987654322@)。这可能包括一些额外的工作,但可能是您正在寻找的。

我真的希望这至少对你有所帮助。 :)

【讨论】:

谢谢,我不知道我们可以用helm来做这个,我会研究一下。 绝对不用担心。但是,如前所述,以helm 方式进行操作非常繁琐,并且需要大量配置。虽然如果您想要零部署等可能是值得的。如果您需要任何进一步的帮助,请随时联系我。 :)【参考方案7】:

正如其他答案中已经回答的那样,您无法在部署之外定义 POD 之间的初始化顺序。

每个部署 (POD) 都是一个独立的单元,应该有自己的生命周期,如果一个 POD 依赖于其他 POD 来运行以进行初始化,您可能需要审查您的设计。

如果 POD 在启动时已启动,而在另一个 POD 启动后出现故障,会发生什么情况? 如果 POD B 正在更新,然后 POD A 更新?

你应该设计你的系统,他们总是会失败,如果服务 B 在服务 A 之前启动,POD 的行为将与它们以正确的顺序和服务 A 启动的方式相同(即依赖于 B ) 之后失败了。

您的应用程序应该处理这些,而不是将其卸载到编排器。

.

如果您确实需要实现排序和更改应用程序是没有问题的,您可以使用init containers 向其他容器中的健康(就绪)端点发出请求,与 K8s 的检查方式相同如果您的容器准备就绪,当他们以成功的响应回答时,您就完成了 init 执行并让 POD 运行其他容器。

【讨论】:

以上是关于如何在 Kubernetes 中按特定顺序配置 Pod 初始化?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JUnit4 中按特定顺序运行测试方法?

在 Solr 中按特定顺序按多个字段排序

是否可以针对特定字段在 mysql 或 mongodb 中按顺序保存数据?

如何在具有可写流的循环中按顺序在 Node 中写入流?

如何在 ScalaTest / SBT 中按顺序运行测试套件?

如何在 mongoDb 中按多个字段排序