欢迎参与 8 月 1 日中午 11 点的线上分享,了解 GreptimeDB 联合处理指标和日志的最新方案! 👉🏻 点击加入

Skip to content
On this page
技术
2023-11-02

混沌工程——是谁背着我偷偷写 Bug 🤸

GreptimeDB 支持以单机和分布式的形式进行部署,但紧随而来一个尖锐的问题:我们对投入生产的这套复杂系统有多少信心?因此,在 0.3 到 0.4 迭代的过程中,我们引入了混沌工程(Chaos engineering)来提高系统的健壮性。

(一)混沌工程是怎么实施的

我们选择了 Chaos Mesh 作为故障注入工具。我们在 Pod 中运行一个测试程序(Testcase) ,该程序通过定义 CR(Custom Resource)为 DB 集群中特定的 Pod 注入故障;并在转移故障后,对 DB 集群的可用性和数据完整性进行验证。

下面是一个示例,向 greptimedb-cluster 命名空间中名为 greptimedb-datanode-1 的 Pod 注入一个 Pod Kill 的故障。

yaml
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  namespace: greptimedb-cluster
spec:
  action: pod-kill
  mode: one
  selector:
    filedSelectors:
      'metadata.name': 'greptimedb-datanode-1'

为了便于调试测试程序,测试程序在开发环境中可以直接运行在主机上,并通过 Kubectl 的端口转发访问 K8s 中的 DB 服务。

(图 1:测试用例运行演示)
(图 1:测试用例运行演示)

(二)一些探索和经验

从最小场景开始

测试覆盖不高时,可能会有一些“负负得正”的情况,让整套系统看起来“正常”运行(实际上即使覆盖率较高,也依然可能存在这些问题)。所以我们可以从最小场景开始测试,这个阶段你需要非常清晰地知道系统的预期行为,并通过查看系统日志,判断系统的行为是否真的符合预期,以便发现问题后及时补相应的集成测试。

例如,我们需要验证系统是否能容忍 Datanode 节点被 Kill,并触发 Region Failover 流程(即将 Region 迁移到其他可用节点)。我们可以通过构建一个最小场景(少量表,少量数据)来进行验证,通常当故障被注入到故障真正发生会有一定的时间间隔,此时我们需要一些方法去判断系统是否真实发生故障了。

通常有几种做法:通过调用 Kube API 观察 ReplicatSet 的 Pod 副本数量少于预期;亦或是通过对目标节点进行读写来感知——在观测到故障前不间断的发起一些(少量的)将会路由到目标节点的读写操作,当客户端会返回故障时,即可视为目标节点不可用。随后等待集群恢复(例如调用 Kube API 等待 ReplicatSet 的 Pod 副本数量回到预期),我们就可以开始验证服务可用性和数据的完整性。

尽可能贴近真实的场景

GreptimeDB 可以将数据保存在 AWS S3 或者阿里云 OSS 等等这样的廉价对象存储上。S3 这类存储相比本地存储来说,在测试中还是有不少差异的,主要体现在对 S3 访问的延迟上。应尽早地贴近真实场景,即测试使用 S3 存储的 DB 集群。我们在开发测试程序的时候,也要将被测试 DB 集群的数据存储在靠近开发环境的 S3 中。

梳理思路 + 补充集成测试

在开始混沌测试前,尽可能地把思路梳理清晰,在集成测试中把将要测试到链路进行覆盖。混沌测试还是有不少额外工作量的,前期把测试做到位能节省不少时间。当然混沌测试和集成测试也可以说是相辅相成的,有些问题只有你真的在混沌测试中遇到了,才会打破你之前的一些判断:“哇*,原来这个不是我想的小概率事件🤣”。

关注偶发的问题

(图 2:测试用例逻辑演示)
(图 2:测试用例逻辑演示)

任何偶然发生的问题都要深究,对于小概率发生的问题其实需要大量的重试,并通过日志精准地定位问题。

构建可复用故障

构建一个混沌测试需要投入不少精力:通常注入一个故障,其中会涉及到多个步骤,例如注入故障,观察到故障发生,等待服务完全恢复等。通过对这些步骤进行抽象,我们可以做到实现注入一个故障,测试多个不同的场景

(三)在混沌工程中发现的 Bugs

我们在混沌工程中发现的 Bugs 主要集中在以下几类:

  • Trait 的不同实现,行为不一致;

  • 字段或接口冗余;

  • 多个 Bug 叠加,负负得正;

  • 未使用别名造成的歧义;

  • Corner Case 中数据与缓存不一致;

  • 迭代过程中多人协作造成的一些遗漏。

我们还很意外地发现了一个上游的 Bug,OpenDAL FsBackend 的异步写入在 sync_all 之前未调用 flush,导致其有潜在丢失数据的风险。我们在 0.4 版本中及时反馈并修复了这个 Bug,可以通过下面链接详细了解:

关于 Greptime

Greptime 格睿科技专注于为可观测、物联网及车联网等领域提供实时、高效的数据存储和分析服务,帮助客户挖掘数据的深层价值。目前基于云原生的时序数据库 GreptimeDB 已经衍生出多款适合不同用户的解决方案,更多信息或 demo 展示请联系下方小助手(微信号:greptime)。

欢迎对开源感兴趣的朋友们参与贡献和讨论,从带有 good first issue 标签的 issue 开始你的开源之旅吧~期待在开源社群里遇见你!添加小助手微信即可加入“技术交流群”与志同道合的朋友们面对面交流哦~

Star us on GitHub Now: https://github.com/GreptimeTeam/greptimedb

官网:https://greptime.cn/

文档:https://docs.greptime.cn/

Twitter: https://twitter.com/Greptime

Slack: https://greptime.com/slack

LinkedIn: https://www.linkedin.com/company/greptime/

加入我们的社区

获取 Greptime 最新更新,并与其他用户讨论。