持续集成和持续交付 (CI/CD) 监控

编辑

持续集成和持续交付 (CI/CD) 监控

编辑

为了帮助管理员监控和排查其 CI/CD 平台的问题,并帮助开发人员提高 CI/CD 管道的速度和可靠性,Elastic 可观测性提供了对持续集成和持续交付 (CI/CD) 过程的可视性。

为了在管道上提供监控仪表板、警报和根本原因分析,Elastic 与最流行的 CI/CD 平台的社区合作,使用 OpenTelemetry 来检测工具。

CI/CD 可观测性架构

编辑

使用 APM Server,将所有 OpenTelemetry 原生 CI/CD 工具直接连接到 Elastic 可观测性。

Simple architecture of CI/CD observability with Elastic
使用 Elastic 的 CI/CD 可观测性架构

更高级的 CI/CD 可观测性架构包括部署在边缘(CI/CD 工具旁边)的 OpenTelemetry 收集器。此架构提供以下功能

  • CI/CD 工具和收集器之间的低延迟对 otel-cli 等临时工具特别有利。
  • 除了 Elastic 可观测性之外,还能够将可观测性信号路由到多个后端。
Advanced architecture of CI/CD observability with Elastic
使用 Elastic 的高级 CI/CD 可观测性架构

CI/CD 管理员的可观测性

编辑

Elastic 可观测性允许 CI/CD 管理员监控和排查 CI/CD 平台的问题,并检测异常。

CI/CD 平台监控和警报

编辑

Elastic 可观测性通过提供 CI 系统的 KPI 仪表板,帮助 CI/CD 管理员监控其平台。

Jenkins 健康状况仪表板提供了有关构建执行、失败、构建代理的配置、活动和空闲工作器或 JVM 健康状况的见解。

CI/CD overview
Elastic 可观测性中的 Jenkins KPI
Jenkins KPIs
Elastic 可观测性中的 Jenkins 配置 KPI
Jenkins JVM health indicators
Elastic 可观测性中的 Jenkins JVM 健康指标

CI/CD 平台故障排除

编辑

CI/CD 管理员在快速排除平台问题时,需要评估异常的影响,无论是排除一个管道的问题,还是排除影响许多管道或整个 CI/CD 平台的更广泛中断问题。

Elastic 可观测性通过以分布式跟踪形式可视化管道执行,以及在任何维度中切片和切块管道执行以评估中断的性质和影响的能力,从而实现 CI 平台中断的故障排除。

在下图中,Jenkins CI 构建失败,其异常报告为错误。选择任何这些错误以查看特定信息。在本例中,它是与停止的 CI 代理相关的错误。

Jenkins pipeline builds
Elastic 可观测性中的 Jenkins 管道构建错误

错误概览屏幕提供了 CI 构建捕获的异常的高级视图。相似的错误被分组,以便快速查看哪些错误正在影响您的服务,并允许您采取措施进行纠正。

Jenkins pipeline build errors
Elastic 可观测性中的 Jenkins 作业和管道错误
Concourse CI traces view
Elastic 可观测性中作为跟踪的 Concourse CI 管道执行

开发人员的可观测性

编辑

开发团队需要不断优化其不断变化的 CI/CD 管道,以提高其可靠性,同时追求更快的管道。以分布式跟踪形式可视化管道有助于记录正在发生的事情,并提高性能和可靠性(不稳定的测试和管道)。

通过使用 OpenTelemetry 与 Maven 或 Ansible 等许多流行的 CI/CD 和 DevOps 工具集成,Elastic 可观测性通过提供对 CI/CD 管道执行的深入见解来解决这些问题。

CI/CD 管道可见性

编辑

在 Elastic 可观测性中以分布式跟踪形式可视化 CI/CD 管道,提供了所有管道的文档和健康指标。

Elastic 可观测性中的应用程序服务视图提供了所有检测的 CI/CD 服务器的视图及其 KPI 的见解。

Jenkins servers view
Elastic 可观测性中的 Jenkins 服务器

服务页面通过按管道分解健康和性能指标,提供有关 CI/CD 工作流的更精细的见解。要快速查看哪些管道遇到最多的错误、最频繁执行或最慢,您可以对列表进行排序和过滤。

Jenkins server view
Elastic 可观测性中的 Jenkins 服务器

单个管道的可见性

编辑

一旦您确定了要排除故障的管道,您可以向下钻取以获取有关其随时间推移的性能的更详细信息。管道摘要显示了管道各个构建和作业的持续时间和失败率的细分,以发现减速或失败。

