10分钟带你彻底搞懂集群容错和服务隔离

本文深入浅出地介绍了分布式系统中的集群容错策略,如Failover、Failback、Failsafe和Failfast,以及服务隔离技术,如线程隔离、进程隔离和集群隔离,帮助开发者提升服务可用性和可靠性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

十分钟搞懂系列

序号标题链接
110分钟带你彻底搞懂企业服务总线https://blog.youkuaiyun.com/belongtocode/article/details/119487731
210分钟带你彻底搞懂微内核架构https://blog.youkuaiyun.com/belongtocode/article/details/119107837
310分钟带你彻底搞懂服务限流和服务降级https://blog.youkuaiyun.com/belongtocode/article/details/119107785
410分钟带你彻底搞懂负载均衡https://blog.youkuaiyun.com/belongtocode/article/details/118977839
510分钟带你彻底搞懂集群容错和服务隔离https://blog.youkuaiyun.com/belongtocode/article/details/118968771
610分钟带你彻底搞懂注册中心https://blog.youkuaiyun.com/belongtocode/article/details/118639474
710分钟带你彻底搞懂RPC架构https://blog.youkuaiyun.com/belongtocode/article/details/118639448

在分布式系统中,由于网络条件以及系统自身缺陷等问题,服务与服务的调用过程难免会出现失败。为了把这种失败的影响程度降到最小,目前,业界有两种主流的最佳实践方案,分别是集群容错和服务隔离。这节课,我就带你利用这两种方案来解决服务雪崩效应,帮你提升分布式系统服务访问的可靠性。

假如你正在设计和开发一个分布式服务系统,该系统中存在一批独立运行的服务实例。围绕某一个具体的业务场景,通常都会涉及多个服务之间的交互。

img

在这个典型场景(图 1)中,存在一个从服务 E 到服务 A 的完整调用链路。如果其中有一个服务出现了宕机,那么整个调用链路中的其它服务因为资源的竞争也会处于不可用状态,这种扩散效应就是所谓的服务雪崩效应。

我们该怎么应对这种服务雪崩效应呢?

集群容错策略

目前主流的应对策略是提供服务访问的容错(Fault Tolerance)机制。想要实现容错机制,集群就要做到冗余,也就是让每个服务具备多个实例。这样,当一个服务实例出现问题时,请求还可以尝试访问其它服务实例。

我们知道,集群的构建相当于已经具备了冗余的条件,而要想在访问一个服务实例出现问题时确定下一个想要访问的服务实例,就涉及具体的集群容错策略了。

常见的集群容错策略包括 Failover、Failback、Failsafe 和 Failfast 等。下面我们一一来了解。

Failover 是最常见、最实用的集群容错策略。它又叫失效转移策略,当发生服务调用异常时,可以重新在集群中查找下一个可用的服务实例。同时,为了防止无限重试,开发人员通常会对失败重试最大次数进行限制,一般控制在 3 次之内。

img

对应的,Failback 可以理解为失效自动恢复。当请求失败时,系统会把这个失败请求记录下来,并通过一定的定时机制进行重试。这种策略适用于那些对时效性要求不高的场景,例如消息通知。

而 Failsafe 代表失败安全策略,当获取服务调用异常时,直接忽略。它通常将异常写入审计日志等媒介,确保后续可以根据日志记录找到引起异常的原因并解决。

Failfast 也叫快速失败策略,它在获取服务调用异常时,立即报错。显然,Failfast 已经彻底放弃了重试机制,等同于没有容错,可以用于非幂等性的写入操作,这是一种常见的应用场景。而在特定场景中也可以使用该策略确保非核心业务服务只调用一次,为重要的核心服务节约宝贵时间。

后三种集群容错策略很容易混淆,它们之间的区别你可以参考这张图:

img

除了这些最常见的集群容错机制之外,在诸如 Dubbo 等主流分布式服务框架中,开发人员还实现了一些特殊的策略。比如 Forking 策略代表一种分支调用机制,在这种机制下请求会同时发送给集群中的多个服务实例,只要有一个服务实例响应成功就行。再比如 Broadcast 策略,代表的是一种广播机制,这种机制同样也会调用所有服务实例,但只有在所有调用都成功的情况下才会返回成功。从适用场景上讲,Forking 机制适用于实时性要求较高的场景,而 Broadcast 机制通常用于实现消息通知,不是简单的远程调用。

服务隔离策略

除了集群容错策略外,应对服务雪崩还有一种有效手段,就是服务隔离。

在架构设计领域存在一个舱壁隔离(Bulkhead Isolation)的架构模式,服务隔离的设计思想真是来自于此。那么,什么是舱壁隔离?你可以想象一艘船,这艘船有 8 个船舱,正常情况下,船舱壁是隔离海水或湖水的,如果一个船舱破了,进水了,那么只损失一个船舱,其它船舱可以不受影响。比如这张示意图,2 号和 8 号船舱虽然已经出现问题,但不影响其它 6 个船舱。

