我有一个关于 Kubernetes 集群的基本问题。假设您有一个 pod,并且需要更新 pod。在此期间不应有停机时间。当然也许状态或会话丢失了,但我对 pod 更新过程更感兴趣。
当 pod 由配置了滚动更新的部署控制时,将创建一个新 pod,旧 pod 将开始终止,一旦新 pod 健康,旧 pod 将被删除。当副本配置为 1,并且临时实际副本变为 2 时,会发生此行为。
当 Pod 由配置了滚动更新的 Statefulset 控制时,Pod 会立即被删除并再次重新创建,因此存在停机时间。仅当副本配置为 >= 2 时,此行为才会改变。但这样,总是有两个 pod。
有人可以解释一下,或者是否有办法解决此行为?
StatefulSet 的关键设计点是它是有状态的:每个副本都有自己对应的 PersistentVolumeClaim。 在许多服务器中,您不能让多个进程同时访问相同的本地文件(如果存在锁定文件,大多数数据库服务器将拒绝启动)。 此外,更容易获得的 PersistentVolume 类型往往只允许 ReadWriteOnce 访问;它们不能附加到多个节点。
因此,对于在 StatefulSet 中运行的工作负载,通常不能同时运行旧 Pod 和新 Pod。
如果您需要在 StatefulSet 中进行零停机更新,则大部分繁重的工作需要在流程内实现。 多节点复制数据库就是一个很好的例子(想想 MongoDB 或 Elasticsearch)。 任何特定数据通常存在于至少两个副本上(可配置)。 如果一个副本暂时宕机,另一个副本可以接替其责任,并且其数据仍然存在;当它回来时,它可以重新加入集群并获取它错过的更新。
另一个推论是,您无法对单副本 StatefulSet 进行零停机更新。 再次考虑单节点非复制数据库(MySQL 或 PostgreSQL):即使您可以启动两个具有相同 PersistentVolume 的 Pod,只要锁文件存在,第二个 Pod 中的数据库进程就不会启动,并且将一直存在,直到第一个 Pod 退出。 Deployment 将等待终止旧 Pod,直到新 Pod 的活动性和就绪性探测通过,但如果数据库进程正在等待声明锁定文件,则这种情况永远不会发生。