- API网关
- 后端
- LLM 网关
- 微服务
- 人工智能
【免费下载链接】kong
🦍 The API and AI Gateway
导读:本文围绕 Kong 开源仓库中性能测试(perf test)基础设施的 Equinix Metal 驱动契约展开,逐条解读
spec/fixtures/perf/terraform/equinix-metal/README.md定义的三大前置条件(id_rsa私钥、四个 IP 输出项、internal-ip 回退规则),并结合该目录下完整的 Terraform 配置与spec/helpers/perf/drivers/terraform.lua驱动源码,说明这套基础设施如何被 Kong 性能测试框架自动拉起、读取和销毁。读完本文,你将掌握 Equinix Metal 上部署 Kong 压测环境的完整机制,并能理解如何将该契约推广到其他云厂商(AWS、DigitalOcean、BYO)。
一、契约文档:Kong perf 测试对 Terraform 驱动的最低要求
Kong 仓库中,性能测试的 Terraform 驱动被组织在 spec/fixtures/perf/terraform 目录下,每个云厂商一个子目录。其中 equinix-metal/README.md 是唯一一份以 README 形式固化契约的驱动,全文内容如下:
Perf test terraform driver expects:
id_rsaas the private key presentkong-ip,kong-internal-ip,worker-ipandworker-internal-ipto present in terraform output. If instance has no private IP, use<type>-ipas<type>-internal-ipis also accepted.
这份文档虽然短,却是整个 perf 测试驱动体系与云资源之间唯一正式的"接口协议",包含三个核心约定:
- 私钥契约:工作目录下必须存在名为
id_rsa的 SSH 私钥文件,驱动通过它免密登录所有被创建的实例; - 输出契约:
terraform output必须提供kong-ip、kong-internal-ip、worker-ip、worker-internal-ip四个 IP 值,驱动据此定位 Kong 节点与压测 worker 节点; - 回退契约:若实例没有私有 IP(如某些精简网络配置),允许将
<type>-ip直接当作<type>-internal-ip使用。
下文将逐一验证这三个约定在仓库源码中的实际落地方式。
二、私钥契约:id_rsa从生成、落盘到使用的完整链路
2.1 密钥生成与落盘
在 tls.tf 中,驱动使用 Terraform 的tlsprovider 动态生成一对 RSA 密钥:
resource "tls_private_key" "key" { algorithm = "RSA" }密钥生成后,ssh.tf 负责将其私钥以id_rsa文件名写入驱动工作目录,并强制权限为0600:
resource "local_sensitive_file" "key_priv" { content = tls_private_key.key.private_key_pem filename = "./id_rsa" file_permission = "0600" }这里filename = "./id_rsa"正是 README 中"id_rsaas the private key present"的出处:Terraform apply 完成时,驱动所在目录必然出现该私钥文件。
2.2 驱动如何消费私钥
spec/helpers/perf/drivers/terraform.lua中的ssh_execute_wrap方法拼装了全部 SSH 参数,其中明确引用id_rsa:
return "ssh " .. "-o IdentityFile=" .. self.work_dir .. "/id_rsa " .. -- TODO: no hardcode "-o TCPKeepAlive=yes -o ServerAliveInterval=10 " .. "-o ControlPath=" .. self.work_dir .. "/cm-%r@%h:%p " .. "-o ControlMaster=auto -o ControlPersist=5m " .. "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no " .. "-o LogLevel=ERROR " .. self.ssh_user .. "@" .. ip .. " '" .. cmd .. "'"从源码可以看出,id_rsa契约背后还有一层隐性约束:SSH 连接必须依赖连接复用(ControlMaster=auto、ControlPersist=5m)与跳过主机指纹校验(StrictHostKeyChecking=no),否则批量执行命令时会反复建立连接或被指纹提示阻塞。工作目录work_dir由驱动new()方法解析:"./spec/fixtures/perf/terraform/" .. provider,所以对于 Equinix Metal 即 spec/fixtures/perf/terraform/equinix-metal。
三、输出契约:四个 IP 输出项与terraform output -json的读取
3.1 output.tf 中的四个核心输出
output.tf 完整实现了 README 要求的输出契约:
output "kong-ip" { value = equinix_metal_device.kong.access_public_ipv4 } output "kong-internal-ip" { value = equinix_metal_device.kong.access_private_ipv4 } output "db-ip" { value = var.seperate_db_node ? equinix_metal_device.db.0.access_public_ipv4: "" } output "db-internal-ip" { value = var.seperate_db_node ? equinix_metal_device.db.0.access_private_ipv4: "" } output "worker-ip" { value = equinix_metal_device.worker.access_public_ipv4 } output "worker-internal-ip" { value = equinix_metal_device.worker.access_private_ipv4 }可见除契约要求的四个输出外,还额外提供db-ip与db-internal-ip用于独立数据库节点(受seperate_db_node开关控制)。值得注意的是kong-ip取access_public_ipv4、kong-internal-ip取access_private_ipv4,这正是 README 所述"公有 IP + 私有 IP"两种地址的映射来源。
3.2 驱动侧如何读取输出
terraform.lua的setup()方法在terraform apply成功后,通过terraform output -json一次性拉取全部输出并解析:
res, err = perf.execute("cd " .. self.work_dir .. " && terraform output -json") res = cjson.decode(res) self.kong_ip = res["kong-ip"].value self.kong_internal_ip = res["kong-internal-ip"].value if self.opts.seperate_db_node then self.db_ip = res["db-ip"].value self.db_internal_ip = res["db-internal-ip"].value else self.db_ip = self.kong_ip self.db_internal_ip = self.kong_internal_ip end self.worker_ip = res["worker-ip"].value self.worker_internal_ip = res["worker-internal-ip"].value这段代码同时体现了输出契约的两个细节:
- 驱动使用
cjson解析terraform output -json的标准 JSON 结构(res["kong-ip"].value); - 当
seperate_db_node为 false 时,数据库直接复用 Kong 节点 IP,不额外拉起独立数据库实例。
3.3 各 provider 输出契约的一致性
输出契约并不局限于 Equinix Metal,其余 provider 也遵循完全相同的输出命名。例如 aws-ec2/output.tf 输出kong-ip、kong-internal-ip、worker-ip、worker-internal-ip、db-ip、db-internal-ip;bring-your-own/output.tf 则将用户传入的变量原样输出为同名输出。这种"输出名统一"的设计让 terraform.lua 驱动可以用同一套解析逻辑兼容所有云厂商。
四、回退契约:无私有 IP 场景的<type>-ip降级
README 的第三句话规定:若实例没有私有 IP,允许将<type>-ip直接当作<type>-internal-ip。仓库中该规则有两处落地:
1. 驱动层自动降级(Equinix Metal 场景)
terraform.lua的start_worker()中,压测请求默认发送到worker_internal_ip:
if not uri then uri = string.format("http://%s:8000", self.kong_internal_ip) end而setup_kong()中 Kong 的pg_host默认使用db_internal_ip。一旦terraform output -json返回空字符串,驱动随后通过 SSH 命令执行会失败——因此回退必须发生在更上游。
2. 变量层显式回退(bring-your-own 场景)
bring-your-own/variables.tf 给出了最清晰的降级实现:
locals { kong_internal_ip_fallback = var.kong_internal_ip != "" ? var.kong_internal_ip : var.kong_ip worker_internal_ip_fallback = var.worker_internal_ip != "" ? var.worker_internal_ip : var.worker_ip }kong_internal_ip、worker_internal_ip变量默认值为空字符串,当用户未提供时自动回退到公网 IP。注释# db IP fallback is done in the lua part则指明数据库节点的回退由 Lua 驱动完成——即上文setup()中self.db_ip = self.kong_ip的逻辑。
此外,在 spec/helpers/perf.lua 的use_defaults()中,用户可通过环境变量PERF_TEST_BYO_KONG_INTERNAL_IP等显式指定内部 IP,其默认值即对应公网 IP 变量:
kong_internal_ip = os.getenv("PERF_TEST_BYO_KONG_INTERNAL_IP"), -- fallback to kong_ip五、实例资源定义:metal.tf 与 variables.tf 的可调参数
5.1 三节点资源模型
metal.tf 定义了 perf 测试的标准拓扑:kong 节点(被压测对象)+ worker 节点(压测发起方)+ 可选 db 节点(独立数据库)。
resource "equinix_metal_device" "kong" { hostname = "kong-${random_string.ident.result}" plan = var.metal_plan facilities = var.metal_region operating_system = var.metal_os billing_cycle = "hourly" project_id = var.metal_project_id tags = [] depends_on = [ equinix_metal_ssh_key.key ] } resource "equinix_metal_device" "db" { count = var.seperate_db_node ? 1: 0 ... } resource "equinix_metal_device" "worker" { hostname = "worker-${random_string.ident.result}" ... }关键设计点:
billing_cycle = "hourly"按小时计费,与压测"用完即毁"的节奏匹配;depends_on = [equinix_metal_ssh_key.key]保证 SSH 公钥先于设备创建上传(metal.tf 顶部定义了equinix_metal_ssh_key资源,其public_key来自tls_private_key.key.public_key_openssh);random_string.ident(4 位随机串)用于生成唯一 hostname,避免多轮压测命名冲突;db资源使用count = var.seperate_db_node ? 1 : 0实现条件创建。
5.2 可调变量清单
variables.tf 暴露了完整的参数面:
| 变量 | 类型 | 默认值 | 说明 |
|---|---|---|---|
metal_auth_token | string | 无 | 必须提供,Equinix Metal API token |
metal_project_id | string | 无 | 必须提供,设备创建所属项目 ID |
metal_plan | string | c3.small.x86 | Kong 节点机型 |
metal_worker_plan | string | c3.small.x86 | worker 节点机型 |
metal_db_plan | string | c3.small.x86 | 数据库节点机型 |
metal_region | list(string) | 11 个 AMER 机房(dc13/da11/sv15/sv16/sp4/ch3/ny5/ny7/la4/tr2/se4) | 可用区候选列表,Metal 会从中分配 |
metal_os | string | ubuntu_20_04 | 设备操作系统 |
seperate_db_node | bool | false | 是否创建独立数据库实例 |
main.tf中声明了版本约束:Terraform~> 1.2、equinix provider~> 1.6,以及 local/null/tls/random 四个辅助 provider。provider "equinix"仅配置auth_token = var.metal_auth_token。
5.3 参数如何从环境变量注入
用户无需手写.tfvars文件——perf.lua 的use_defaults()会把环境变量转换成terraform apply的-var参数(驱动new()中实现为-var 'k=v'拼接):
tfvars = { metal_project_id = os.getenv("PERF_TEST_METAL_PROJECT_ID"), metal_auth_token = os.getenv("PERF_TEST_METAL_AUTH_TOKEN"), metal_plan = os.getenv("PERF_TEST_METAL_PLAN"), -- "c3.small.x86" metal_os = os.getenv("PERF_TEST_METAL_OS"), -- "ubuntu_20_04", } tfvars.seperate_db_node = seperate_db_node对应关系为:PERF_TEST_METAL_PROJECT_ID→metal_project_id、PERF_TEST_METAL_AUTH_TOKEN→metal_auth_token、PERF_TEST_METAL_PLAN→metal_plan、PERF_TEST_METAL_OS→metal_os,以及PERF_TEST_SEPERATE_DB_NODE→seperate_db_node(注意源码中的拼写为SEPERATE)。驱动选择则通过PERF_TEST_DRIVER=terraform与PERF_TEST_TERRAFORM_PROVIDER=equinix-metal完成。
六、契约之上的完整压测生命周期
README 描述的契约只是起点,terraform.lua 在拿到 IP 后继续完成如下完整流程:
6.1 数据库准备(db 节点)
setup()在 db 节点上依次执行:卸载 unattended-upgrades、安装 Docker、清理历史容器,然后启动 PostgreSQL 13 容器:
"sudo docker run -d -p5432:5432 ".. "-e POSTGRES_PASSWORD=" .. PG_PASSWORD .. " " .. "-e POSTGRES_DB=kong_tests " .. "-e POSTGRES_USER=kong --name=kong-database postgres:13 postgres -N 2333"并通过docker logs -f kong-database轮询"is ready to accept connections"确认数据库就绪。PG_PASSWORD是每次驱动实例化时生成的随机密码,postgres -N 2333提高了最大连接数以支撑高并发压测。
6.2 Kong 安装(kong 节点)
setup_kong(version)支持两种版本来源:
- 发布包:从
download.konghq.com下载kong-<version>_amd64.deb并dpkg -i安装; - git 源码 + daily 镜像:以
git:<分支>形式传入版本时,驱动会 checkout 对应分支,并把kong/kong:master-ubuntu每日镜像内的 Lua 源码与 OpenResty 组件提取到节点上(docker cp方式)。
安装前后还会做系统调优:将 CPU 调速器设为performance、扩大本地端口范围net.ipv4.ip_local_port_range='10240 65535',这些细节保证了压测结果不被系统默认配置干扰。
6.3 worker 节点环境与压测工具
start_worker(conf, port_count)在 worker 节点安装 nginx 与wrk/wrk2,并写入一段预生成的 nginx 配置:默认监听8088起始的端口,location /返回固定大体积字符串(模拟真实上游响应体)。压测脚本目录 scripts/wrk.lua 提供动态 URL 生成逻辑,可通过KONG_DEMO_CONSUMER_COUNT、KONG_DEMO_SERVICE_COUNT、KONG_DEMO_WORKSPACE_COUNT、KONG_DEMO_ROUTE_PER_SERVICE环境变量调节服务/消费者/路由规模:
local consumer_count = os.getenv("KONG_DEMO_CONSUMER_COUNT") or 5 local service_count = os.getenv("KONG_DEMO_SERVICE_COUNT") or 5 local workspace_count = os.getenv("KONG_DEMO_WORKSPACE_COUNT") or 1 local route_per_service = os.getenv("KONG_DEMO_ROUTE_PER_SERVICE") or 5 function request() local random_consumer = rand(consumer_count) local random_service = rand(service_count) local random_route = rand(route_per_service) if workspace_count == 1 then url_path = string.format("/s%s-r%s?apikey=consumer-%s", random_service, random_route, random_consumer) else random_workspace = rand(workspace_count) url_path = string.format("/w%s-s%s-r%s?apikey=consumer-%s", random_workspace, random_service, random_route, random_consumer) end return wrk.format(nil, url_path, headers) end6.4 压测启动与负载均衡等待
get_start_load_cmd()有一个容易被忽略的重要机制:发起压测前会持续检查 Kong 节点的 1 分钟 loadavg,直到loadavg / 物理核数 < 0.2才允许开压(源码常量LOAD_NORMALIZED_THRESHOLD = 0.2),从而保证每轮压测都从"空闲基线"开始,结果可横向比较。
6.5 销毁与回收
teardown(full)分两级清理:默认仅卸载 Kong 相关文件与进程(dpkg -r kong、pkill nginx),保留实例以加速下一轮测试;传入 full 参数时才执行terraform destroy -auto-approve彻底销毁所有设备,与billing_cycle = "hourly"的计费模型闭环。
七、验证与配套:从契约到可运行的 perf 测试
7.1 最小接入条件
要在一台机器上跑通 Equinix Metal 压测,需要满足:
- 本机安装 Terraform
~> 1.2(驱动setup()会先执行which terraform做存在性检查); - 具备 Equinix Metal 账号的 auth token 与 project ID;
- 以
PERF_TEST_DRIVER=terraform、PERF_TEST_TERRAFORM_PROVIDER=equinix-metal等环境变量启动任一 perf spec,例如 spec/04-perf/01-rps/01-simple_spec.lua。
7.2 与 perf spec 的对接方式
性能测试用例通过require("spec.helpers.perf")使用驱动,核心 API 包括use_defaults()、setup_kong(version)、start_kong()、start_worker()、start_load()、wait_result()、teardown(),压测版本可通过PERF_TEST_VERSIONS环境变量以逗号分隔传入多个版本做对比测试。驱动操作默认带 3 次重试(RETRY_COUNT = 3),任意一次失败都会抛错终止用例。
7.3 可替换性:一份契约,四套实现
Equinix Metal 只是 Terraform 驱动的默认 provider。仓库中 aws-ec2、digitalocean、bring-your-own 均实现了同一套输出契约,切换 provider 只需修改PERF_TEST_TERRAFORM_PROVIDER及对应的PERF_TEST_*环境变量。因此,本文解析的三条契约(id_rsa、四个 IP 输出、internal-ip 回退)实际上构成了 Kong perf 测试框架与任意云基础设施之间的通用接入标准。
八、总结
equinix-metal/README.md用三句话定义了一套严谨的驱动-基础设施契约:私钥id_rsa保障免密运维通道,四个 IP 输出项统一了节点寻址方式,internal-ip 回退规则兼容无私有网络的环境。从 tls.tf、ssh.tf、output.tf 到 terraform.lua 驱动的逐行落地,再到 perf.lua 的环境变量注入与 scripts/wrk.lua 的负载生成,这套最小契约支撑起了 Kong 在真实云主机上的可重复、可对比的吞吐与延迟基准测试能力。无论是为 Kong 贡献新的云厂商 provider,还是理解现有压测流程的每一环,这份契约都是最值得先读的入口。
- API网关
- 后端
- LLM 网关
- 微服务
- 人工智能
【免费下载链接】kong
🦍 The API and AI Gateway
相关推荐
Langflow基础设施:Terraform自动化
Langflow基础设施:Terraform自动化 概述:为什么需要基础设施即代码 在现代AI应用开发中,Langflow作为可视化多智能体和RAG(Retri
人工智能大模型AI AgentRAG后端前端MCP 服务工作流自动化10分钟上手!Terraform基础设施自动化测试实战指南
10分钟上手!Terraform基础设施自动化测试实战指南 Terraform是一款流行的开源工具,用于构建、变更和版本化云基础架构。它支持多种云提供商以及本地
IaCCLI基础设施云原生DevOpsMetallb测试环境自动化:使用Terraform搭建基础设施
Metallb测试环境自动化:使用Terraform搭建基础设施 Metallb作为Kubernetes的网络负载均衡器实现,需要可靠的测试环境验证其功能。本文
云原生网络
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考