img

结合分布式服务架构中的应用场景,舱壁隔离模式的具体体现就是各种服务隔离机制。

其实,隔离本质上是对系统中的服务进行分割,这样当系统发生故障的时候,就能控制影响范围。也就是说,隔离可以保证发生故障后只有出问题的服务不可用,其它服务仍然可用。

img

我们一起来看一下服务隔离的基本思路图。图中的隔离媒介是服务隔离实现的关键,针对它业界有一些成熟的实现方案,常见的包括线程隔离、进程隔离、集群隔离以及读写隔离等。

线程隔离

我们先来看看最常见的线程隔离。我们知道。系统执行一个请求的基本单位是线程,所以使用线程隔离就相当于对请求与请求之间的资源进行了隔离。在日常开发过程中,我们通常使用线程池来创建线程,因此线程隔离的主要实现手段就是借助于线程池。当把不同的请求分配到不同的线程池进行处理时,就算一个线程池出现了问题,也不会把问题扩散到其它线程池。各个线程池之间相互独立,各自确保自身业务的处理过程和可用性。

线程隔离可以说是实现服务隔离的基础,我们通过一个案例来进一步介绍它的工作场景和原理。假如系统存在服务 A、服务 B 和服务 C 这 3 个服务,我们通过设置运行时参数得到这 3 个服务一共使用 300 个线程,客户端调用这 3 个服务会共享线程池。

img

你看这张示例图,如果服务 A 出现了问题,那么所有访问它的线程就会因为同步等待响应结果而不断消耗线程资源,最终导致雪崩效应:

img

这里边框为虚线的服务代表不可用,我们可以看到因为服务 A 不可用导致共享的 300 线程全部耗尽,从而影响了其它两个服务。因此基于线程隔离机制,我们就可以为每个服务分别创建独立的线程池,从而对资源进行隔离,这样就能够避免雪崩效应的产生。

下面,我们为三个服务都独立分配 100 个线程再来看看:

img

调整之后,我们会发现就算服务 A 中的 100 个线程都已经被消耗殆尽,其它服务中的请求过程也不会受到影响,因为它们运行在独立的线程池中。

进程隔离

讲完线程隔离,我们再来看进程隔离。进程隔离把资源的隔离范围从线程上升到进程,在 Java 世界中,相当于就是上升到了 JVM 级别。这样,我们就可以把整个业务系统拆分为多个独立的子系统,每个子系统完成自身的请求,而不依赖于其它子系统,目前主流的微服务架构就是这一隔离机制最好的实践。

集群隔离

集群隔离是进程隔离的升级版,将某些服务单独部署成集群,或对于某些服务可以进行分组集群管理,某一个集群出现问题之后就不会影响到其它集群,从而实现了故障隔离,效果图如下所示:

img

读写隔离

读写隔离也是一种常见的隔离技术,当用于读取操作的服务器出现故障时,写服务器照常可以运作,反之也是一样。对于离线分析类的应用场景而言,读写隔离可以很好地控制读取操作瓶颈和对写入操作的影响。

实际运用中,读写隔离可以有不同的表现形式。例如,当使用 MongoDB 进行海量数据存储时,我们可以采用热库和存档库概念,将新写入的数据同时存储到热库和存档库。热库只存储最近一个月的数据,而存档库则保存所有的历史数据。当我们想对历史数据进行读取处理时,可以确保热库不受影响。

总结

总的来说,在日常开发过程中,你可以使用这节课介绍的集群容错和服务隔离机制来为分布式系统提升服务访问的可靠性。我再给你梳理一下这节课的关键知识点。

在分布式系统中,错误总会发生,处理不好就会形成雪崩效应,我们应对雪崩效应的核心思想是努力控制它的影响范围。一方面,我们可以借助于集群机制以及 Failover、Failback、Failsafe 和 Failfast 等机制来实现集群容错;另一方面,我们可以使用线程隔离、进程隔离、集群隔离以及读写隔离等等策略来实现服务隔离。针对日常场景,集群容错一般都是主流框架所默认提供的机制。而服务隔离方面,我建议你合理利用线程隔离和进程隔离来综合使用不同粒度的隔离机制,确保服务的高可用。

参考文章:
整理于极客时间每日一课对应文章

