使用OpenTelemetry对Kong网关进行链路追踪

本文介绍如何使用OpenTelemetry对Kong进行链路追踪。Kong是一个云原生、平台无关、可扩展的API网关,提供负载均衡、安全性、监控和API管理功能,并支持各种插件以扩展其功能。Kong OpenTelemetry 插件支持采集Kong的调用链数据并上报至可观测链路 OpenTelemetry 版,只需添加少量配置即可开启链路追踪。

使用限制

  • Kong版本要求:3.1.x及以上版本。

  • Kong链路追踪功能只支持HTTP协议(HTTP/HTTPS),不支持TCP和UDP。

  • Kong OpenTelemetry插件目前仅支持通过HTTP方式上报,不支持gRPC方式上报。

前提条件

获取接入点信息

新版控制台

  1. 登录可观测链路 OpenTelemetry 版控制台,在左侧导航栏单击接入中心

  2. 开源框架区域单击OpenTelemetry卡片。

  3. 在弹出的OpenTelemetry面板中选择数据需要上报的地域。

    说明

    初次接入的地域将会自动进行资源初始化。

  4. 选择连接方式上报方式,然后复制接入点信息。

    • 连接方式:若您的服务部署在阿里云上,且所属地域与选择的接入地域一致,推荐使用阿里云内网方式,否则选择公网方式。

    • 上报方式:根据客户端支持的协议类型选择HTTP协议上报数据。

    image.png

旧版控制台

  1. 登录可观测链路 OpenTelemetry 版控制台

  2. 在左侧导航栏单击集群配置,然后在右侧页面单击接入点信息页签。

  3. 在页面顶部选择需要接入的地域,然后在集群信息区域打开显示Token开关。

  4. 客户端采集工具区域单击OpenTelemetry

    相关信息列中,获取接入点信息。ot旧版中.jpg

    说明

    如果应用部署于阿里云生产环境,则选择阿里云VPC网络接入点,否则选择公网接入点。

接入步骤(自动埋点)

Kong OpenTelemetry插件支持采集Kong的调用链数据并上报至可观测链路 OpenTelemetry 版,您只需修改Kong的配置文件即可开启链路追踪。

一、为Kong开启链路追踪

方法一:在环境变量里设置

  • KONG_TRACING_INSTRUMENTATIONS:开启链路追踪。

  • KONG_TRACING_SAMPLING_RATE:采样率,取值范围为0到1.0。1.0为全部采样,0为不采样。

KONG_TRACING_INSTRUMENTATIONS=all
KONG_TRACING_SAMPLING_RATE=1

方法二:在kong.conf配置文件中设置

  • tracing_instrumentations:开启链路追踪。

  • tracing_sampling_rate:采样率,取值范围为0到1.0。1.0为全部采样,0为不采样。

# kong.conf  
tracing_instrumentations = all  
tracing_sampling_rate = 1.0  
...

二、配置OpenTelemetry上报参数

说明

使用以下三种方法配置OpenTelemetry上报参数时,请替换以下参数:

  • ${HTTP_ENDPOINT}:HTTP接入点,请替换为前提条件中获取到的HTTP接入点,例如http://tracing-analysis-dc-hk.aliyuncs.com/adapt_xxxxx/api/otlp/traces

  • ${SERVICE_NAME}:应用名,自定义。此名称将会作用Kong的应用名称在可观测链路 OpenTelemetry 版控制台中展示。

方法一:在kong.yaml中设置OpenTelemetry上报地址和应用名称

# kong.yaml
...
plugins:
  ...
  - name: opentelemetry
    config:
      traces_endpoint: ${HTTP_ENDPOINT}
      resource_attributes:
        service.name: ${SERVICE_NAME}

方法二:通过Kong Admin API设置OpenTelemetry上报地址和应用名称

curl -X POST http://localhost:8001/plugins/ \
    --header "accept: application/json" \
    --header "Content-Type: application/json" \
    --data '
    {
  "name": "opentelemetry",
  "config": {
    "traces_endpoint": "${HTTP_ENDPOINT}",
    "resource_attributes": {
      "service.name": "${SERVICE_NAME}"
    }
  }
}
    '

方法三:在Kubernetes中创建KongClusterPlugin资源,并设置OpenTelemetry上报地址和应用名称

apiVersion: configuration.konghq.com/v1
kind: KongClusterPlugin
metadata:
 name: <global-opentelemetry>
 annotations:
   kubernetes.io/ingress.class: kong
 labels:
   global: "true"
config:
 traces_endpoint: ${HTTP_ENDPOINT}
 resource_attributes:
   service.name: ${SERVICE_NAME}
plugin: opentelemetry
说明

设置完OpenTelemetry上报地址和应用名称后,需要重启Kong网关,即可为Kong开启OpenTelemetry链路追踪。