Jenkins pipeline overview
Elastic 可观测性中 Jenkins 管道的性能概览

管道和传统的作业会自动检测。如果您发现构建缓慢或失败,并且需要了解正在发生的事情,您可以深入查看构建的跟踪视图,以查找持续时间较长的作业或有错误的作业。然后,您可以深入了解详细信息,以了解错误的来源。

Trace of a Jenkins pipeline build
Elastic 可观测性中作为跟踪的 Jenkins 管道构建

要进一步调查,您可以查看以标签形式捕获的构建的详细信息。

Attributes of a Jenkins pipeline execution
Elastic 可观测性中 Jenkins 管道执行的上下文属性

在 Elastic 中存储 Jenkins 管道日志

编辑

Jenkins 管道日志可以通过 OpenTelemetry 协议 (OTLP) 发送,以便与管道构建的跟踪和 Jenkins 健康指标一起存储在可观测性后端中。将日志存储在可观测性后端中具有以下几个好处

  • 由于可观测性后端中所有信号的统一,Jenkins 实例的可观测性、监控、警报和故障排除能力得到提高。
  • 构建具有更好的可追溯性和长期存储,因此您可以更轻松地审核软件交付生命周期。
  • 通过大大减少 Jenkins 中存储的数据量,并限制存储大量构建历史时 Jenkins 的众所周知的文件系统性能挑战,提高 Jenkins 的可伸缩性和可靠性。

要求和配置

编辑

在 Elastic 中存储 Jenkins 管道日志需要

  • Elastic 可观测性版本 8.1 或更高版本。
  • 在 Jenkins OpenTelemetry 插件上配置的 OpenTelemetry 协议端点可以从 Jenkins 代理访问(即,除非 OpenTelemetry 收集器也部署在 Jenkins 代理上,否则不要指定 localhost OTLP 端点)。
  • 使用 OpenTelemetry 收集器时,除了跟踪和指标管道之外,还需要设置一个日志管道

在 Elastic 中存储管道日志

  1. 导航到 Jenkins 配置屏幕的 OpenTelemetry 部分。
  2. 设置 OTLP 端点
  3. 使用 添加可视化可观测性后端 下拉列表选择 Elastic 可观测性 选项。
  4. 设置 Kibana 基本 URL
  5. 单击 高级 按钮以选择存储集成策略。在 Elastic 可观测性中存储管道日志有两个选项

    • 在 Elastic 中存储管道日志并在 Elastic 和 Jenkins 中可视化日志,这意味着您可以在 Jenkins UI 中按需查看存储在 Elastic 中的日志。请在下面在 Kibana 和 Jenkins 中可视化日志中了解更多信息。
    • 在 Elastic 中存储管道日志并在 Elastic 中独家可视化日志,这意味着日志将不再通过 Jenkins UI 可见。请在下面在 Kibana 中独家可视化日志中了解更多信息。

建议在 Elastic 和 Jenkins 中可视化日志,因为它通过继续在 Jenkins UI 中呈现日志来提供更流畅的用户体验,同时允许您验证 Elasticsearch 设置。

在 Kibana 和 Jenkins 中可视化日志

编辑

Jenkins OpenTelemetry 插件在 Elasticsearch 中提供管道日志存储,同时允许您在 Kibana 中可视化日志,并继续通过 Jenkins 管道构建控制台显示日志。

Jenkins Console Output page displaying both log contents and a link to view logs in Elastic Observability

这种更高级的设置需要将 Jenkins 控制器连接到 Elasticsearch,并对 logs-apm.app 具有读取权限,并且最好对该索引模板的 ILM 策略的元数据具有读取权限(默认情况下为 logs-apm.app_logs-default_policy 策略)。使用“验证 Elasticsearch 配置”来验证设置。

Architecture diagram for storing pipeline logs in Elastic and visualizing logs in both Elastic and Jenkins
在 Elastic 中存储管道日志并在 Elastic 和 Jenkins 中可视化日志的架构

在 Kibana 中独家可视化日志

编辑

在 Kibana 中独家可视化日志涉及更简单的设置,不需要从 Jenkins 控制器访问 Elasticsearch。这是因为 Jenkins 管道构建控制台显示到 Kibana 日志可视化屏幕的超链接,而不是在 Jenkins UI 中显示日志。

Jenkins Console Output page with link to view logs in Elastic Observability
Architecture diagram for storing pipeline logs in Elastic and visualizing logs exclusively in Elastic
在 Elastic 中存储管道日志并在 Elastic 中独家可视化日志的架构