<think>嗯,用户的问题是关于Rook部署的Ceph集群无法删除,因为CephBlockPool一直处于创建中的状态。首先,我需要回忆一下Rook和Ceph的关系,Rook是在Kubernetes上管理存储系统的Operator,而Ceph是一个分布式存储系统。当用户尝试删除集群时,如果某个资源如CephBlockPool卡在创建中,可能会导致删除失败。 首先,用户可能已经尝试过直接删除集群,但遇到了阻碍。常见的情况是,Kubernetes的Finalizers机制会等待资源彻底清理完毕才允许删除,但如果资源卡住,Finalizers可能无法完成,从而阻塞整个删除过程。这时候需要手动干预,比如删除Finalizers。 接下来,我应该分步骤思考解决方案。第一步,检查CephBlockPool的状态,使用kubectl命令查看具体信息,看看是否有错误信息。如果发现它卡在删除中,可能需要手动清理相关的Finalizers。然后,检查Rook Operator的日志,看看是否有相关错误,比如资源无法释放或底层存储问题。 另外,还需要确保所有使用存储资源的PVC和PV都已被删除,否则Ceph可能无法正常终止。用户可能忽略了某些残留的PVC,导致CephBlockPool无法删除。此外,直接删除命名空间可能也是一种方法,但需要确保其他资源已经被清理,否则可能无法立即生效。 如果手动清理Finalizers后仍然无法删除,可能需要更彻底地清理Rook的配置和数据,比如删除/data/rook目录,这需要进入节点执行,但要注意数据丢失的风险。最后,重建集群时的注意事项,比如确保所有依赖项正确,也是需要提醒用户的。 需要注意的安全事项包括备份数据,避免直接删除Finalizers导致的问题,以及处理节点上的残留数据。用户可能在操作过程中遇到权限问题,或者残留数据导致新集群的问题,所以这些点都需要强调。 总结步骤应该是:检查资源状态→删除Finalizers→清理关联资源→检查Operator日志→强制删除命名空间→清理节点数据→重建集群。同时提醒用户谨慎操作,避免数据丢失。</think>针对Rook部署的Ceph集群因CephBlockPool卡在创建状态导致无法删除的问题,可按以下步骤排查和解决: --- ### 一、问题根源分析 1. **Finalizer阻塞**:Kubernetes资源(如CephBlockPool)的`finalizers`字段会等待关联资源清理完成,若底层存储操作异常,会导致删除流程卡死。 2. **Rook Operator状态异常**:Operator可能因权限、资源不足或BUG无法完成清理动作。 3. **残留数据未释放**:底层OSD设备或存储池数据未被彻底清除。 --- ### 二、手动清理步骤 #### 步骤1:强制删除CephBlockPool ```bash # 查看CephBlockPool状态 kubectl -n rook-ceph get cephblockpool # 若状态为Deleting或长期Pending,移除finalizer kubectl -n rook-ceph patch cephblockpool <pool-name> -p '{"metadata":{"finalizers":[]}}' --type=merge ``` #### 步骤2:清理关联资源 ```bash # 删除所有关联PVC/PV(确保数据已备份!) kubectl delete pvc --all -n rook-ceph kubectl delete pv --all # 删除CRD定义(关键操作!) kubectl delete crd cephblockpools.ceph.rook.io ``` #### 步骤3:检查Rook Operator日志 ```bash kubectl -n rook-ceph logs -l app=rook-ceph-operator --tail=1000 # 观察是否有权限错误(如访问s3失败)、资源争用或Ceph状态异常提示 ``` #### 步骤4:强制删除命名空间 ```bash # 若rook-ceph命名空间卡在Terminating状态 kubectl get ns rook-ceph -o json | jq '.spec.finalizers = []' > rook-ceph.json kubectl replace --raw "/api/v1/namespaces/rook-ceph/finalize" -f ./rook-ceph.json ``` --- ### 三、底层存储清理 #### 1. 物理节点清理 ```bash # 在所有节点执行(危险操作!将永久删除Ceph数据) sudo rm -rf /var/lib/rook sudo wipefs -af /dev/<ceph-osd-disk> # 清理OSD磁盘头信息 ``` #### 2. 清除multus网络残留(如使用网络隔离) ```bash ip link delete cni0 # 删除虚拟网桥(按需操作) ``` --- ### 四、重建集群注意事项 1. **预检项**: ```bash lsblk # 确认磁盘无残留分区 dmesg | grep -i ceph # 检查内核级错误 ``` 2. **部署参数**: 在`cluster.yaml`中增加容错配置: ```yaml spec: cleanupPolicy: confirmation: yes sanitizeDisable: false # 强制擦除元数据 ``` --- ### 五、避坑指南 1. **Finalizer谨慎操作**:直接清空finalizers可能导致资源泄漏,需确认关联资源已无依赖。 2. **Operator版本对齐**:确保卸载时使用的Rook版本与安装时一致,避免API兼容性问题。 3. **日志关键字段**:在Operator日志中搜索`OP_FAILED`或`failed to reconcile`定位具体错误点。 通过上述步骤可系统性解除删除阻塞状态。若问题仍存在,建议提供`kubectl describe cephcluster -n rook-ceph`输出进一步分析。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Apple_Web

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值