三、查看Kong调用链

完成以上配置后,您可通过Kong创建路由并进行访问,以生成调用链。然后登录可观测链路 OpenTelemetry 版控制台,查看由OpenTelemetry生成的Kong调用链。

  • 应用列表页面查看Kong应用。image (6).png

  • 调用链分析页面打开Kong的调用链,查看请求耗时、客户端IP、 HTTP状态码、HTTP路由等信息。7.jpg

四、高级配置(可选)

配置一:设置Kong OpenTelemetry插件使用的链路透传协议(Trace上下文格式)

在默认情况下,Kong OpenTelemetry使用W3C作为链路透传协议,这意味着插件只会识别上游传入的W3C协议请求头,并向下透传W3C协议请求头。如果您需要Kong支持其他透传协议,可以修改config.propagation.extractconfig.propagation.inject config.propagation.default_format 参数。

以下面的配置为例,插件将按照W3C(OpenTelemetry)、b3(Zipkin)、Jaeger、OT(OpenTracing)的顺序尝试从HTTP请求头中提取Trace上下文,preserve意味着Kong的链路向下透传时保留原始格式。如果未识别到上下文,将使用default_format中定义的W3C格式生成Trace。

# kong.yaml
...
plugins:
  ...
  - name: opentelemetry
    config:
      ...
      propagation:
        extract: [ w3c, b3, jaeger, ot ]
        inject: [ preserve ]
        default_format: "w3c"

配置二:设置Kong OpenTelemetry插件生效范围

Kong OpenTelemetry插件支持四种生效范围,分别是全局生效、应用级别生效、路由级别生效和Consumer级别生效。默认情况下Kong OpenTelemetry插件全局生效,如果您希望修改生效范围,请参考以下配置进行修改。

  • 为单个应用开启

    请将 ${SERVICE_NAME|ID} 替换为允许插件生效的服务名称或服务ID。

    # kong.yaml
    plugins:
    ...
    - name: opentelemetry
     service: ${SERVICE_NAME|ID}
     config:
       traces_endpoint: ${HTTP_ENDPOINT}
       resource_attributes:
         service.name: ${SERVICE_NAME}
  • 为单个路由开启

    请将 ${ROUTE_NAME|ID} 替换为允许插件生效的路由名称或路由ID。

    # kong.yaml
    plugins:
    ...
    - name: opentelemetry
      route: ${ROUTE_NAME|ID}
      config:
        traces_endpoint: ${HTTP_ENDPOINT}
        resource_attributes:
         service.name: ${SERVICE_NAME}
  • 为单个Consumer开启

    请将${CONSUMER_NAME|ID}替换为允许插件生效的Consumer名称或Consumer ID。

    # kong.yaml
    plugins:
    ...
    - name: opentelemetry
      consumer: ${CONSUMER_NAME|ID}
      config:
        traces_endpoint: ${HTTP_ENDPOINT}
        resource_attributes:
         service.name: ${SERVICE_NAME}

配置三:设置采集的Kong链路类型

Kong允许通过tracing_instrumentations配置项或KONG_TRACING_INSTRUMENTATIONS环境变量来指定要采集的链路类型。类型如下表所示。

参数取值

描述

off

关闭链路追踪

all

启用以下所有类型的链路追踪

request

只启用请求级别的链路追踪

db_query

追踪数据库查询

dns_query

追踪DNS查询

router

追踪路由器执行,包括路由器重建

http_client

追踪OpenResty HTTP客户端请求

balancer

追踪负载均衡器重试

plugin_rewrite

追踪插件迭代器在重写阶段的执行

plugin_access

追踪插件迭代器在访问阶段的执行

plugin_header_filter

追踪插件迭代器在头部过滤阶段的执行

操作示例

下文将通过一个例子演示如何采集Kong网关及后端应用的调用链,并上报至可观测链路 OpenTelemetry 版

准备工作

项目结构

仅展示本示例需要的文件。

docker-kong/compose/
│
├── docker-compose.yml          # Docker Compose配置文件
│
├── config/
│   └── kong.yaml               # Kong声明式配置文件
│
└── backend/
    ├── Dockerfile              # 后端服务的Dockerfile
    ├── main.js
    ├── package.json
    └── package-lock.json

