十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MongoDB 与 Antithesis:网络模糊测试拓扑构建与测试编排实践指南

MongoDB 与 Antithesis:网络模糊测试拓扑构建与测试编排实践指南 MongoDB 与 Antithesis网络模糊测试拓扑构建与测试编排实践指南【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo导读本文基于 MongoDB 官方仓库中的 docs/antithesis/README.md 编写系统讲解如何将 MongoDB 各种集群拓扑单节点、副本集、分片集群等打包成 Docker 镜像并上传到 Antithesis 第三方平台在其网络模糊测试network fuzzing环境中运行测试套件并自动生成缺陷报告。读完本文你将掌握 Antithesis 基础镜像体系mongo-binaries、workload、拓扑镜像与docker-compose.yml的编写规范、初始化脚本的存活要求、如何在 Evergreen 中创建新拓扑任务以及 Normal resmoke testing 与 Test Composer 两种测试模式的配置方式并辅以仓库源码docker_cluster_image_builder.py、antithesis_image_build_and_push.sh作为实现级佐证。Antithesis 是什么第三方网络模糊测试环境Antithesis 是一家第三方供应商它提供一个可以进行网络模糊测试的环境。MongoDB 团队将包含docker-compose.yml文件的镜像上传到 Antithesis Docker 仓库这些docker-compose.yml描述了各种 MongoDB 拓扑例如分片集群、副本集。Antithesis 会在自己的环境中对镜像执行docker-compose up从而拉起对应的多容器应用并运行测试套件。关键流程如下构建镜像把描述拓扑的文件docker-compose.yml、初始化脚本、日志目录等打包为拓扑镜像上传到 Antithesis Docker registry启动拓扑Antithesis 基于该镜像执行docker-compose up在真实多容器环境中启动 MongoDB 拓扑注入故障在测试套件运行期间Antithesis 会对拓扑执行网络模糊测试故障注入生成报告测试结束后Antithesis 生成一份缺陷报告标识出被发现的 bug。整个流程在 CIEvergreen侧由 evergreen/antithesis_image_build_and_push.sh 承载它负责登录 Antithesis 仓库、调用 resmoke 构建三类镜像、在本地做一次 sanity check然后推送镜像并在 patch 场景下通过 Antithesis API 触发测试任务。基础镜像构建 MongoDB 测试拓扑的积木base_images目录仓库中位于 buildscripts/antithesis/base_images/包含了创建 MongoDB 测试拓扑的积木这些镜像会在 Evergreen 的 nightly 构建中通过antithesis image build and push任务上传到 Antithesis Docker registry。目录下有两个子镜像mongo_binaries与workload。mongo_binaries系统被测SUT镜像该镜像包含最新的mongo、mongos、mongod二进制可以用来启动mongod实例、mongos实例或执行mongo命令。它是构建被测系统System Under Test拓扑的核心积木。从 mongo_binaries/Dockerfile 可以看到它的关键细节基础镜像为ubuntu:22.04EXPOSE 20000-20100因为 resmoke 从 20000 开始为每个 mongo{d,s} 进程递增分配端口安装curl、python3、llvm-12、libc6-dbg、gdb等调试与运行依赖通过 retry_apt.sh 进行最多 6 次指数退避重试以应对镜像同步期间的 apt 抖动复制tsan.suppressions来自 etc/tsan.suppressions通过构建参数注入ASAN_OPTIONS、UBSAN_OPTIONS、TSAN_OPTIONS并自动追加external_symbolizer_path指向 LLVM symbolizer以及 TSAN 的 suppressions 路径将bin/*复制到/usr/bin/、lib/*复制到/usr/lib/并将libvoidstar.so安装到/usr/lib/libvoidstar.so——libvoidstar.so是 Antithesis 的插桩库二进制必须链接到它才能被 Antithesis 观测CI 构建时会用ldd校验这一点见 docker_cluster_image_builder.py 的_fetch_mongodb_binaries将 MongoDB 源码复制到/mongo最后运行/usr/bin/mongo --version验证安装。本地开发构建时由于开发者一般没有真正的libvoidstar.so构建器会写入一个stub 文件占位见 docker_cluster_image_builder.py 的_add_libvoidstar_to_build_context而在 Evergreen 中则必须使用系统真实的/usr/lib/libvoidstar.so并断言其存在。workload测试执行容器workload镜像包含最新的mongo二进制以及resmoke测试运行器。workload 容器不属于实际拓扑的一部分它的职责是执行mongo命令完成拓扑的初始化设置在已有拓扑上运行测试套件例如buildscripts/resmoke.py run --suite antithesis_concurrency_sharded_with_stepdowns_and_balancer每个拓扑必须恰好有 1 个 workload 容器。注意在workload镜像构建期间evergreen/antithesis_image_build_and_push.sh 运行后会生成antithesis 兼容的测试套件并以antithesis_前缀命名。这些套件才是可以在 Antithesis 中运行的套件它们从workload容器内部可用。从 workload/Dockerfile 可以看到它与 mongo_binaries 镜像的区别额外安装git、software-properties-common并通过 deadsnakes PPA 安装Python 3.13resmoke 项目要求 3.13把python3.13软链为系统python/python3复制 QA 仓库到/QA并软链为/mongo/jstests/qa_tests、jstestfuzz 仓库到/jstestfuzz软链到/mongo/jstestfuzz使用uv版本由 buildscripts/uv_version.txt 锁定在/opt/venv中同步 MongoDB Python 依赖软链 enterprise 模块到/mongo/jstests/enterprise_tests。镜像的获取与构建逻辑无论是mongo_binaries还是workload其构建都统一由DockerComposeImageBuilder驱动见 docker_cluster_image_builder.py在 Evergreen 中master分支的二进制由编译任务产出还需用db-contrib-tool setup-repro-env拉取last-continuous与last-lts二进制本地开发要求安装db-contrib-toolpip install db-contrib-tool或pipx install db-contrib-tool用它下载 Ubuntu 22.04 的 MongoDB 二进制workload 镜像要求存在mongo_enterprise_modules仓库src/mongo/db/modules/enterprise在 Evergreen 中构建时依赖evergreen/antithesis_clone_repos.sh预先克隆 QA、jstestfuzz 等仓库因为 GitHub token 会在构建前提前生成并在一小时后过期不能在构建过程中再执行克隆。拓扑镜像FROM scratch 的文件系统容器拓扑镜像对应base_images中的Dockerfile一节所描述的角色把启动对应拓扑所需的全部文件组装成一个镜像一个docker-compose.yml、一个logs目录、一个scripts目录和一个data目录。只要结构正确你就能从该镜像复制出这些文件与目录然后本地执行docker-compose up复现同样的拓扑。该类镜像在构建时由 docker_cluster_image_builder.py 的_add_docker_compose_configuration_to_build_context动态生成生成出的 Dockerfile 与文档中给出的示例一致FROM scratch COPY docker-compose.yml / ADD --chmod0755 scripts /scripts ADD logs /logs ADD data /data ADD debug /debug若配置了 Test Composer 目录还会额外ADD --chmod0755 test_composer /test_composer。为什么用FROM scratch这些镜像仅仅作为存放拓扑所需全部文件的文件系统载体不运行任何程序因此使用FROM scratch最小化体积。镜像的实际运行者是被docker-compose.yml引用的mongo-binaries与workload镜像。所有拓扑镜像都在antithesis image build and push任务期间构建并上传到 Antithesis Docker registry其中/data与/logs等目录由 evergreen/antithesis_image_build_and_push.sh 脚本创建。docker-compose.yml拓扑描述与故障注入控制docker-compose.yml描述了如何利用mongo-binaries和workload镜像构造目标拓扑。以下是文档中给出的分片集群示例与构建器生成的结构一致见 docker_cluster_image_builder.py 中create_docker_compose_service的字段映射version: 3.0 services: configsvr1: container_name: configsvr1 hostname: configsvr1 image: mongo-binaries:evergreen-latest-master volumes: - ./logs/configsvr1:/var/log/mongodb/ - ./scripts:/scripts/ - ./data/configsvr1:/data/configdb/ command: /bin/bash /scripts/configsvr_init.sh networks: antithesis-net: ipv4_address: 10.20.20.6 # Set the an IPv4 with an address of 10.20.20.130 or higher # to be ignored by the fault injector # configsvr2: ... configsvr3: ... database1: ... container_name: database1 hostname: database1 image: mongo-binaries:evergreen-latest-master volumes: - ./logs/database1:/var/log/mongodb/ - ./scripts:/scripts/ - ./data/database1:/data/db/ command: /bin/bash /scripts/database_init.sh Shard1 networks: antithesis-net: ipv4_address: 10.20.20.3 # Set the an IPv4 with an address of 10.20.20.130 or higher # to be ignored by the fault injector # database2: ... database3: ... database4: ... database5: ... database6: ... mongos: container_name: mongos hostname: mongos image: mongo-binaries:evergreen-latest-master volumes: - ./logs/mongos:/var/log/mongodb/ - ./scripts:/scripts/ command: python3 /scripts/mongos_init.py depends_on: - database1 - database2 - database3 - database4 - database5 - database6 - configsvr1 - configsvr2 - configsvr3 networks: antithesis-net: ipv4_address: 10.20.20.9 # The subnet provided here is an example # An alternative subnet can be used workload: container_name: workload hostname: workload image: workload:evergreen-latest-master volumes: - ./logs/workload:/var/log/resmoke/ - ./scripts:/scripts/ command: python3 /scripts/workload_init.py depends_on: - mongos networks: antithesis-net: ipv4_address: 10.20.20.130 # The subnet provided here is an example # An alternative subnet can be used networks: antithesis-net: driver: bridge ipam: config: - subnet: 10.20.20.0/24编写规范与约束每个容器必须有commandcommand运行一个初始化脚本脚本必须放在以 volume 挂载的scripts目录中。写法必须是/bin/bash /scripts/[script_name].sh或python3 /scripts/[script_name].py。这是拓扑在 Antithesis 中正常启动的硬性要求。日志路由创建mongod或mongos实例时使用--logpath /var/log/mongodb/mongodb.log并把./logs/容器名挂载到/var/log/mongodb/如示例中database1的做法。这样一旦 Antithesis 检测到 bug可以方便地取回日志。IPv4 地址与故障注入豁免ipv4_address设置为10.20.20.130 或更高的容器不会被网络模糊测试影响。例如workload容器通常不希望被网络模糊测试干扰因此示例中分配了10.20.20.130。构建器源码中与此对应next_available_fault_enabled_ip从 2 开始递增受故障注入next_available_fault_disabled_ip从 130 开始递增不受故障注入。镜像 tag所有镜像统一使用evergreen-latest-mastertagpatch 场景则为evergreen-patch或自定义 tag必要时由 evergreen/antithesis_image_build_and_push.sh 自动更新。额外的 ulimits构建器还会为每个服务加上ulimits.memlock -1。这是因为 s2n-tlshandoff 传输层使用在启动时会调用mlock()而 Antithesis 容器默认的RLIMIT_MEMLOCK很低会导致s2n_config_new_minimal()失败、中止传输层初始化放开 memlock 限制后 mongo{d,s} 才能正常启动。scripts初始化脚本的写法与存活要求初始化脚本用于在容器启动时完成拓扑搭建。文档以sharded_cluster拓扑为例介绍了两种写法利用utils.py中的工具方法编写 Python 脚本如mongos_init.py或使用简单的 shell 脚本如database_init.py。当前仓库中初始化脚本由 docker_cluster_image_builder.py 自动生成每个 mongo{d,s} 进程对应一个scripts/服务名.sh内容就是该进程的完整启动参数process.args用shlex.quote拼接scripts/workload.sh固定为tail -f /dev/null保持 workload 容器存活同时生成scripts/run_resmoke.sh封装 resmoke 运行命令和scripts/print_connection_string.sh打印 resmoke fixture 的 shell 连接串Test Composer 脚本依赖它获取连接 URL。核心约束初始化脚本不能结束否则底层容器会退出。保持容器存活的方式有两种Python 脚本使用无限 while 循环Shell 脚本使用tail -f /dev/null。如何创建一个新的 Antithesis 测试拓扑创建新拓扑需要谨慎以确保高效利用有限的测试资源。步骤是创建一个继承antithesis_task_template、并打上antithesistag 的新 Evergreen 任务把指定的suite传给antithesis image build and push任务。可以参考现有的其他示例来起步。完整的模板式任务配置示例来自 buildscripts/antithesis/test_composer/README.md- : *antithesis_task_template name: antithesis_my_task commands: - func: antithesis image build and push vars: suite: concurrency_sharded_replication_with_balancer_and_config_transitions_and_add_remove_shard resmoke_args: - --runAllFeatureFlagTests antithesis_test_composer_dir: basic_js_commandsantithesis image build and push任务内部的核心命令见 antithesis_image_build_and_push.shbuildscripts/resmoke.py run --suite ${suite} ${resmoke_args} \ --dockerComposeTag $tag \ --dockerComposeBuildImages workload,config,mongo-binaries \ --dockerComposeBuildEnv evergreen ${extra_args}构建完成后会执行 sanity checkdocker-compose up -d拉起拓扑在 workload 容器内以--sanityCheck --externalSUT运行一次 resmoke带 1 小时超时收集日志后再把镜像推送到 Antithesis 仓库。其中mongo-binaries与workload两个共享镜像通过 S3 锁buildscripts/s3_lock.py保证并发推送互斥。如何在 Antithesis 中测试你的套件在 Evergreen patch 中传入参数schedule_antithesis_testsevergreen patch --param schedule_antithesis_teststrue当 Evergreen patch 中构建出 antithesis 镜像后系统会向 Antithesis 发送一个 API 请求让 Antithesis 运行你新建的镜像一小时。运行结束后报告会通过邮件发送给你。重要提示这个参数会作用于你在 patch 中安排的每一个 antithesis 任务。一次 patch 中不要同时安排超过 12 个携带该参数的任务否则会耗尽分配给项目的 Antithesis 测试额度。从源码看antithesis_image_build_and_push.sh 在 patch 且schedule_antithesis_teststrue时会用jq组装参数antithesis.config_image、antithesis.images、custom.duration设为.5小时、antithesis.report.recipients设为作者邮箱、antithesis.is_ephemeral设为true然后调用curl -X POST请求 Antithesis 的 launch API 端点触发测试。Antithesis 中的两种测试模式Normal resmoke testing默认模式Antithesis 会持续运行你的 resmoke 套件每次从中随机取一个测试来执行。大多数使用 Python fixture 的 resmoke 套件都开箱即用地支持这种模式其运行方式与 Evergreen 中的测试非常相似。如果任务上没有指定antithesis_test_composer_dir变量Evergreen 中的 antithesis 任务默认就是这种模式。Test Composer模板驱动的自主测试Antithesis 提供了名为 Test Composer 的能力用于针对集群运行测试模板。Test Composer 通过让你定义模板引导 Antithesis 在多种系统状态下自主生成数千个测试用例实现自主化测试。只要任务上指定了antithesis_test_composer_dir变量Evergreen 任务就会自动使用 Test Composer。Test Composer 采用一套命名约定parallel_driver_*、singleton_driver_*、serial_driver_*、first_*、eventually_*、finally_*、anytime_*来告诉 Antithesis 何时以及如何运行脚本从而控制并行度、故障注入与命令顺序。仓库中内置了两个模板basic_js_commands针对单个mongod的并行 JavaScript 负载find/insert/update/delete/aggregate/事务/dbCheck 等共享 js/commands.js 中的重试逻辑处理瞬时网络错误、server selection 失败与可重试写错误random_resmoke以随机种子--seed $(od -vAn -N4 -tu4 /dev/urandom)加--shuffle --sanityCheck的方式运行现有 resmoke jstests。关于命名规范、现有模板、最佳实践、本地开发方法以及 Evergreen 配置细节请参阅 buildscripts/antithesis/test_composer/README.md。附加资源如果希望进一步利用 Antithesis可以参考仓库内以下资源继续深入构建与推送全流程evergreen/antithesis_image_build_and_push.sh拓扑镜像与 docker-compose 的生成实现buildscripts/resmokelib/testing/docker_cluster_image_builder.py基础镜像定义buildscripts/antithesis/base_images/mongo_binaries/Dockerfile 与 buildscripts/antithesis/base_images/workload/DockerfileTest Composer 模板与指南buildscripts/antithesis/test_composer/README.md测试钩子中的 Antithesis 日志支持buildscripts/resmokelib/testing/hooks/README.md【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表