1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目叫“devops-for-the-horde”。光看名字你可能会联想到游戏里的“部落”或者“军团”感觉有点中二但点进去一看这其实是一个面向开发者和运维工程师的实战型DevOps项目集合。它的核心目标非常明确通过一系列精心编排的、可复现的实战场景帮助个人或小团队从零开始构建一套完整的、现代化的DevOps工具链和实践体系。我自己在运维和DevOps领域摸爬滚打了十几年见过太多团队在工具选型和流程落地上的纠结。要么是工具链太零散各个组件之间像孤岛配置和维护成本高得吓人要么就是直接上云厂商的全家桶虽然省事但底层原理黑盒化一旦出问题排查起来两眼一抹黑成本也居高不下。这个项目恰好瞄准了这个痛点。它没有选择某个单一的、庞大的平台而是采用了一种“乐高积木”式的思路将CI/CD、基础设施即代码、监控、日志、服务网格等核心DevOps能力拆解成一个个独立的、可组合的模块。“Horde”在这里我理解有两层含义。一是象征着我们这些在技术前线“攻城略地”的工程师群体我们需要强大的、统一的“武器”和“战术”二是指项目本身像是一个由众多工具和实践组成的“军团”协同作战才能发挥最大威力。这个项目就是为我们这样的“部落”提供一套从单兵训练到联合作战的完整手册。无论你是想系统学习DevOps的初学者还是希望优化现有流程的资深工程师都能在这里找到可以直接“抄作业”的模板和深入思考的引子。2. 项目整体架构与设计哲学2.1 模块化与可组合的设计思想“devops-for-the-horde”项目最吸引我的地方在于其清晰的模块化架构。它没有试图打造一个银弹式的终极平台而是承认了现代技术栈的多样性和快速演进特性。整个项目可以看作是一个“最佳实践工具箱”的目录。通常一个完整的DevOps流水线会包含以下几个核心环节源代码管理与协作这是一切的起点。持续集成代码提交后自动触发构建、测试。持续交付/部署将通过测试的制品自动、安全地部署到各种环境。基础设施管理用代码定义和管理服务器、网络、存储等资源。配置管理确保服务器环境的一致性。监控与可观测性了解应用和基础设施的运行状态。日志聚合与分析集中收集和查询日志便于排错。这个项目为上述每个环节都提供了至少一种经过验证的实现方案。例如它可能用GitLab CI或GitHub Actions来演示CI/CD用Terraform来演示基础设施即代码用Ansible来演示配置管理用Prometheus Grafana搭建监控用ELK Stack处理日志。关键在于这些模块之间的接口是定义清晰的比如Terraform输出某个服务器的IPAnsible的Inventory文件可以动态读取这个IP你可以根据自己团队的技术偏好和基础设施现状像搭积木一样选择和组合这些模块。注意这种设计哲学要求使用者对每个工具的基本概念有一定了解。项目的价值不在于从零教你terraform init是什么意思而在于展示如何让Terraform和Ansible协同工作解决环境依赖和配置传递的实际问题。2.2 技术栈选型背后的逻辑浏览这类项目我们不仅要看它“用了什么”更要思考“为什么用这个”。这往往是项目作者多年实战经验的浓缩。以我个人的经验来看这类项目的选型通常遵循几个原则主流与成熟优先选择的工具通常是该领域市场占有率前三、社区活跃、文档丰富的。比如容器编排选Kubernetes而非小众方案CI工具选GitHub Actions/Jenkins/GitLab CI。这保证了方案的稳定性和可求助性。云原生友好工具链本身要能很好地运行在容器环境中并且支持声明式配置。例如用Helm来管理Kubernetes应用部署用Prometheus Operator来管理监控组件。自动化程度最大化从代码提交到服务上线尽可能减少人工干预点。项目会重点展示如何通过Webhook自动触发流水线如何实现自动化的蓝绿部署或金丝雀发布。成本可控演示方案通常会兼顾本地开发环境如Minikube、Docker Compose和公有云环境让学习者可以在零成本或低成本的情况下进行实验同时掌握迁移到生产云环境的方法。“devops-for-the-horde”很可能正是基于这些原则来构建它的示例。它向我们传递了一个重要信息构建DevOps体系工具的选择是战术而通过标准化、自动化的流程将工具串联起来形成合力才是战略。3. 核心模块深度解析与实操要点接下来我们假设“devops-for-the-horde”项目包含以下几个典型模块并深入拆解其实现要点和背后的思考。请注意以下内容是基于常见DevOps实践和该项目标题的合理推演与补充。3.1 基础设施即代码模块以Terraform为例核心场景你需要为你的应用快速搭建一套包含VPC、子网、安全组、虚拟机集群的基础设施环境。传统做法登录云控制台点点点。一次还好如果需要为开发、测试、生产各建一套或者频繁销毁重建这将是灾难。而且环境配置无法版本化也无法进行Code Review。IaC做法使用Terraform编写.tf文件用代码描述你想要的最终基础设施状态。实操要点与避坑指南状态文件管理Terraform会生成一个terraform.tfstate文件记录它管理的资源映射。绝对不要把这个文件提交到Git中尤其是多人协作时会导致状态冲突和敏感信息泄露。正确的做法是使用远程后端如AWS S3 DynamoDB用于锁或Terraform Cloud。# backend.tf 示例 - 使用S3后端 terraform { backend s3 { bucket my-terraform-state-bucket key prod/network/terraform.tfstate region us-east-1 dynamodb_table terraform-state-lock # 状态锁表防止并发操作 } }模块化设计不要把所有资源写在一个main.tf里。应该按逻辑划分模块比如network/、compute/、database/。项目里可能会提供一个modules/目录里面是封装好的可复用模块。project/ ├── environments/ │ ├── dev/ │ │ ├── main.tf # 调用模块传入dev环境变量 │ │ └── terraform.tfvars │ └── prod/ │ ├── main.tf # 调用相同的模块传入prod环境变量 │ └── terraform.tfvars └── modules/ ├── vpc/ ├── ec2-cluster/ └── rds/变量与输出善用变量文件*.tfvars来管理不同环境的配置差异。同时将模块的关键输出如VPC ID、负载均衡器地址定义清楚以便其他模块或脚本如Ansible消费。# 在compute模块中定义输出 output “app_server_ips” { value aws_instance.app[*].private_ip description “应用服务器的私有IP列表” }实操心得在团队中推行Terraform一开始最大的阻力往往是学习成本和“我控制台点两下就完事了”的思维惯性。一个有效的破局方法是先选择一个小的、非核心的、需要频繁重建的资源比如一个临时测试用的Redis集群用Terraform管理起来。让大家亲眼看到terraform apply和terraform destroy带来的效率提升和一致性保障比任何说教都管用。3.2 CI/CD流水线模块以GitLab CI与Kubernetes集成为例核心场景开发者向main分支推送代码后自动完成Docker镜像构建、单元测试、安全扫描并将镜像部署到Kubernetes测试环境。流水线设计解析一个健壮的CI/CD流水线应该包含多个阶段Stage并且每个作业Job职责单一。项目中的.gitlab-ci.yml文件可能如下结构stages: - build - test - scan - deploy-staging - deploy-prod # 可能需要手动触发 variables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA build-job: stage: build image: docker:latest services: - docker:dind # 使用Docker-in-Docker服务 script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $DOCKER_IMAGE . - docker push $DOCKER_IMAGE only: - main - merge_requests unit-test-job: stage: test image: node:16 # 假设是Node.js项目 script: - npm ci - npm run test:unit cache: key: $CI_COMMIT_REF_SLUG paths: - node_modules/ container-scan-job: stage: scan image: aquasec/trivy:latest script: - trivy image --exit-code 1 --severity HIGH,CRITICAL $DOCKER_IMAGE dependencies: - build-job # 依赖build阶段生成的镜像 deploy-staging-job: stage: deploy-staging image: bitnami/kubectl:latest script: - echo $KUBE_CONFIG_STAGING | base64 -d kubeconfig - export KUBECONFIG./kubeconfig - kubectl set image deployment/myapp-deployment myapp-container$DOCKER_IMAGE -n staging - kubectl rollout status deployment/myapp-deployment -n staging --timeout120s environment: name: staging url: https://staging.myapp.com only: - main关键点解析与避坑镜像Tag策略使用$CI_COMMIT_SHORT_SHA作为镜像Tag确保了每次提交都有唯一对应的、可追溯的制品。永远不要使用latest标签在生产流程中。Docker-in-Docker (dind)在容器内运行Docker命令需要特权模式存在安全风险。对于生产级流水线更推荐使用Kaniko或Buildah这类无需Docker守护进程的镜像构建工具它们更安全且通常构建速度更快。Kubernetes部署示例中使用了kubectl set image进行滚动更新。这虽然简单但在复杂场景下不够用。项目的高级部分很可能会引入Helm进行部署管理。通过Helm Chart你可以将应用的所有Kubernetes资源Deployment, Service, ConfigMap等打包并支持通过values.yaml文件轻松管理不同环境的配置。环境与机密管理Kubernetes的kubeconfig文件、数据库密码等敏感信息绝不能硬编码在CI配置文件中。必须使用CI/CD平台提供的机密变量功能如GitLab的CI/CD Variables并勾选Masked和Protected。部署时可以通过Kubernetes Secrets或外部密管系统注入。实操心得流水线失败是常态。一定要为关键作业设置超时时间和重试机制。例如kubectl rollout status命令必须设置--timeout否则网络抖动导致命令卡住时整个流水线会无限期等待。另外在deploy-prod阶段前设置手动触发关卡是平衡发布速度与安全性的重要手段。3.3 监控与告警模块Prometheus Grafana Alertmanager核心场景你需要实时了解你的Kubernetes集群和应用是否健康并在出现问题时如Pod频繁重启、CPU使用率超过90%持续5分钟立即收到通知。架构解析 这是一个经典的云原生监控组合。Prometheus负责指标Metrics的抓取、存储和查询。它采用拉模型主动从配置好的目标Targets上抓取指标。Grafana负责数据的可视化通过丰富的仪表盘将Prometheus中的指标以图表形式展现。Alertmanager负责处理由Prometheus发出的告警进行去重、分组、静默并路由到不同的接收器如电子邮件、Slack、钉钉。在Kubernetes中的部署要点如今在K8s中部署这套监控栈最推荐的方式是使用Prometheus Operator和对应的Helm Chart。Operator通过自定义资源定义CRD让你可以用声明式的方式管理Prometheus、Alertmanager等组件大大简化了配置。服务发现传统Prometheus需要静态配置抓取目标。在K8s中Prometheus Operator可以自动发现集群内的Service、Pod等资源并基于Annotations自动配置抓取任务。你只需要在应用的Pod模板上添加特定的注解即可。apiVersion: v1 kind: Pod metadata: name: my-app annotations: prometheus.io/scrape: “true” # 允许抓取 prometheus.io/port: “8080” # 指标端口 prometheus.io/path: “/metrics” # 指标路径 spec: containers: - name: app image: my-app:latest ports: - containerPort: 8080告警规则定义告警规则也通过CRDPrometheusRule来定义同样可以用YAML管理并纳入Git。apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: app-alerts spec: groups: - name: app.rules rules: - alert: HighRequestLatency expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) 0.5 for: 5m # 持续5分钟才触发 labels: severity: warning annotations: summary: “高请求延迟发生在 {{ $labels.instance }}” description: “{{ $labels.instance }} 的95分位请求延迟超过0.5秒 (当前值: {{ $value }}s)”告警路由与抑制在Alertmanager配置中可以根据告警的标签如severity: critical,team: backend路由到不同的接收方。还可以设置抑制规则例如当“集群节点宕机”告警触发时抑制所有从该节点发出的其他应用级告警避免告警风暴。实操心得监控告警最容易犯的两个错误是“告警太多”和“告警无用”。一开始人们倾向于为所有能想到的指标设置告警结果导致告警疲劳真正的关键告警被淹没。我的建议是从“影响用户体验的核心黄金指标”开始错误率、延迟、流量、饱和度。先为这些指标设置少数几个关键告警。告警信息一定要包含明确的修复指引或相关链接比如“请检查数据库连接池配置”或“链接到相关运行手册”这能极大缩短平均修复时间。4. 从零开始搭建你自己的“Horde”实战指南假设我们现在要从零开始参照“devops-for-the-horde”项目的思路为一个名为“SimpleBlog”的Web应用搭建最小可行的DevOps流程。我们将使用GitLab、Docker、KubernetesMinikube、Helm、Prometheus和Grafana。4.1 环境准备与本地Kubernetes集群搭建目标在本地开发机上创建一个可用的Kubernetes环境。步骤安装Minikube和kubectlMinikube是运行本地单节点K8s集群的最佳工具。# 以macOS为例使用Homebrew安装 brew install minikube kubectl # 启动Minikube集群建议分配足够资源 minikube start --cpus4 --memory8192 --driverdocker # 验证集群状态 kubectl cluster-info kubectl get nodes启用必要的插件Minikube提供了很多插件来方便地部署常用服务。# 启用Ingress控制器用于后续定义外部访问路由 minikube addons enable ingress # 启用Metrics Server为HPA和kubectl top提供资源指标 minikube addons enable metrics-server配置本地DNS可选但推荐为了在本地通过域名如blog.local访问服务可以修改本机hosts文件将Minikube的IP指向自定义域名。# 获取Minikube IP minikube ip # 输出类似 192.168.49.2 # 编辑 /etc/hosts (Linux/macOS) 或 C:\Windows\System32\drivers\etc\hosts (Windows) # 添加一行192.168.49.2 blog.local4.2 容器化应用与编写Helm Chart目标将SimpleBlog应用Docker化并创建Helm Chart以便在K8s中部署。编写Dockerfile在应用根目录创建Dockerfile确保应用以非root用户运行。FROM node:16-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction FROM node:16-alpine WORKDIR /app COPY --frombuilder /app/node_modules ./node_modules COPY . . # 创建一个系统用户来运行应用 RUN addgroup -g 1001 -S nodejs adduser -S nodejs -u 1001 USER nodejs EXPOSE 3000 CMD [“node”, “server.js”]创建Helm Chart使用Helm命令行工具快速生成Chart骨架。helm create simpleblog-chart cd simpleblog-chart生成的目录结构如下我们需要重点关注几个文件simpleblog-chart/ ├── Chart.yaml # Chart的元数据 ├── values.yaml # 默认配置值 ├── templates/ # Kubernetes资源模板 │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ └── _helpers.tpl # 模板辅助函数 └── charts/ # 子Chart依赖定制化templatestemplates/deployment.yaml: 定义应用如何运行。我们需要修改容器镜像部分使其能通过CI/CD动态注入。spec: containers: - name: {{ .Chart.Name }} image: “{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}” imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - containerPort: {{ .Values.service.port }} env: {{- toYaml .Values.env | nindent 12 }} # 支持通过values注入环境变量 resources: {{- toYaml .Values.resources | nindent 12 }}templates/ingress.yaml: 定义外部访问规则。确保已启用并配置正确。{{- if .Values.ingress.enabled -}} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include “simpleblog-chart.fullname” . }} annotations: {{- toYaml .Values.ingress.annotations | nindent 4 }} spec: ingressClassName: {{ .Values.ingress.ingressClassName }} rules: - host: {{ .Values.ingress.host | default “blog.local” }} http: paths: - path: / pathType: Prefix backend: service: name: {{ include “simpleblog-chart.fullname” . }} port: number: {{ .Values.service.port }} {{- end }}配置values.yaml为不同环境如staging, production准备不同的values文件。# values-staging.yaml image: repository: my-registry.com/mygroup/simpleblog tag: latest-stable # CI/CD会覆盖此tag ingress: enabled: true host: “staging-blog.mycompany.com” resources: requests: memory: “256Mi” cpu: “250m” limits: memory: “512Mi” cpu: “500m”4.3 集成CI/CDGitLab流水线自动化一切目标配置GitLab CI实现代码提交后自动构建镜像、运行测试、扫描漏洞、并更新K8s部署。准备Kubernetes访问权限在K8s集群中为CI/CD机器人创建一个ServiceAccount和对应的Secret。# 创建一个名为gitlab-ci的ServiceAccount kubectl create serviceaccount gitlab-ci -n default # 为其绑定cluster-admin角色生产环境请使用更细粒度的RoleBinding kubectl create clusterrolebinding gitlab-ci-admin --clusterrolecluster-admin --serviceaccountdefault:gitlab-ci # 获取其token用于kubeconfig kubectl get secret $(kubectl get serviceaccount gitlab-ci -o jsonpath‘{.secrets[0].name}’) -o jsonpath‘{.data.token}’ | base64 --decode # 获取集群CA证书 kubectl get secret $(kubectl get serviceaccount gitlab-ci -o jsonpath‘{.secrets[0].name}’) -o jsonpath‘{.data.ca\.crt}’ | base64 --decode使用上述信息在本地生成一份kubeconfig文件。在GitLab中配置机密变量进入GitLab项目设置 - CI/CD - Variables添加以下变量KUBE_CONFIG_STAGING: 将生成的完整kubeconfig文件内容进行Base64编码后填入。DOCKER_REGISTRY_URL,DOCKER_REGISTRY_USER,DOCKER_REGISTRY_PASSWORD: 你的私有容器镜像仓库凭证。编写增强版.gitlab-ci.yml我们将集成安全扫描和更复杂的部署策略。include: - template: Security/SAST.gitlab-ci.yml # 引入GitLab内置的SAST模板 - template: Security/Container-Scanning.gitlab-ci.yml # 引入容器扫描模板 variables: DOCKER_IMAGE: $DOCKER_REGISTRY_URL/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA HELM_CHART_DIR: “simpleblog-chart” stages: - build - test - security-scan - deploy-staging - performance-test # 新增性能测试阶段 - deploy-prod build: stage: build image: docker:latest services: - docker:dind script: - docker build -t $DOCKER_IMAGE . - docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY_URL - docker push $DOCKER_IMAGE only: - main - merge_requests # 单元测试和集成测试... # SAST和Container-Scanning由模板自动生成作业... deploy-staging: stage: deploy-staging image: alpine/helm:3.9.0 script: - apk add --no-cache git - echo $KUBE_CONFIG_STAGING | base64 -d /tmp/kubeconfig - export KUBECONFIG/tmp/kubeconfig - cd $HELM_CHART_DIR - helm upgrade --install simpleblog-staging . \ --namespace staging \ --create-namespace \ --set image.tag$CI_COMMIT_SHORT_SHA \ --set ingress.hoststaging-blog.local \ -f values-staging.yaml - kubectl rollout status deployment/simpleblog-staging -n staging --timeout300s environment: name: staging url: http://staging-blog.local only: - main performance-test: stage: performance-test image: loadimpact/k6 script: - k6 run --vus 10 --duration 30s scripts/load-test.js # 一个简单的k6测试脚本 dependencies: [] needs: [“deploy-staging”] # 依赖staging部署完成 only: - main deploy-prod: stage: deploy-prod image: alpine/helm:3.9.0 script: - echo $KUBE_CONFIG_PROD | base64 -d /tmp/kubeconfig - export KUBECONFIG/tmp/kubeconfig - cd $HELM_CHART_DIR # 使用蓝绿部署策略先安装一个新版本流量切换验证后再删除旧版本 - helm upgrade --install simpleblog-prod-${CI_COMMIT_SHORT_SHA} . \ --namespace production \ --create-namespace \ --set image.tag$CI_COMMIT_SHORT_SHA \ --set ingress.enabledfalse \ # 新版本先不接入流量 -f values-prod.yaml # 此处可加入人工验证步骤或自动化测试 - echo “新版本部署完成准备切换流量...” # 更新主Ingress将流量指向新版本 - helm upgrade --install simpleblog-prod . \ --namespace production \ --set image.tag$CI_COMMIT_SHORT_SHA \ --set ingress.enabledtrue \ -f values-prod.yaml # 删除旧的Release (可选可保留最近几个版本用于快速回滚) - helm list -n production --filter ‘^simpleblog-prod-‘ --short | grep -v ${CI_COMMIT_SHORT_SHA} | xargs -r -I {} helm uninstall {} -n production environment: name: production url: https://blog.mycompany.com when: manual # 生产部署设置为手动触发 only: - main这个流水线实现了从代码到生产的自动化并嵌入了安全门禁和渐进式发布策略是一个接近生产可用的简化版流程。5. 常见问题排查与效能提升技巧在实际操作中你一定会遇到各种问题。以下是一些高频问题的排查思路和提升效率的技巧。5.1 CI/CD流水线故障排查清单当流水线作业失败时不要慌张按照以下顺序排查问题现象可能原因排查步骤docker build失败1. Dockerfile语法错误。2. 网络问题无法拉取基础镜像。3. 构建上下文缺失文件。1. 本地运行docker build -t test .验证。2. 检查CI Runner网络尝试docker pull基础镜像。3. 检查.dockerignore文件确认所需文件在上下文中。docker push失败1. 镜像仓库认证失败。2. 仓库地址或镜像名格式错误。3. 权限不足。1. 检查DOCKER_REGISTRY_*变量是否正确Masked变量是否有特殊字符。2. 确认镜像名符合仓库规范如包含项目组。3. 登录仓库检查该账户是否有push权限。kubectl或helm命令超时/失败1. Kubeconfig配置错误或过期。2. 集群网络不通或资源不足。3. RBAC权限不足。1. 在CI脚本中cat /tmp/kubeconfig检查配置或使用kubectl cluster-info测试连接。2. 检查集群节点状态kubectl get nodes查看事件kubectl get events。3. 检查ServiceAccount的RoleBinding是否正确。部署后应用无法访问1. Pod启动失败。2. Service或Ingress配置错误。3. 应用本身监听端口错误。1.kubectl get pods -n namespace查看Pod状态kubectl logs -f pod-name查看日志。2.kubectl describe svc/ingress name查看配置详情。3.kubectl exec -it pod-name — netstat -tlnp检查容器内进程监听。流水线运行缓慢1. Runner资源不足。2. 未有效利用缓存。3. 每个作业都拉取大型基础镜像。1. 为Runner分配更多CPU/内存或使用更强大的云Runner。2. 为npm ci,go mod download等步骤配置缓存。3. 使用较小的基础镜像如Alpine或使用本地镜像仓库缓存常用镜像。5.2 Kubernetes运维实用技巧快速进入Pod调试kubectl debug命令可以创建一个临时调试容器共享故障Pod的命名空间非常适合排查网络问题。kubectl debug -it problem-pod --imagebusybox --targetproblem-pod -- sh查看Pod启动前的错误如果Pod一直处于Pending或CrashLoopBackOff状态除了看Pod日志一定要查看Events。kubectl describe pod pod-name -n namespace # 重点关注Events部分常见原因镜像拉取失败、节点资源不足、不满足节点亲和性等。使用kubectl get的-o wide和-o yaml-o wide可以查看更多列信息如Pod所在节点。-o yaml可以输出资源的完整YAML定义用于检查实际生效的配置或者导出配置进行修改。配置kubectl命令自动补全大幅提升工作效率。# bash echo ‘source (kubectl completion bash)’ ~/.bashrc # zsh echo ‘source (kubectl completion zsh)’ ~/.zshrc5.3 提升DevOps流程效能的建议本地开发环境容器化使用docker-compose或skaffold在本地模拟多服务环境确保“它在我的机器上能运行”的问题在早期就被发现。编写有意义的提交信息采用Conventional Commits规范便于自动生成变更日志并且CI/CD可以根据提交类型如feat:、fix:决定是否触发部署到生产环境。基础设施代码也需要测试对Terraform代码使用terraform validate和terraform plan进行静态检查和变更预览。可以考虑使用terratest进行集成测试。监控你的流水线对CI/CD流水线本身也设置监控比如跟踪流水线平均执行时间、失败率、恢复时间。流水线是交付的生命线它的健康度至关重要。定期进行“混沌工程”演练在非核心业务时间主动注入故障如随机删除一个Pod、模拟网络延迟检验系统的弹性和团队的应急响应能力。工具可以选择Chaos Mesh或Litmus Chaos。