检测 CI/CD 管道

编辑

通过检测不同的 CI/CD 和 DevOps 工具来实现观察 CI/CD 管道。Elastic 与开源社区合作,利用 OpenTelemetry 来提供最佳覆盖范围。

Jenkins

编辑
安装 OpenTelemetry 插件
编辑
  1. 在 Jenkins UI 上,转到 Manage Jenkins > Manage Plugins

    Jenkins Plugin Manager
  2. 单击 Available 选项卡,然后搜索 OpenTelemetry
  3. 选中 OpenTelemetry 复选框,然后单击 Download now and install after restart

    要验证插件是否已安装,请单击 已安装 选项卡,并搜索 OpenTelemetry 插件

配置 OpenTelemetry 插件
编辑

需要配置 OpenTelemetry 插件,以便将数据报告给 OpenTelemetry 服务。此外,您还需要 OpenTelemetry 服务的端点、身份验证类型和访问凭据。

  1. 在 Jenkins UI 中,转到 Manage Jenkins > Configure System
  2. 转到 OpenTelemetry 插件部分。
  3. 使用 Elastic APM 服务器 URL 和 APM 服务器身份验证配置您的 OpenTelemetry 端点和身份验证

    • 如果使用 Elastic APM 密钥令牌授权,请选择 Bearer 身份验证令牌,并将令牌添加为 Jenkins 秘密文本凭据。

      Configure OTEL plugin
    • 如果使用 Elastic API 密钥授权,请定义 Header 身份验证

      • 标头名称:"Authorization"
      • 标头值:一个秘密文本凭据,其值为 "ApiKey an_api_key"an_api_key 是密钥的值)
  1. 转到 添加可视化可观察性后端,并定义您的 Kibana 服务器的 URL。

    Define Kibana URL
  2. 最后,还有其他设置需要配置

    • 用于通信的端点证书。
    • 发送到 OpenTelemetry 服务Service name 和 Service namespace。
    • 超时和批处理时间。
    • 您可能希望从发送的数据中省略的任何步骤。

      您可以将 OpenTelemetry 配置导出为环境变量,以便与其他工具(如 otel-cli、Ansible Otel 插件等)一起使用。如果您启用此选项,请注意,您可能会在控制台输出中暴露凭据。

要了解有关 Jenkins 与 Elastic Observability 集成的更多信息,请参阅 OpenTelemetry

在 Kibana 中安装 Jenkins 仪表板
编辑

有一些开箱即用的 Kibana 仪表板,可帮助可视化 CI/CD 平台的一些指标。

使用 Import API 或 Kibana UI,您可以安装与 7.12 或更高版本兼容的仪表板

例如,您可以按照以下步骤操作

  • 在 Kibana UI 中导入仪表板
Import Kibana dashboard
在 Kibana 中导入仪表板
  • 现在可以使用新仪表板了
Jenkins dashboard in Kibana
Kibana 中的 Jenkins 仪表板已准备就绪
Jenkins dashboard
Kibana 中的 Jenkins 仪表板

Maven

编辑

Maven OpenTelemetry 扩展集成提供了对所有 Maven 构建的全面可见性。该扩展为每个构建生成跟踪和性能指标,以帮助您了解运行最多的 Maven 目标或 Maven 子模块、它们的失败频率以及完成所需的时间。

CI 管道(Jenkins 作业或管道)中的上下文传播通过 TRACEPARENTTRACESTATE 环境变量传递到 Maven 构建,这些环境变量与 W3C 跟踪上下文规范 匹配。因此,CI 平台中发生的一切也都会显示在跟踪中。

您可以使用 Maven OpenTelemetry 扩展 配置您的 Maven 项目。例如,您可以将以下代码段添加到您的 pom.xml 文件中

<project>
  ...
  <build>
    <extensions>
      <extension>
          <groupId>io.opentelemetry.contrib</groupId>
          <artifactId>opentelemetry-maven-extension</artifactId>
          <version>1.12.0-alpha</version>
      </extension>
    </extensions>
  </build>
</project>

现在,您可以通过将配置详细信息作为环境变量传递,触发将 Maven 构建报告性能数据发送到 Elastic Observability

export OTEL_EXPORTER_OTLP_ENDPOINT="https://elastic-apm-server.example.com:8200"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer an_apm_secret_token"
export OTEL_TRACES_EXPORTER="otlp"

mvn verify

您可以使用 Maven 命令行参数 “-Dmaven.ext.class.path=…​” 来检测 Maven 构建,而无需修改 pom.xml 文件