操作步骤

  1. 下载Kong/docker-kong开源项目。

    git clone https://github.com/Kong/docker-kong.git && cd docker-kong/compose
  2. 创建后端服务(以Node.js应用为例)。

    本步骤会创建一个使用Express框架的Node.js应用,该应用在7001端口启动并暴露/hello端点。

    1. 创建应用目录。

      mkdir backend && cd backend
    2. 创建package.json。

      cat << EOF > package.json
      {
        "name": "backend",
        "version": "1.0.0",
        "main": "index.js",
        "scripts": {},
        "keywords": [],
        "author": "",
        "license": "ISC",
        "description": "",
        "dependencies": {
          "@opentelemetry/api": "^1.9.0",
          "@opentelemetry/auto-instrumentations-node": "^0.52.0",
          "axios": "^1.7.7",
          "express": "^4.21.1"
        }
      }
      EOF
    3. 创建main.js。

      cat << EOF > main.js
      "use strict";
      const axios = require("axios").default;
      const express = require("express");
      const app = express();
      app.get("/", async (req, res) => {
        const result = await axios.get("http://localhost:7001/hello");
        return res.status(201).send(result.data);
      });
      app.get("/hello", async (req, res) => {
        console.log("hello world!")
        res.json({ code: 200, msg: "success" });
      });
      app.use(express.json());
      app.listen(7001, () => {
        console.log("Listening on http://localhost:7001");
      });
      EOF
    4. 创建Dockerfile。

      说明

      请按照前提条件中的步骤获取HTTP接入点,并替换${HTTP_ENDPOINT}

      cat << EOF > Dockerfile
      FROM node:20.16.0
      WORKDIR /app
      COPY package*.json ./
      RUN npm install
      COPY . .
      ENV OTEL_TRACES_EXPORTER="otlp"
      ENV OTEL_LOGS_EXPORTER=none
      ENV OTEL_METRICS_EXPORTER=none
      ENV OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="${HTTP_ENDPOINT}"
      ENV OTEL_NODE_RESOURCE_DETECTORS="env,host,os"
      ENV OTEL_SERVICE_NAME="ot-nodejs-demo"
      ENV NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
      EXPOSE 7001
      CMD ["node", "main.js"]
      EOF
  3. 为Kong开启链路追踪,并将后端服务添加到Docker Compose中。

    1. backend目录回到上层目录。

      cd ..
    2. 修改docker compose。

      vim docker-compose.yml
    3. docker-compose.yml文件中为Kong添加环境变量,开启链路追踪。

      ...
      services:
        kong:
          ...
          environment:
            ...
            # 新增两个环境变量
            KONG_TRACING_INSTRUMENTATIONS: all
            KONG_TRACING_SAMPLING_RATE: 1.0
          ...
      ...
    4. docker-compose.yml文件中定义名为backend-api的Nodejs后端服务。

      ...
      services:
        ...
        backend-api:
          build:
            context: ./backend
            dockerfile: Dockerfile
          environment:
            NODE_ENV: production
          ports:
            - "7001:7001"
          networks:
            - kong-net
      ...
  4. 在Kong中配置后端服务和路由规则,并启用OpenTelemetry插件。

    1. 进入conf文件夹。

      cd config
    2. 将以下内容追加到kong.yaml中。

      说明

      请按照前提条件中的步骤获取HTTP接入点,并替换${HTTP_ENDPOINT}

      cat << EOF >> kong.yaml
      
      services:
        - name: backend-api
          url: http://backend-api:7001
          routes:
            - name: main-route
              paths:
                - /hello
      
      plugins:
        - name: opentelemetry
          config:
            traces_endpoint: ${HTTP_ENDPOINT} # 请替换为实际的HTTP接入点
            headers:
              X-Auth-Token: secret-token
            resource_attributes:
              service.name: kong-dev
      EOF
  5. 启动Kong和后端服务。

    1. 回到上层目录。

      cd ..
    2. docker-compose.yml文件所在目录中执行命令,启动Kong和后端服务。

      docker compose up -d
  6. 通过Kong访问后端服务。

    curl http://localhost:8000/hello
    
    # 预期输出:{"code":200,"msg":"success"}
  7. 前往可观测链路 OpenTelemetry 版控制台,查看Kong及后端服务的调用链。

    说明

    在本例中,Kong在应用列表页面的名称显示为kong-dev,后端应用名称为ot-nodejs-demo。

常见问题

  1. 启用Kong OpenTelemetry插件后,在可观测链路 OpenTelemetry 版控制台没有看到Kong的调用链。

    将Kong的日志级别设置为debug(设置环境变量KONG_LOG_LEVEL=debug或者在kong.conf文件中设置log_level=debug),重新生成请求,然后查看日志中是否输出了Kong的调用链信息。

  2. Kong的调用链无法与其他应用串联。

    请确认其他应用使用的链路透传协议与Kong的透传协议是否相同,默认情况下Kong使用W3C作为透传协议。

  3. Kong OpenTelemetry插件是否会对Kong网关的性能产生影响?

    启用Kong OpenTelemetry插件可能会对Kong网关产生影响。推荐调整链路采样率(具体方法,请参见一、为Kong开启链路追踪),并调整OpenTelemetry插件上报调用链的批次大小、重试次数和重试时间。插件具体配置,请参见 Kong OpenTelemetry Configuration

相关文档