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 可观测性架构包括在边缘部署的 OpenTelemetry Collector,位于 CI/CD 工具旁边。此架构提供以下功能

  • 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 集成许多流行的 CI/CD 和 DevOps 工具(如 Maven 或 Ansible),Elastic 可观测性通过提供对 CI/CD 管道执行的深入见解来解决这些问题。

CI/CD 管道可视性编辑

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

Elastic 可观测性中的 APM 服务视图提供了所有检测到的 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 Controller 连接到 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 Controller 访问 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 与 Open Source 社区合作,利用 OpenTelemetry 提供最佳覆盖范围。

Jenkins编辑

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

    Jenkins Plugin Manager
  2. 点击 可用 选项卡,并搜索 OpenTelemetry
  3. 选中 OpenTelemetry 复选框,然后点击 立即下载并在重启后安装

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

配置 OpenTelemetry 插件编辑

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

  1. 在 Jenkins UI 上,转到 管理 Jenkins > 配置系统
  2. 转到 OpenTelemetry 插件部分。
  3. 使用 Elastic APM Server URL 和 APM Server 身份验证配置您的 OpenTelemetry 端点和身份验证。

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

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

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

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

    • 用于通信的端点证书。
    • 发送到 OpenTelemetry 服务的服务名称和服务命名空间。
    • 超时和批处理时间。
    • 您可能想要从发送的数据中省略的任何步骤。

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

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

在 Kibana 中安装 Jenkins 仪表板编辑

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

使用 导入 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 可观察性。

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=…​”在不修改 pom.xml 文件的情况下对 Maven 构建进行检测。

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 可观察性中可视化端到端管道执行,包括 CI 管道和 Maven 构建的详细步骤。

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

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

要了解更多信息,请参阅 Maven 构建与 Elastic 可观察性集成

Ansible编辑

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

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

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

Ansible playbooks in Jenkins
对 Ansible 剧本的可见性

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

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

Ansible AWX/Tower编辑

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

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

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

APM Service Endpoint in Ansible Tower
Ansible AWX/Tower 中的 APM 服务端点
Custom fields in Ansible Tower
Ansible AWX/Tower 中的自定义字段

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

Otel CLI编辑

otel-cli 是一个用于发送 OpenTelemetry 跟踪的命令行工具,当没有其他隐式集成到位时,如果显式地对脚本进行检测,这将很有用。

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

# 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 可观察性中执行使用 otel-cli 检测的 Makefile 的 Jenkins 构建
Jenkins service map view
使用 otel-cli 检测的 Jenkins 管道执行的服务地图视图

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 以发送跟踪,请参阅 跟踪 文档。在 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 可观察性中报告。

Concourse CI pipeline execution
Elastic 可观察性中的 Concourse CI 管道执行

Concourse CI 不会通过 OpenTelemetry 报告健康指标。但是,您可以使用 OpenTelemetry 收集器跨度指标处理器 将管道执行跟踪推导出 KPI 指标,例如管道的吞吐量和错误率。

从部署管道检查服务健康状况编辑

在部署管道中集成自动化的服务健康检查对于端到端部署自动化至关重要,这至关重要地使部署频率能够提高。

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

以下示例显示了一个金丝雀部署管道,该管道利用 Elastic 健康检查 HTTP API 来自动化质量检查,然后再将部署从金丝雀推广到所有实例。

Canary Deployment Pipeline

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

  • startend:使用 ISO-8601 格式的时间间隔(例如“2021-09-01T13:24:12Z”,这是一个 UTC 时间)
  • kuery: 用于根据服务名称和部署的新版本(例如)进行过滤,以缩小到金丝雀实例。例如 service.name:"MY_SERVICE_NAME" AND service.version:"1.2.3"
  • environment: 部署金丝雀实例的环境。例如:production

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

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

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))