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

编辑

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

编辑

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

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

CI/CD 可观测性架构

编辑

使用 APM 服务器,将所有支持 OpenTelemetry 的 CI/CD 工具直接连接到 Elastic 可观测性。

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

更高级的 CI/CD 可观测性架构包括在边缘部署一个 OpenTelemetry 收集器,靠近 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 可观测性中的应用程序服务视图提供了所有已监控 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 代理上,否则不要指定本地 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 管道是通过监控不同的 CI/CD 和 DevOps 工具来实现的。Elastic 与利用 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 服务器 URL 和 APM 服务器身份验证配置您的 OpenTelemetry 端点和身份验证。

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

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

      • 标头名称:"Authorization"
      • Header 值:一个包含值 "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 作业或管道)的上下文传播通过与 W3C Trace Context 规范 匹配的 TRACEPARENTTRACESTATE 环境变量传递到 Maven 构建。因此,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 playbook 的可见性。该插件为每次运行生成跟踪和性能指标,以帮助您了解哪些 Ansible 任务或角色运行最频繁、失败频率以及完成所需时间。

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

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

Ansible playbooks in Jenkins
对 Ansible playbook 的可见性

此集成开箱即用地为服务地图提供与 Ansible Playbook 连接的所有服务。所有这些功能都可以帮助您快速直观地评估在配置和持续交付中使用的服务。

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

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 可以帮助将每个目标中的每个命令可视化为跨度。

# 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 Collector Span Metrics Processor 将管道执行跟踪转换为 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 令牌进行身份验证。

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