export OTEL_EXPORTER_OTLP_ENDPOINT="https://elastic-apm-server.example.com:8200"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer an_apm_secret_token"
export OTEL_TRACES_EXPORTER="otlp"

mvn -Dmaven.ext.class.path=path/to/opentelemetry-maven-extension.jar verify

您还可以从 CI 平台触发 Maven 构建,并在 Elastic Observability 中可视化端到端管道执行,包括 CI 管道和 Maven 构建的详细步骤。

当使用 Jenkins 调用 Maven 构建时,无需使用环境变量来配置 Maven 构建 (OTEL_EXPORTER_OTLP_ENDPOINT…),只需依靠 Jenkins 将 OpenTelemetry 配置作为环境变量注入的能力即可。有关更多详细信息,请参阅 安装 OpenTelemetry 插件

Maven builds in Jenkins
执行 Maven 构建的 Jenkins 管道

要了解更多信息,请参阅 Maven 构建与 Elastic Observability 的集成

Ansible

编辑

Ansible OpenTelemetry 插件集成提供了对所有 Ansible playbook 的可见性。该插件为每次运行生成跟踪和性能指标,以帮助您了解运行最多的 Ansible 任务或角色、它们的失败频率以及完成所需的时间。

您可以使用 Ansible OpenTelemetry 回调插件 配置您的 Ansible playbook。需要安装 OpenTelemetry python 库,并按照 示例 部分中的说明配置回调。

来自 Jenkins 作业或管道的上下文传播会传递到 Ansible 运行。因此,CI 中发生的一切也会显示在跟踪中。

Ansible playbooks in Jenkins
Ansible playbook 的可见性

这种集成开箱即用地将 Service Map 与连接到 Ansible Playbook 的所有服务一起提供。所有这些功能都可以帮助您快速直观地评估在您的预配和持续部署中使用的服务。

Ansible service map view
使用 Ansible 插件检测的 Jenkins 管道执行的 ServiceMap 视图

Ansible AWX/Tower

编辑

Ansible OpenTelemetry 插件集成支持 Ansible AWX/Tower。要启用它,请按照以下步骤操作。

AWX 需要一个安装了 Ansible 和 Python 包的执行环境。您可以使用 Ansible Builder CLI 工具 创建容器定义。然后将容器上传到 AWX 可访问的映像存储库,并使用您创建的容器定义执行环境。

要注入环境变量和服务详细信息,请使用自定义凭据类型并将凭据分配给 Playbook 模板。这使您可以灵活地重用 Elastic APM 的端点详细信息,还可以标准化用于报告目的的自定义字段。

Applications Services Endpoint in Ansible Tower
Ansible AWX/Tower 中的应用程序服务端点
Custom fields in Ansible Tower
Ansible AWX/Tower 中的自定义字段

想了解更多信息?这篇博文 很好地概述了所有这些部分如何协同工作。

Otel CLI

编辑

otel-cli 是一个用于发送 OpenTelemetry 跟踪的命令行工具,如果您在没有其他隐式集成的情况下显式地检测脚本,它会很有用。

使用 otel-cli 包装器,您可以配置在 shell、make 或其他脚本语言中实现的构建脚本。例如,使用 otel-cli 检测下面的 Makefile 可以帮助可视化每个目标中的每个命令作为 span。

# see https://blog.container-solutions.com/tagging-docker-images-the-right-way

NAME   := acmecorp/foo
TAG    := $$(git log -1 --pretty=%!H(MISSING))
IMG    := ${NAME}:${TAG}
LATEST := ${NAME}:latest

build:
  @otel-cli exec \
    --name 'docker build' \
    docker build -t ${IMG} .
  @otel-cli exec \
    --name 'docker tag' \
    docker tag ${IMG} ${LATEST}

push:
  @otel-cli exec \
    --name 'docker push' \
    --attrs "http.url=https://docker.elastic.dev" \
    docker push ${NAME}

login:
  @otel-cli exec \
    --name 'docker login' \
    --attrs 'rpc.system=grpc' \
    docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}

调用使用 otel-cli 进行跟踪的 shell 脚本

export OTEL_EXPORTER_OTLP_ENDPOINT="elastic-apm-server.example.com:8200"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer an_apm_secret_token"
export OTEL_TRACES_EXPORTER="otlp"

make login build push
Jenkins build executing an instrumented Makefile
在 Elastic Observability 中执行使用 otel-cli 检测的 Makefile 的 Jenkins 构建
Jenkins service map view
使用 otel-cli 检测的 Jenkins 管道执行的 ServiceMap 视图

