【发布时间】:2020-03-13 18:52:43
【问题描述】:
我正在尝试使用 Kubernetes 上的 Spring-Kafka 在 Kafka 上实现一次性交付。 据我了解,必须在生产者上设置 transactional-ID,并且在重新启动时应该相同,如此处所述https://stackoverflow.com/a/52304789/3467733。
在 Kubernetes 上使用这种语义会出现问题。 如何获得一致的 ID?
为了解决这个问题,我实现了一个 Spring boot 应用程序,我们称之为“副本计数器”,它通过 Kubernetes API 检查有多少与调用者同名的 pod,所以我为每个 pod 都有一个计数器复制品。
例如,假设我要部署一个 Pod,我们称之为APP-1。
此应用执行以下操作:
- 它对 Replicas-Counter 执行
GET,将 pod-name 作为参数传递。 - replicas-counter 调用 Kubernetes API 以检查有多少具有该 pod 名称的 pod。所以它会执行一个 +1 并将其返回给调用者。我还需要计算未就绪的 pod(想想第一次部署,如果我不检查未就绪的 pod,他们就无法获得 ID)。
- APP-1 获取 id 并将其用作 transactional-id
但是,正如您所见,执行滚动更新时可能会出现问题,例如:
假设我们有 3 个 pod:
一开始我们有:
- app-1:transactional-id-1
- app-2:transactional-id-2
- app-3:transactional-id-3
因此,在滚动更新期间,我们将:
-
old-app-1:transactional-id-1
-
old-app-2:transactional-id-2
-
old-app-3:transactional-id-3
-
new-app-3:transactional-id-4(未准备好,等待准备好)
New-app-3 准备就绪,因此 Kubernetes 关闭了 Old-app-3。所以是时候继续滚动更新了。
-
old-app-1:transactional-id-1
-
old-app-2:transactional-id-2
-
new-app-3:transactional-id-4
-
new-app-2:transactional-id-4(未准备好,等待准备好)
如您所见,我有 2 个具有相同事务 ID 的 pod。
据我了解,这些 ID 在重新启动时必须相同且唯一。
如何实现能够提供一致 ID 的东西?有人处理过这个问题吗?
这些 ID 的问题仅适用于 Kubernetes 部署,而不适用于 Stateful-Set,因为它们有一个稳定的标识符作为名称。我不想将所有部署转换为有状态集来解决这个问题,因为我认为这不是处理这种情况的正确方法。
【问题讨论】:
-
StatefulSets 是真正可行的方法。
-
@ThomasJungblut 所以你不认为这是对这种 Kubernetes 资源的滥用吗?这样,每个生产者应用程序都将是一个 sts
-
这是保证 pod 在重新启动时保持一致标识符的唯一方法,不,我认为这不是滥用。
-
正如@ThomasJungblut 建议的那样,您应该使用
StatefulSets来获得稳定的pod 标识符。这是一篇描述为什么在这种情况下应该使用StatefulSets的文章:blog.yugabyte.com/…
标签: kubernetes apache-kafka spring-kafka