0

我需要以“最多一次”语义运行我的应用程序。在任何给定时间只运行我的应用程序的一个实例或根本不运行,这绝对是至关重要的

起初我使用具有单个副本的资源类型“部署”,但后来我意识到在网络分区期间,我们可能无意中运行了多个实例。

当我在 kubernetes 中搜索最常用的语义时,我偶然发现了“有状态集”。进一步阅读,这些示例处理了容器需要持久卷并且通常这些容器运行多个副本的情况。我的应用程序甚至没有使用任何卷。

如果节点无法访问,我还阅读了关于杀死 pod 的容忍度。鉴于容忍可以处理 pod 无法访问的情况,有状态设置对我的用例来说是否过度杀伤?

我正在证明使用有状态集是合理的——因为即使在那个时候节点变得无法访问并且达到了容忍秒数,并且 kubelet 意识到它已与网络断开并杀死进程,kubernetes 可以启动另一个实例。而且我相信有状态的集合也可以防止这种极端情况。

我对吗?有没有其他方法可以实现这一目标?

4

3 回答 3

3

引用Kubernetes 文档

...StatefulSet 为其 Pod 维护一个粘性、稳定的身份...保证每个 Pod 的身份有助于避免在节点变得无法访问(网络分区)的情况下出现脑裂副作用。

如同一文档中所述,节点上的 StatefulSet Pod 被标记为“未知”并且不会重新调度,除非在节点变得无法访问时强制删除。如果走这条路,需要考虑适当的恢复。

所以,是的——StatefulSet 可能比 Deployment 更适合给定的用例。

在我看来,使用 StatefulSet 并不过分——选择最适合您的用例的 Kubernetes 对象。

于 2019-12-23T02:33:30.577 回答
1

在任何给定时间只运行我的应用程序的一个实例是绝对关键的。

使用领导者选举模式来保证最多一个活动副本。如果您使用多个副本和领导者选举,则其他副本在网络分区情况下处于备用状态。这就是Kubernetes 控制平面中的组件在只需要一个活动实例时解决此问题的方式。

Kubernetes 中的领导者选举算法通常通过超时锁定(例如在 etcd 中)来工作。只有拥有锁的实例是活动的。当锁超时时,leader选举算法要么延长锁超时时间,要么选举一个新的leader。它的工作方式取决于实现,但可以保证最多有一个领导者- 活动实例。

参见例如Simple Leader Election with Kubernetes,它还描述了如何在边车容器中解决这个问题。

如果您的应用程序是无状态的,您应该使用Deployment而不是StatefulSet. 看起来这StatefulSet是一种在网络分区情况下最多解决一个实例的方法,但这主要是在有状态复制应用程序的情况下,例如缓存或数据库集群,即使它也可以解决您的特定情况。

于 2019-12-22T21:49:22.207 回答
1
  • Statefulsets 最多不是一种语义的资源——它们通常用于部署“状态完整”的应用程序,例如数据库,这些应用程序使用其 pod 的持久身份在它们之间进行集群

  • 我们遇到了类似你提到的问题 - 我们隐含地假设在启动新实例之前将完全删除旧 pod

  • 一种选择是使用 preStop hooks + init-containers 组合的组合

  • preStop hook 将进行必要的清理(比如删除应用程序特定的 etcd 键)

  • 初始化容器可以等到 etcd 键消失(有上限)。

参考:

https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

一种替代方法是尝试使用反关联设置,但我对此不太确定

于 2019-12-23T09:41:30.287 回答