Pytest-otel

编辑

pytest-otel 是一个 pytest 插件,用于将 Python 测试结果作为 OpenTelemetry 跟踪发送。测试跟踪可以帮助您了解测试执行情况、检测瓶颈,以及比较随时间推移的测试执行情况,以检测错误行为和问题。

来自 CI 管道(Jenkins 作业或管道)的上下文传播通过 TRACEPARENT 传递到 Maven 构建。

OTEL_EXPORTER_OTLP_ENDPOINT=https://elastic-apm-server.example.com:8200 \
OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer an_apm_secret_token" \
OTEL_SERVICE_NAME=pytest_otel \
pytest --otel-session-name='My_Test_cases'
Pytest tests
Pytest 测试的可见性

Concourse CI

编辑

要配置 Concourse CI 发送跟踪,请参阅 tracing 文档。在 Concourse 配置中,您只需定义 CONCOURSE_TRACING_OTLP_ADDRESSCONCOURSE_TRACING_OTLP_HEADERS

CONCOURSE_TRACING_OTLP_ADDRESS=elastic-apm-server.example.com:8200
CONCOURSE_TRACING_OTLP_HEADERS=Authorization=Bearer your-secret-token

支持上下文传播;因此,您可以从上述集成中受益。

配置 Concourse CI 跟踪后,Concourse CI 管道执行将在 Elastic Observability 中报告。

Concourse CI pipeline execution
Elastic Observability 中的 Concourse CI 管道执行

Concourse CI 不会通过 OpenTelemetry 报告运行状况指标。但是,您可以使用 OpenTelemetry Collector Span Metrics Processor 将管道执行跟踪转换为 KPI 指标,例如管道的吞吐量和错误率。

从部署管道检查服务运行状况

编辑

在部署管道中集成自动服务运行状况检查对于端到端部署自动化至关重要,这对于提高部署频率至关重要。

Elastic Observability 公开了 HTTP API 来检查服务的运行状况。您可以将这些 API 集成到部署管道中,以验证新部署实例的行为,并根据运行状况自动继续部署或回滚。

以下示例显示了一个 canary 部署管道,该管道利用 Elastic 运行状况检查 HTTP API 来自动化质量检查,然后再将部署从 canary 推广到整个实例集

Canary Deployment Pipeline

通过调用 KIBANA_URL/internal/apm/services API 执行运行状况检查,以比较新部署实例上的服务事务错误率与阈值。将以下参数传递给调用

  • startend:使用 ISO-8601 格式的时间间隔(例如 "2021-09-01T13:24:12Z",这是 UTC 时间)
  • kuery:用于筛选服务名称,例如,部署到缩小到 canary 实例的新版本。示例 service.name:"MY_SERVICE_NAME" AND service.version:"1.2.3"
  • environment:canary 实例部署到的环境。示例:production

要定义时间范围,请使用 startend 参数。这些参数是 ISO-8601 格式的日期。要仅查询一个服务,请在 kuery 参数中编写过滤器,然后使用表达式 service.name:MY_SERVICE_NAME and service.version: SERVICE_VERSION 按服务名称进行过滤。最后,通过传递 environment 参数来应用 environment 过滤器。要选择所有环境,请使用 ENVIRONMENT_ALL

此 API 调用需要身份验证。我们建议使用 API 令牌进行身份验证。

此 API 可能会发生更改,并且即将发布针对持续交付用例优化的稳定 API。

def check_service_health(service_name, service_version, error_rate_threshold, kibana_url, api_token):
    now = datetime.now()
    five_minutes_ago = now - timedelta(minutes=5)
    params = {
        "start": five_minutes_ago.strftime("%Y-%m-%dT%H:%M:%SZ"),
        "end": now.strftime("%Y-%m-%dT%H:%M:%SZ"),
        "kuery": "service.name:{} and service.version:{}".format(service_name, service_version),
        "environment": "ENVIRONMENT_ALL"
    }
    url = "{}/internal/apm/services?{}".format(kibana_url, urllib.parse.urlencode(params))
    req = urllib.request.Request(url=url, headers={"Authorization": "Bearer {}".format(api_token)})
    with urllib.request.urlopen(req) as response:
     body = response.read().decode("utf8")
     obj = json.loads(body)
     if len(obj['items']) > 0 and obj['items'][0].transactionErrorRate > error_rate_threshold:
            raise Exception("Error rate for service {} is higher than threshold {}, current value is {}".format(service_name, error_rate_threshold, obj['items'][0].transactionErrorRate))