背景

APISIX 官网:APISIX 是一款高性能可扩展的云原生网关

OpenTelemetry 官网:Opentelemetry 是当前 CNCF 除 k8s 外最火爆的项目,已经成为可观测性相关链路、日志、指标的数据采集行业标准,各大云厂商和中间件都已经集成。

需求

希望 用户id、灰度标签等信息在服务间无感地进行传递。

思路

Opentelemetry 提供了上下文全链路透传的能力,其传输格式见通用 w3c-baggage 协议

简单来说就是对 http 请求增加 baggage 请求头,baggage 的大概格式如下

baggage: userId=alice,isProduction=false

下面我们要做的就是在网关进行流量染色,根据 token 或者其他信息增加对应的 baggage 请求头,由于 apisix 中没有现成的插件因此需要自己开发一个。

插件功能非常简单如下图所示

行·

实现

1 准备工作

1.1 熟悉官方文档

1.2 下载 apisix 源码

git clone https://github.com/apache/apisix

仓库里有很多插件可以供我们参考

在 plugins 目录下创建 w3c-baggage.lua 文件

1.3 开发环境准备

由于是云原生网关,我们本地没有 k8s 集群的话就通过 docker 去搭建容器环境

https://apisix.apache.org/zh/docs/apisix/installation-guide/

git clone https://github.com/apache/apisix-docker.git
cd apisix-docker/example
  • 启动服务
    • docker-compose up -d

2 插件开发

  • schema 中的 properties 支持实时生效,可以在 apisix dashboard 上动态配置
  • _M 为一些原信息,我选择优先级比 opentelemetry 和 skywalking 小一点
  • rewrite 为核心修改请求头逻辑,在官网插件市场中找功能相似的插件进行参考,我找到的是 forword-auth 插件,修改后代码如下
local ngx = ngx
local ipairs = ipairs
local core = require("apisix.core")
local http = require("resty.http")

local schema = {
    type = "object",
    properties = {
        url = {
            type = "string",
            description = "上下文服务提取上下文接口地址"
        },
        request_headers = {
            type = "array",
            default = {},
            items = { type = "string" },
            description = "需要由客户端转发到上下文服务的请求头"
        },
        timeout = {
            type = "integer",
            minimum = 1,
            maximum = 60000,
            default = 3000,
            description = "timeout in milliseconds",
        },
        keepalive = {
            type = "boolean",
            default = true
        },
        keepalive_timeout = {
            type = "integer",
            minimum = 1000,
            default = 60000
        },
        keepalive_pool = {
            type = "integer",
            minimum = 1,
            default = 5
        },
    }
}

local plugin_name = "w3c-baggage"

local _M = {
    version = 0.1,
    priority = 12008,
    name = plugin_name,
    schema = schema,
    metadata_schema = metadata_schema,
}

function _M.check_schema(conf, schema_type)
    return core.schema.check(schema, conf)
end

function _M.rewrite(conf, ctx)
    local request_body = {
        url = ngx.var.host .. ngx.var.request_uri,
        headers = {}
    }

    -- append headers that need to be get from the client request header
    if #conf.request_headers > 0 then
        for _, header in ipairs(conf.request_headers) do
            if not request_body.headers[header] then
                request_body.headers[header] = core.request.header(ctx, header)
            end
        end
    end

    local params = {
        method = "POST",
        headers = {
            ["Content-Type"] = "application/json",
        },
        body = core.json.encode(request_body),
        keepalive = conf.keepalive,
    }

    if conf.keepalive then
        params.keepalive_timeout = conf.keepalive_timeout
        params.keepalive_pool = conf.keepalive_pool
    end

    local httpc = http.new()
    httpc:set_timeout(conf.timeout)

    local res, err = httpc:request_uri(conf.url, params)

    if not res then
        core.log.error("w3c-baggage error: ", err)
        return
    end

    if not res.body or res.status ~= 200 then
        return
    end

    core.request.set_header(ctx, "baggage", res.body)
end

return _M

3 插件部署调试

  • 修改 docker-compose.yml 将 w3c-baggage.lua 文件映射到容器 /usr/local/apisix/apisix/plugins/w3c-baggage.lua

在这里插入图片描述

  • 查看默认配置插件信息
    • docker-compose exec apisix cat /usr/local/apisix/conf/config-default.yaml
  • 修改 vi apisix_conf/config.yaml,复制 config-default.yaml 中的 plugins 列表,并增加 w3c-baggage(插件名)

在这里插入图片描述

  • 重启 apisix
    • docker-compose stop apisix
    • docker-compose up -d
  • 检查脚本内容
    • docker-compose exec apisix cat /usr/local/apisix/apisix/plugins/w3c-baggage.lua
  • 观察日志,看有没有错误
    • docker-compose logs apisix
  • 导出插件 schema.json
    • docker-compose exec apisix curl 127.0.0.1:9092/v1/schema > schema.json
  • 修改 docker-compose.yml,将刚才导出的 schema.json 挂载到容器 /usr/local/apisix-dashboard/conf/schema.json

在这里插入图片描述

  • 重启 apisix-dashboard
    • docker-compose stop apisix-dashboard
    • docker-compose up -d
  • 进入 apisix dashboard 配置插件生效

在这里插入图片描述

  • 启动上下文服务,发起请求调试
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