You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kong Gateway自定义插件部署报错求助及插件优化咨询

Kong容器崩溃问题排查与自定义插件潜在风险分析

一、容器崩溃错误解决

容器启动时出现module 'kong.plugins.oauth2.secret' not found错误,原因及解决方案如下:

错误原因

  • 使用了Kong Gateway(企业版)镜像,该镜像默认启用RBAC组件,但未授权状态下部分依赖模块缺失;
  • 声明式配置或环境变量触发了oauth2插件加载,但对应模块未完整安装。

解决方案

  1. 替换为社区版镜像
    修改docker-compose.yml中的镜像为社区版(无需授权,组件完整):
    image: kong/kong:latest
    
  2. 清理旧资源后重启
    执行命令彻底清理旧容器与卷,避免缓存干扰:
    docker-compose down -v
    docker-compose up -d
    
  3. 锁定插件加载范围
    确保KONG_PLUGINS环境变量仅包含需要的插件:
    KONG_PLUGINS=bundled, lambda_s3_handler
    

二、自定义插件lambda_s3_handler的潜在问题

1. AWS签名不完整

当前invoke_lambda函数中手动构造的Authorization头仅包含Access Key ID,缺少AWS4-HMAC-SHA256签名的核心参数(如签名日期、签名值、算法等),Lambda会直接拒绝请求。

修复建议:使用resty.aws或Kong官方AWS SDK自动生成合法签名,避免手动拼接。

2. 大文件内存溢出风险

处理超过6MB的Base64 PDF时,ngx.decode_base64会将整个文件解码后加载到内存,可能导致Kong Worker进程内存溢出(OOM),直接影响服务稳定性。

优化建议:

  • 通过KONG_CLIENT_MAX_BODY_SIZE环境变量设置合理的请求体上限;
  • 实现流式解码与上传,避免一次性加载整个文件到内存。

3. 错误处理存在漏洞

  • Lambda返回的响应可能不是合法JSON,直接调用cjson.decode会抛出未捕获的错误,导致请求中断;
  • S3上传仅检查请求是否发送成功,未校验响应状态码(如403权限错误、500服务错误等),无法准确判断上传结果。

修复建议:

  • 用pcall包裹JSON解码逻辑,捕获解码错误:
    local success, lambda_result = pcall(cjson.decode, res.body)
    if not success then
        return nil, "Lambda response decode failed: " .. lambda_result
    end
    
  • 校验S3响应状态码:
    if res.status ~= 200 and res.status ~= 201 then
        return false, "S3 upload failed with status: " .. res.status .. ", body: " .. res.body
    end
    

4. 配置硬编码,灵活性不足

代码中直接写死AWS区域、Lambda函数名、S3桶名的默认值,不符合Kong插件的配置规范,无法通过Admin API或声明式配置动态修改。

优化建议:通过插件conf参数传递配置,在handler.lua中读取:

function LambdaS3Handler:access(conf)
    local AWS_REGION = conf.aws_region
    local LAMBDA_FUNCTION = conf.lambda_function
    local S3_BUCKET = conf.s3_bucket
    -- 后续逻辑
end

同时在kong.yml中配置插件参数:

- name: lambda_s3_handler
  route: my-lambda-route_2
  config:
    aws_region: "regionname"
    lambda_function: "lambdafunctionname"
    s3_bucket: "bucketname"

5. 同步请求导致响应延迟

Lambda调用与S3上传均为同步阻塞操作,会显著增加用户请求的响应时间,高并发场景下可能导致Kong Worker线程耗尽。

优化建议:将S3上传逻辑放到log阶段异步执行,提前返回UUID给用户,降低延迟。

6. 凭证管理不安全

直接通过os.getenv获取AWS密钥,存在环境变量泄露风险;未使用Kong Secrets管理或IAM角色(若部署在AWS环境)。

优化建议:

  • 若部署在ECS/EKS,为容器绑定IAM角色,无需手动配置密钥;
  • 使用Kong Secrets插件存储AWS密钥,通过kong.secrets.get()读取。

7. 请求体大小限制未适配

Kong默认client_max_body_size为10MB,若PDF解码后超过该值,会直接拒绝请求。

修复建议:在docker-compose.yml中添加环境变量:

- KONG_CLIENT_MAX_BODY_SIZE=20M

附:用户提供的配置与代码

kong.yml

_format_version: "3.0"
_transform: true

services:
- name: online-test  # <just to check if connection is working
  url: https://httpstat.us/200
- name: aws-ping-test   # <just to check if connection is working
  url: https://lambda.eu-central-1.amazonaws.com
- name: lambda-s3-service
  url: https://lambda.eu-central-1.amazonaws.com

routes:
- name: my-online-test
  service: online-test
  paths:
    - /online
- name: my-aws-ping-test
  service: aws-ping-test
  paths:
    - /aws-ping
- name: my-lambda-route
  paths:
    - /lambda 

- name: my-lambda-route_2
  service: lambda-s3-service
  paths:
    - /lambda-2


