Lura v2.14.1 Ubuntu 22.04 安装指南
在 Ubuntu 22.04 上用 Lura v2.14.1 框架源码编译 API 网关二进制并以 systemd 托管,附 KrakenD CE 2.13.11 官方 deb 仓库安装对照方案。
Lura v2.14.1 Ubuntu 22.04 安装指南
目标:在 Ubuntu 22.04 上用 Lura v2.14.1 框架源码编译 API 网关二进制并以 systemd 托管,同时给出 KrakenD CE 2.13.11 官方 deb 仓库安装的对照方案。已在 Ubuntu 22.04 实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64),root 用户操作
- 架构:linux/amd64
- Go 工具链:go1.25.0(官方 tar 包安装至 /usr/local/go)
- Lura 版本:v2.14.1(GitHub 源码 tag,commit 615be1ef85a96eda2fa99d473643008769764c72)
- 对照方案:KrakenD CE 2.13.11(官方 deb 仓库,内嵌 Lura v2.14.x 引擎)
- 演示后端:Python 脚本模拟的两个 JSON 服务,监听 8090(产品)、8091(库存)
- 端口:自建网关监听 8080
- 配置文件路径:自建网关
/etc/lura/lura.json、二进制/usr/local/bin/lura-gateway;KrakenD CE 配置/etc/krakend/krakend.json
二、Lura 与 KrakenD:先分清两个名字
Lura(github.com/luraproject/lura)是 KrakenD 团队开源的 API 网关框架,Go 语言编写,Apache 2.0 协议。它不是一个可以直接 apt 安装的可执行程序,而是一个 库:你在自己的 main.go 里引用 Lura 引擎,配合一份 JSON/YAML 配置,编译出一个属于你自己的网关二进制。Lura 项目只在 GitHub 发布源码 tag,不提供任何预编译产物。
KrakenD Community Edition(CE)则是 官方把 Lura 引擎打包好的发行版:内置日志、遥测、限流、JWT 校验、熔断等中间件装配,提供 deb/rpm 安装包和官方交付渠道,配置文件为 krakend.json。本文以 Lura v2.14.1 为主线实测(KrakenD CE 2.13.11 的 go.mod 依赖正是 Lura v2.14.x 系列开发版,两者同源)。
💡 技术拓展:Lura 框架与 KrakenD CE 发行版的关系,类似 Electron 与 VS Code——前者是引擎,后者是产品。选型的实际差别:
维度 裸 Lura 框架 KrakenD CE 发行版 交付形态 源码 tag,自行编译 deb/rpm 包,开箱即用 中间件(限流/JWT/熔断/遥测) 核心不含,需自己引入组件装配 全部内置,配置即用 配置文件 lura.json(自己定路径)krakend.json(固定路径)升级维护 跟 go.mod 依赖升级,自担兼容性 apt/yum 一条命令升级 二次开发空间 完全自由(改引擎行为、加插件) 仅限官方暴露的配置面与插件机制 简单结论:只想跑网关用 KrakenD CE;要深度定制引擎行为才直接用 Lura。
再从更大的选型面看 API 网关:
💡 技术拓展:常见开源 API 网关对比(截至 Lura v2.14.1 时代):
网关 语言/内核 定位 特点 Lura / KrakenD Go 无状态聚合网关 配置驱动、端点聚合、无数据库、进程即网关 Kong Lua(OpenResty)+ PostgreSQL 全功能 API 管理平台 插件生态最全,依赖数据存储 Apache APISIX Lua + etcd 云原生动态网关 热更新、控制面数据面分离 Traefik Go 边缘路由/入口网关 自动服务发现、面向 Kubernetes 入口 Nginx + OpenResty C + Lua 反向代理生态 性能基准最好,聚合能力需手写 Lura/KrakenD 的差异化在于"聚合"与"无状态":一个端点可以并发调用多个后端并把结果合并为一个响应,且网关进程不依赖任何数据库。
三、环境准备:安装 Go 1.25 编译工具链
本文全程在 Ubuntu 22.04.5 LTS(x86_64)以 root 实测。Lura v2.14.1 的 go.mod 声明要求 Go 1.25.0,因此直接安装该版本官方 tar 包:
root@ubuntu22:~# apt-get update -qq
root@ubuntu22:~# apt-get install -y -qq curl git ca-certificates
root@ubuntu22:~# cd /tmp
root@ubuntu22:/tmp# curl -sLO https://go.dev/dl/go1.25.0.linux-amd64.tar.gz
root@ubuntu22:/tmp# ls -la go1.25.0.linux-amd64.tar.gz
-rw-r--r-- 1 root root 59659213 Oct 17 02:07 go1.25.0.linux-amd64.tar.gz
root@ubuntu22:/tmp# tar -C /usr/local -xzf go1.25.0.linux-amd64.tar.gz
root@ubuntu22:/tmp# export PATH=$PATH:/usr/local/go/bin
root@ubuntu22:/tmp# go version
go version go1.25.0 linux/amd64
⚠️ 排障实录:如果直接
apt install golang-go,Ubuntu 22.04 源里的 Go 是 1.18,用go mod tidy拉取 Lura v2.14.1 时会报go.mod requires go >= 1.25.0直接失败。必须按上文方式安装 go.dev 的官方 tar 包。
把 Go 写入环境变量,让重启后依然生效:
root@ubuntu22:/tmp# echo 'export PATH=$PATH:/usr/local/go/bin:/root/go/bin' >> /root/.bashrc
root@ubuntu22:/tmp# source /root/.bashrc
四、获取 Lura 框架源码
克隆 v2.14.1 tag(浅克隆只取该 tag 一个提交,速度快):
root@ubuntu22:~# cd /opt
root@ubuntu22:/opt# git clone --depth 1 --branch v2.14.1 https://github.com/luraproject/lura.git lura-src
Cloning into 'lura-src'...
Note: switching to '615be1ef85a96eda2fa99d473643008769764c72'.
root@ubuntu22:/opt# ls lura-src | head -8
CODE_OF_CONDUCT.md
CONTRIBUTING.md
LICENSE
Makefile
README.md
SECURITY.md
async
backoff
克隆时 git 会提示 You are in 'detached HEAD' state,这是 tag 克隆的正常现象,无需处理。
⚠️ 排障实录:国外网络环境下 GitHub 克隆缓慢或超时,可改走代理:
git clone -c http.proxy=http://192.168.1.62:7897 --depth 1 --branch v2.14.1 https://github.com/luraproject/lura.git lura-src,或使用镜像站点https://gitee.com/mirrors/lura.git(同步略有延迟)。
💡 技术拓展:
--depth 1是浅克隆,只拉最近一次提交,省时省空间。Lura 的源码里没有cmd/目录——确认了它"只有库没有可执行入口"的定位,Makefile的generate目标编译的全部是测试用插件示例。
五、编写网关主程序并构建二进制
5.1 创建工程与 main.go
新建工程目录 /opt/lura-gateway,写入网关主程序。这段代码就是 Lura 官方 README 给出的最小装配:解析配置 → 构建日志器 → 组装 gin 路由工厂与默认代理工厂 → 启动:
root@ubuntu22:~# mkdir -p /opt/lura-gateway && cd /opt/lura-gateway
root@ubuntu22:/opt/lura-gateway# cat > main.go << 'EOF'
package main
import (
"flag"
"log"
"os"
"github.com/luraproject/lura/v2/config"
"github.com/luraproject/lura/v2/logging"
"github.com/luraproject/lura/v2/proxy"
"github.com/luraproject/lura/v2/router/gin"
)
func main() {
port := flag.Int("p", 0, "Port of the service")
logLevel := flag.String("l", "ERROR", "Logging level")
debug := flag.Bool("d", false, "Enable the debug")
configFile := flag.String("c", "/etc/lura/lura.json", "Path to the configuration filename")
flag.Parse()
parser := config.NewParser()
serviceConfig, err := parser.Parse(*configFile)
if err != nil {
log.Fatal("ERROR:", err.Error())
}
serviceConfig.Debug = serviceConfig.Debug || *debug
if *port != 0 {
serviceConfig.Port = *port
}
logger, _ := logging.NewLogger(*logLevel, os.Stdout, "[LURA]")
routerFactory := gin.DefaultFactory(proxy.DefaultFactory(logger), logger)
routerFactory.New().Run(serviceConfig)
}
注意 import 路径全部带 /v2 后缀——Lura v2.x 的 Go module 名就是 github.com/luraproject/lura/v2。
5.2 初始化模块并拉取依赖
root@ubuntu22:/opt/lura-gateway# go mod init lura-gateway
go: creating new go.mod: module lura-gateway
root@ubuntu22:/opt/lura-gateway# go mod edit -require=github.com/luraproject/lura/v2@v2.14.1
root@ubuntu22:/opt/lura-gateway# go mod tidy
go mod tidy 完成后,go.mod 内容如下(indirect 依赖以实际解析结果为准):
module lura-gateway
go 1.25.0
require github.com/luraproject/lura/v2 v2.14.1
⚠️ 排障实录:
go mod tidy卡在下载依赖,多因直连proxy.golang.org被墙。设置国内模块代理后重跑即可:go env -w GOPROXY=https://goproxy.cn,direct。
5.3 编译
root@ubuntu22:/opt/lura-gateway# go build -o lura-gateway .
root@ubuntu22:/opt/lura-gateway# ls -la lura-gateway
-rwxr-xr-x 1 root root 23951487 Oct 17 02:08 lura-gateway
root@ubuntu22:/opt/lura-gateway# ./lura-gateway --help
Usage of ./lura-gateway:
-c string
Path to the configuration filename (default "/etc/lura/lura.json")
-d Enable the debug
-l string
Logging level (default "ERROR")
-p int
Port of the service
得到的 lura-gateway 是一个约 24 MB 的静态二进制,四个启动参数:-c 配置路径、-p 覆盖监听端口、-l 日志级别、-d 调试开关。把它放到系统路径:
root@ubuntu22:/opt/lura-gateway# install -m 0755 lura-gateway /usr/local/bin/lura-gateway
root@ubuntu22:/opt/lura-gateway# which lura-gateway
/usr/local/bin/lura-gateway
六、编写网关配置并首次运行
6.1 最小配置
准备两个演示后端(模拟上游 JSON 服务):用 Python 起两个本地 JSON 服务,监听 8090(产品)与 8091(库存):
root@ubuntu22:~# mkdir -p /etc/lura
root@ubuntu22:~# cat > /srv/mock_backend.py << 'EOF'
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json, sys
PORT = int(sys.argv[1])
NAME = sys.argv[2]
DATA = {
"backend-a": {
"/products/1": {"id": 1, "name": "Widget", "price": 9.99, "currency": "USD"},
"/products/2": {"id": 2, "name": "Gadget", "price": 24.50, "currency": "USD"},
},
"backend-b": {
"/stock/1": {"product_id": 1, "in_stock": True, "qty": 42},
"/stock/2": {"product_id": 2, "in_stock": False, "qty": 0},
},
}
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
body = DATA.get(NAME, {}).get(self.path)
if body is None:
self.send_response(404)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"error": "not found", "path": self.path}).encode())
return
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(body).encode())
def log_message(self, *a):
pass
ThreadingHTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
EOF
root@ubuntu22:~# nohup python3 /srv/mock_backend.py 8090 backend-a > /tmp/backend-a.log 2>&1 &
root@ubuntu22:~# nohup python3 /srv/mock_backend.py 8091 backend-b > /tmp/backend-b.log 2>&1 &
root@ubuntu22:~# curl -s http://127.0.0.1:8090/products/1
{"id": 1, "name": "Widget", "price": 9.99, "currency": "USD"}
写网关配置 /etc/lura/lura.json(先配一个透传端点验证链路):
root@ubuntu22:~# cat > /etc/lura/lura.json << 'EOF'
{
"version": 3,
"name": "Lura Demo Gateway",
"port": 8080,
"cache_ttl": "60s",
"timeout": "3s",
"endpoints": [
{
"endpoint": "/api/health",
"method": "GET",
"output_encoding": "no-op",
"backend": [
{
"host": ["http://127.0.0.1:8090"],
"url_pattern": "/products/1",
"encoding": "no-op"
}
]
}
]
}
EOF
6.2 前台启动并验证
root@ubuntu22:~# nohup /usr/local/bin/lura-gateway -c /etc/lura/lura.json -l DEBUG > /tmp/lura-run.log 2>&1 &
root@ubuntu22:~# curl -s http://127.0.0.1:8080/api/health
{"id": 1, "name": "Widget", "price": 9.99, "currency": "USD"}
网关已把 /api/health 转发到 8090 的 /products/1,HTTP 200。
⚠️ 排障实录:
cache_ttl必须写成字符串(如"60s")。写成数字"cache_ttl": 60会直接启动失败,报错原文:2026/10/17 04:01:29 ERROR:'/tmp/lura-bad.json': json: cannot unmarshal number into Go struct field parseableServiceConfig.cache_ttl of type string, offset: 82, row: 4, col: 17同理,
version只接受3(v2.x 系列配置版本号是 3),写成 2 会报unsupported version: 2 (want: 3)。
七、systemd 服务托管
7.1 编写单元文件
root@ubuntu22:~# cat > /etc/systemd/system/lura-gateway.service << 'EOF'
[Unit]
Description=Lura API Gateway
Documentation=https://www.luraproject.org
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/lura-gateway -c /etc/lura/lura.json
ExecStop=/bin/kill -s TERM $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
root@ubuntu22:~# systemctl daemon-reload
root@ubuntu22:~# systemctl enable lura-gateway
Created symlink /etc/systemd/system/multi-user.target.wants/lura-gateway.service → /etc/systemd/system/lura-gateway.service.
7.2 启动与验证
root@ubuntu22:~# systemctl start lura-gateway
root@ubuntu22:~# systemctl is-active lura-gateway
active
root@ubuntu22:~# systemctl status lura-gateway --no-pager -l | head -12
● lura-gateway.service - Lura API Gateway
Loaded: loaded (/etc/systemd/system/lura-gateway.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2026-10-17 02:51:38 UTC; 1h 5min ago
Docs: https://www.luraproject.org
Main PID: 352 (lura-gateway)
Tasks: 5 (limit: 5753)
Memory: 1.6M
CPU: 6ms
CGroup: /system.slice/lura-gateway.service
└─352 /usr/local/bin/lura-gateway -c /etc/lura/lura.json
Oct 17 02:51:38 ubuntu22 systemd[1]: Started Lura API Gateway.
Memory: 1.6M——Lura 引擎的内存占用相当小。验证经 systemd 托管的网关转发正常,并测试重启:
root@ubuntu22:~# curl -s http://127.0.0.1:8080/api/products/1
{"product":{"currency":"USD","id":1,"name":"Widget","price":9.99},"stock":{"in_stock":true,"product_id":1,"qty":42}}
root@ubuntu22:~# systemctl restart lura-gateway && systemctl is-active lura-gateway
active
⚠️ 排障实录:
systemctl status显示Code=killed, signal=TERM反复重启时,先看journalctl -u lura-gateway -n 20。最常见的两个原因:一是配置文件 JSON 语法错误(网关启动即退出),二是 8080 端口被占用(ss -tlnp | grep 8080检查)。
八、对照方案:KrakenD CE 官方 deb 仓库安装
如果不需要改引擎行为,直接装 KrakenD CE 更省事。在另一台干净的 Ubuntu 22.04 上实测(也可与上文共存,但 8080 端口二选一)。
8.1 导入 GPG 公钥并配置仓库
root@ubuntu22:~# apt-get install -y -qq curl gpg ca-certificates
root@ubuntu22:~# curl -s https://repo.krakend.io/apt/dists/stable/Release | head -6
Origin: repo.krakend.io
Label: repo.krakend.io
Suite:
Codename: stable
Date: Tue, 13 Oct 2026 11:41:41 UTC
Architectures: amd64
从 Ubuntu 公钥服务器获取 KrakenD 仓库签名公钥(key ID 5DE6FD698AD6FDD2,即官网 apt-key adv 命令里的指纹尾部),并写入 keyring:
root@ubuntu22:~# gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 5DE6FD698AD6FDD2
gpg: key 5DE6FD698AD6FDD2: public key "KrakenD SA <repo@krakend.io>" imported
gpg: Total number processed: 1
gpg: imported: 1
root@ubuntu22:~# gpg --export 5DE6FD698AD6FDD2 > /usr/share/keyrings/krakend-archive-keyring.gpg
root@ubuntu22:~# echo "deb [signed-by=/usr/share/keyrings/krakend-archive-keyring.gpg] https://repo.krakend.io/apt stable main" > /etc/apt/sources.list.d/krakend.list
root@ubuntu22:~# apt-get update 2>&1 | grep -i krakend
Hit:5 https://repo.krakend.io/apt stable InRelease
⚠️ 排障实录:官网旧文档写的
apt-key adv在 Ubuntu 22.04 已弃用但仍可用;更规范的是上文gpg --export到/usr/share/keyrings/并在 sources 条目里signed-by=指定。若 keyserver 连不上,报错gpg: keyserver receive failed,多试几次或换hkps://keys.openpgp.org。
8.2 安装与版本确认
root@ubuntu22:~# apt-get install -y krakend=2.13.11-0
root@ubuntu22:~# which krakend
/usr/bin/krakend
root@ubuntu22:~# krakend version
KrakenD Version: 2.13.11
Go Version: 1.26.8
Glibc Version: GLIBC-2.36_(debian-12)
安装的是 v2 系列最新维护版 2.13.11(仓库候选版本已是 3.0.1-0,可用 apt-cache policy krakend 查看)。它内置的引擎正是 Lura v2.14.x,证实了两者的同源关系。
8.3 包内容与自带服务
root@ubuntu22:~# dpkg -L krakend | grep -E "systemd|krakend.json"
/lib/systemd
/lib/systemd/system
/lib/systemd/system/krakend.service
/etc/krakend/krakend.json
root@ubuntu22:~# cat /lib/systemd/system/krakend.service
[Unit]
Description=Krakend API Gateway
Documentation=http://krakend.io
After=network.target
[Service]
User=krakend
ExecStart=/usr/bin/krakend run -c /etc/krakend/krakend.json
ExecStop=/bin/kill -s TERM $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
KillMode=process
[Install]
WantedBy=multi-user.target
deb 包自带 systemd 单元(以非 root 的 krakend 用户运行)和默认配置 /etc/krakend/krakend.json。配置校验命令 krakend check:
root@ubuntu22:~# krakend check -c /etc/krakend/krakend.json
Parsing configuration file: /etc/krakend/krakend.json
Syntax OK!
启动服务并验证健康端点:
root@ubuntu22:~# systemctl start krakend
root@ubuntu22:~# systemctl is-active krakend
active
root@ubuntu22:~# curl -s http://127.0.0.1:8080/__health
{"agents":{},"now":"2026-10-17 04:00:52.105542923 +0000 UTC m=+3.050355452","status":"ok"}
💡 技术拓展:
__health、__stats、__debug等以双下划线开头的路径是 KrakenD/Lura 保留的内部端点,自己的端点不能用__前缀,否则配置解析时该端点会被丢弃(报ignoring the '/__xxx' endpoint, since it is invalid)。
九、卸载
9.1 卸载自建 Lura 网关
root@ubuntu22:~# systemctl stop lura-gateway
root@ubuntu22:~# systemctl disable lura-gateway
Removed "/etc/systemd/system/multi-user.target.wants/lura-gateway.service".
root@ubuntu22:~# rm /etc/systemd/system/lura-gateway.service
root@ubuntu22:~# systemctl daemon-reload
root@ubuntu22:~# rm /usr/local/bin/lura-gateway
root@ubuntu22:~# rm -rf /etc/lura /opt/lura-gateway /opt/lura-src
9.2 卸载 KrakenD CE
root@ubuntu22:~# systemctl stop krakend
root@ubuntu22:~# apt-get purge -y krakend
root@ubuntu22:~# rm /etc/apt/sources.list.d/krakend.list
root@ubuntu22:~# rm /usr/share/keyrings/krakend-archive-keyring.gpg
root@ubuntu22:~# apt-get update -qq
如需保留配置供以后重装,用 apt-get remove 代替 purge。
十、参考链接
下一篇推荐:《Lura v2.14.1 Docker Compose 部署指南》——用官方交付物三分钟拉起同样的网关。