在 Golang Fargate 任务中访问 DynamoDB

Access DynamoDB in Golang Fargate Task

我正在尝试从我的 Fargate 任务访问 DynamoDB,它是用 golang 编写的。我得到的只是超时。我缺少什么?

我正在使用来自 AWS 实验室 (here) 的 Cloudformation 模板以及允许完全 DynamoDB 访问的任务角色。这是最简单的 public 子网模板加上 Fargate 模板。

我尝试添加 VPC 端点,但没有任何区别。

运行 我机器上的任务有效。 运行 执行(或多或少)相同的 Python (Flask) 任务在本地和 AWS 上都有效。一样的设置,我只是换了个任务图片。

这是代码:

package main

import (
    "context"
    "fmt"
    "github.com/aws/aws-sdk-go-v2/aws/endpoints"
    "github.com/aws/aws-sdk-go-v2/aws/external"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/gin-gonic/gin"
    "time"
)

var db *dynamodb.Client

func init() {
    cfg, err := external.LoadDefaultAWSConfig()
    if err != nil {
        panic("unable to load SDK config, " + err.Error())
    }
    cfg.Region = endpoints.UsEast2RegionID
    db = dynamodb.New(cfg)
}

func main() {
    fmt.Println("go!")
    router := gin.New()
    router.Use(gin.Recovery())
    router.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{"msg": "pong"}) })
    router.GET("/pong", func(c *gin.Context) {
        req := db.ListTablesRequest(&dynamodb.ListTablesInput{})
        ctx := context.Background()
        ctx, cancelFn := context.WithTimeout(ctx, time.Second*5)
        defer cancelFn()
        res, err := req.Send(ctx)
        if err != nil {
            c.JSON(400, gin.H{"msg": "Fail", "error": err.Error()})
            return
        }
        c.JSON(200, gin.H{"msg": fmt.Sprint(res)})
        return
    })
    router.Run()
}

超时:

helles:v2> curl  xyz.us-east-2.elb.amazonaws.com/pong
{"error":"RequestCanceled: request context canceled\ncaused by: context deadline exceeded","msg":"Fail"}

预计:

helles:v2> curl 127.0.0.1:8080/pong
{"msg":"{\n  TableNames: [\"OneTable\",\"OtherTable\"]\n}"}

Python比较:

#!/usr/bin/env python3
from flask import Flask
import boto3

dynamodb = boto3.client("dynamodb")
app = Flask(__name__)

@app.route("/ping")
def index():
    return "pong"

@app.route("/pong")
def pong():
    return dynamodb.list_tables()

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=8080)

结果有点不同,添加了元数据,但是 table 名字在那里。

谢谢

超时通常是网络问题。您是否检查了 ECS 任务和 Dynamo DB 使用的安全组。需要确保您设置了规则以在正确的端口上退出 ECS 并进入 DynamoDB。

您说您在 VPC 中为 Dynamo 设置了端点。如果您正在尝试连接到私有 VPC 中的私有端点,或者您是否正在尝试通过 public 互联网,您的 OP 并不清楚。如果您尝试通过 public 互联网,您还需要检查您的 ECS 任务是否位于具有连接到 public 互联网的 NAT 网关的 VPC 中。看起来您正在尝试通过 127.0.0.1 或 ELB DNS 连接到 DynamoDB 服务,这对我来说没有意义。

回答我自己的问题。

问题出在我使用的 Docker 基本图像上。我的 Docker 文件是:

FROM scratch
ADD ./build/api/api /
EXPOSE 8080
ENTRYPOINT ["/api"]

使用静态链接的可执行文件。

FROM scratch 更改为 FROM gcr.io/distroless/base 使其生效。

我的猜测是 application/dynamodb 客户端无法在缺少基础映像的情况下解析服务地址。

感谢@Dude0001。