首页 > 解决方案 > 如何在 k8s 中等待其他容器完成执行?

问题描述

假设我有一个 appA容器和另一个名为的容器resources-preparation,它将尝试创建 DB 表等以引导 app A

应用A容器和resources-preparation容器位于不同的 pod 中。A容器完成后如何调出 App容器resources-preparation

PS:resources-preparation容器根本不是服务。所以我可能无法使用waitfor图像来检测resources-preparation容器是否完成。

标签: dockerkubernetesgoogle-kubernetes-engine

解决方案


似乎存在一种架构不一致:现有的应用程序架构不能很好地适应 Kubernetes 范式:

  • podA与pod 绑定resources-preparation,因此必须等待其成功完成,而 k8s 假设独立或松散耦合的微服务。
  • 由于紧密依赖,容器Aresources-preparation放置在不同的 Pod 中,而辅助应用程序应该与主容器放置在同一个容器中。请参阅讨论在同一 Pod 中的容器之间进行通信
  • podA依赖于外部数据库,而在 k8s 中,微服务应该使用自己的数据库或副本来保持独立性。
  • pod应该通过 k8s API 进行通信Aresources-preparation这意味着 podA应该resources-preparationkube-apiserver.

列出的原则会导致额外的开销,但这是您为 Kubernetes 所依赖的冗余所付出的代价。

解决问题的可能方法:

  1. 按照 k8s 的原则对应用和后端数据库进行相应的重新设计或修改,分解成一组松耦合的微服务。作为一个假设:

    • a) 让应用程序A独立地从其数据库副本开始;
    • b) 并行让其resources-preparation在自己的副本中启动和创建表;
    • c) 然后将新表添加到现有 Replication 或创建新 Replication。在这种方法中,吊舱A不必等待吊舱resources-preparation。数据库复制将改为等待。这样,依赖关系就会从 k8s 级别移到上层。

    不幸的是,将现有应用程序适应 k8s 可能具有挑战性,并且通常需要从头开始重新开发应用程序。这是一项耗费时间和资源的任务。

    此处提供了一份很好的白皮书:基于容器的应用程序设计原则

  2. 由于resources-preparation是 的辅助容器,因此A将两个容器放入同一个 pod。这样,来自Init Containers 概念的示例代码将完全满足容器的A需要。A对于等待完成的容器来说,重要的resources-preparation是:

    • 初始化容器总是运行到完成
    • 每个 init 容器必须在下一个启动之前成功完成。
  3. 如果由于某种原因不能将两个容器加入到同一个 pod 中,作为一种变通方法,可以将应用程序组件放入“包装器”中,帮助它们假装表现为松散耦合的微服务。这个包装器应该在 pod 级别以下实现,以便对 Kubernetes 透明:围绕容器或应用程序。在一个简单的情况下,您可以A从带有until循环的 shell 脚本中启动应用程序。脚本应该通过 获取在StatefulSetresources-preparation中运行的 pod 的状态,以决定应用程序是否可以启动。kube-apiserverA

    可以为此使用 REST API 请求(请参阅答案Kubernetes API server, serving pod logs)。

    kube-apiserver应该提供一种对 API 请求进行身份验证的方法才能正常工作。理论和实际例子在这里:

    使用 Kubernetes API 访问集群

    卷曲 Kubernetes API 服务器


推荐阅读