plugins:
- name: aws-lambda
  route: my-lambda-route
  config:
    aws_region: "regionname"
    function_name: "lambdafunctionname"
    invocation_type: "RequestResponse"
    log_type: "Tail"
    forward_request_body: true
    forward_request_headers: true
    forward_request_uri: true

- name: lambda_s3_handler
  route: my-lambda-route_2

docker-compose.yml

version: '3.3'

services:
  kong:
    image: kong/kong-gateway:latest
    container_name: kong
    volumes:
      - "./config:/usr/local/kong/declarative"
      #- "./.aws:/usr/local/kong/declarative"
      - "./plugins:/usr/local/share/lua/5.1/kong/plugins"

    environment:
      - KONG_DATABASE=off
      - KONG_DECLARATIVE_CONFIG=/usr/local/kong/declarative/kong.yml
      - KONG_PROXY_ACCESS_LOG=/dev/stdout
      - KONG_ADMIN_ACCESS_LOG=/dev/stdout
      - KONG_PROXY_ERROR_LOG=/dev/stderr
      - KONG_ADMIN_ERROR_LOG=/dev/stderr
      - KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl
      - KONG_LOG_LEVEL=debug
      - KONG_PLUGINS=bundled, lambda_s3_handler
      - KONG_ADMIN_GUI_URL=http://localhost:8002
      - AWS_DEFAULT_REGION=regionname
      - AWS_REGION=regionname
      - AWS_SHARED_CREDENTIALS_FILE=/usr/local/kong/declarative/credentials
      - AWS_PROFILE=profilename

    ports:
      - "8000:8000/tcp"
      - "127.0.0.1:7990:8001/tcp"
      - "8001:8001/tcp"
      - "8443:8443/tcp"
      - "127.0.0.1:8444:8444/tcp"
      #- "127.0.0.1:8001:8001/tcp"
    networks:
      - learn-networking

networks:
  learn-networking:
    external: true
    driver: bridge

handler.lua

local cjson = require "cjson"
local http = require "resty.http"
local base64 = require "ngx.base64"


local LambdaS3Handler = {
    PRIORITY = 1000,
    VERSION = "1.0.0"
}

-- AWS credentials (ensure they are set in environment variables)
local AWS_REGION = os.getenv("AWS_REGION") or "regionname"
local LAMBDA_FUNCTION = os.getenv("AWS_LAMBDA_FUNCTION") or "lambdafunctionname"
local S3_BUCKET = os.getenv("AWS_S3_BUCKET") or "bucketname"

-- Function to invoke AWS Lambda
local function invoke_lambda(filename, email_text)
    local function_name = LAMBDA_FUNCTION
    local payload = { FileName = filename, EmailText = email_text}

    local httpc = http.new()
    local res, err = httpc:request_uri("https://lambda." .. AWS_REGION .. ".amazonaws.com/2015-03-31/functions/" .. function_name .. "/invocations", {
        method = "POST",
        body = cjson.encode(payload),
        headers = {
            ["Content-Type"] = "application/json",
            ["Authorization"] = "AWS4-HMAC-SHA256 Credential=" .. os.getenv("AWS_ACCESS_KEY_ID"),
        },
    })

    if not res then
        return nil, "Failed to invoke Lambda: " .. (err or "Unknown error")
    end

    local lambda_result = cjson.decode(res.body)
    return lambda_result.uuid
end

-- Function to upload file to S3
local function upload_to_s3(uuid, file_data)
    local httpc = http.new()
    local s3_url = "https://" .. S3_BUCKET .. ".s3." .. AWS_REGION .. ".amazonaws.com/" .. uuid .. ".pdf"

    local res, err = httpc:request_uri(s3_url, {
        method = "PUT",
        body = file_data,
        headers = {
            ["Content-Type"] = "application/pdf",
            ["x-amz-acl"] = "bucket-owner-full-control",
        }
    })

    if not res then
        return false, "Failed to upload file to S3: " .. (err or "Unknown error")
    end

    return true
end

-- Main Kong request handler
function LambdaS3Handler:access(conf)
    -- Read JSON body from the request
    ngx.req.read_body()
    local body = ngx.req.get_body_data()

    if not body then
        return kong.response.exit(400, { message = "Invalid request, no body provided" })
    end

    local data = cjson.decode(body)
    if not data.FileName or not data.EmailText or not data.Base64File then
        return kong.response.exit(400, { message = "Missing required fields" })
    end

    -- Step 1: Invoke Lambda
    local uuid, err = invoke_lambda(data.FileName, data.EmailText)
    if not uuid then
        return kong.response.exit(500, { message = "Lambda invocation failed: " .. err })
    end

    -- Step 2: Decode Base64 and upload to S3
    local file_bytes = ngx.decode_base64(data.Base64File)
    local success, upload_err = upload_to_s3(uuid, file_bytes)

    if not success then
        return kong.response.exit(500, { message = "S3 upload failed: " .. upload_err })
    end

    -- Step 3: Return UUID to user
    return kong.response.exit(200, { uuid = uuid })
end

return LambdaS3Handler

内容的提问来源于stack exchange,提问作者MaxS.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 02:12:03