我有一个关于 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 退出。部署将等待终止旧 Pod,直到新 Pod 的存活和就绪探测通过,但如果数据库进程正在等待认领锁定文件,则这种情况永远不会发生。