从Pod漂移,看容器存储如何选择
Yoho  2024-07-24 14:32  发布于中国

Pod漂移是Kubernetes最重要的特性之一,是Kubernetes实现灵活调度和高可用的核心功能。今天,我们就从Pod漂移出发,浅析如何选择容器下的存储。

我们首先简单解释一下什么是Pod漂移。在Kubernetes中,所有的微服务都是由一个一个Pod构建而成,Pod中包含一个或多个容器,它是Kubernetes资源管理的最小单位。在Kubernetes中,无论ReplicaSet、Deployment,还是StatefulSet,这些Pod控制器都会根据配置维持一定的Pod副本数量。当一个节点上的Pod不可访问时,控制器会发现并不断重试等待其响应;如果超过一定时间不响应,控制器会驱逐该Pod,并尝试重新拉起新Pod。如果Pod不可访问是由节点故障导致,Pod会在另一个正常节点上重新拉起,这个过程就叫做Pod漂移。Pod漂移机制保障了单节点故障后,集群会自动补从,维持服务的高可用。

Kubernetes诞生初期是面向无需持久化数据的应用设计的,默认在Pod删除后丢弃数据,并不需要考虑Pod漂移后的数据访问问题。但随着容器承载应用的演进发展,数据持久化存储成为刚需。如何保证Pod漂移后数据可访问是Kubernetes需要解决的关键问题之一,接下来我们分别针对无状态应用和有状态应用,分析采用哪种容器存储能更好的匹配漂移后的数据访问需求。

先看无状态应用。无状态应用部署最常用的控制器是Deployment。它的设计是基于Pod之间没有任何区别和优先级顺序的假设,也不需要保存任何会话的状态数据。因此,Deployment对于不同Pod访问的数据是否一致并不关心;如果不特别设置调度亲和性,Deployment可以在任意节点拉起Pod。但Deployment并不意味着不需要持久化卷(PersistentVolume,PV)。以开发测试中常用的Jenkins为例,Jenkins通常使用Deployment部署,而Jenkins的任务、构建、账户等信息都会以文件的方式存储,所以Jenkins也需要配置PV来实现数据持久化。

采用服务器本地盘:如果使用HostPath作为持久化目录,节点故障后,其上部署的所有Pod漂移到其他节点,而目的节点上并没有原节点的数据,漂移后数据无法访问。如果PV类型是LocalPV,由于新节点上可能没有和模板定义一致的路径,会导致Pod无法漂移。上述两种场景可以看出,Deployment下服务器本地盘并不是最佳选择。

• 采用外置块存储,比如iSCSI SAN:由于LUN与主机间是一一映射关系,为了保证PV只被一台主机读写, Kubernetes设计了AttachDetachController,它负责把外置块存储类型的PV与主机建立Attach关系,防止别的主机使用该PV。当某个节点故障时,Pod需从一个节点漂移到另一个节点;但由于PV已经Attach给了故障节点,Controller需要等待6分钟(MaxWaitForUnmountDuration,系统默认设置为6分钟,不可修改)超时后才能将PV与故障节点Detach,对POD漂移速度影响较大。因此,Deployment下采用块存储作为PV也不是一个好选择。

• 采用外置文件存储(如NFS):文件存储支持共享,在K8S中支持配置RWX(ReadWriteMany)模式;它不需要Attach给某一台主机,可以直接挂载(Mount)给多台主机使用。如果某节点故障,Pod漂移到另外一个节点后,CSI可以调度PV立刻挂载给新节点。POD漂移过程中无需等待PV,最快可在一分钟内完成漂移(依赖相关参数配置),大大提升了业务可靠性。因此,在Deployment模式下,采用NAS作为PV是对Pod漂移最友好的选择。

接下来我们讨论有状态应用。有状态应用常用StatefulSet作为控制器。与Deployment不同的是,该模式下POD间有主从先后关系,不同Pod存储不同的数据;例如MySQL容器化部署一般使用StatefulSet模式。

StatefulSet的故障处理机制:StatefulSet的主从Pod之间不会共享数据,它会为每个Pod创建一个PV,并以Pod的名称作为唯一标识。当某个节点故障与集群管理节点失去联系后,StatefulSet会优先尝试重连,并等待一段时间;若仍无法链接,该节点上的Pod会被标记为Delete状态,但不会立刻删除,而是等待节点重新上线后再删除。在Pod被删除之前,集群不会拉起新的Pod。为什么StatefulSet要这样设计呢?原因是StatefulSet认为Pod与管理节点失联不等于Pod停止运行,此时贸然拉起新Pod,并将PV映射给新Pod,可能导致应用读写冲突甚至数据损坏。此时如果需要依靠POD漂移来恢复业务,在没有自动化脚本的情况下,需要人工介入驱逐故障节点,才能实现Pod漂移。该场景下采用不同的存储类型,会对Pod漂移产生怎样的影响呢?

采用服务器本地盘:由于数据只在本节点保存,POD无法漂移。以MySQL为例,通常采用一主多从的配置;如果Master故障,完成主从切换后,需要人为介入创建新实例、等待新实例完成全量数据构建后再作为Slave加入集群。全量数据构建可能需要数小时,而构建过程中集群处于保护降级状态。可见对于有状态应用,采用服务器本地盘也不是一个好选择。

采用外置块存储:前面已经介绍过,当单个节点故障时,Controller需要等待6分钟超时后才会重新把卷Attach到Pod调度的目标节点上。对于StatefulSet,即使人工介入驱逐节点,从驱逐到Pod完全在新节点拉起,也需要至少约7分钟的时间。

采用外置文件存储:当节点故障并被人为驱逐后,Pod漂移到新节点上,PV可以自动Mount到新主机上;只需要1分钟左右就可以完成漂移,这一速度相对于块存储有极大的提升。对于有状态容器,采用NAS作为存储底座,可以实现POD快速漂移,提升可用性。

通过上述对比可见,不论是无状态应用还是有状态应用,采用NAS是实现POD快速漂移的最优选择。究其本质,共享文件系统是实现跨节点共享的必由之路。VMware通过研发VMFS实现了多节点的虚拟机共享一个文件系统,并基于VMFS实现了HA、FT等高可用能力;而在K8S体系下,也需要共享文件系统提供跨节点访问的能力。企业级NAS存储提供了高性能、高可用、高安全的共享文件系统,成为了容器持久化存储的最佳选择。

 

全部回复(
回复
回复