关于 aws-ecs-service-connect-ipv6
面向排查 ECS Service Connect IPv6 连接故障的技能,解释 IPv4-only Fargate task 遇到 IPv6 地址时的原因,并整理协议、DNS 和客户端侧的规避方法。
主要功能
- 01说明 IPv6 连接失败原因
- 02提供切换 OTLP HTTP 方法
- 03介绍 Cloud Map A 记录方案
- 04列出 Go 客户端 IPv4 配置
- 05提供 DNS 诊断命令
适用场景
- 01排查 Fargate task 连接 Service Connect alias 失败
- 02为 OTLP 导出选择规避方案
- 03检查 DNS 是否返回 IPv6 地址
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mizchi/ skills --skill aws-ecs-service-connect-ipv6安装后在 Claude Code 中输入/aws-ecs-service-connect-ipv6确认已加载。
附带文件README.md
详细介绍
ECS Service Connect 的 IPv6 alias 遇到问题时
症状
尝试从 Fargate 任务内部连接 Service Connect alias(<service>.<namespace>.local:<port>)时出现以下错误:
dial tcp [2600:f0f0::3]:<port>: connect: network is unreachable
2600:f0f0::3 是 AWS Service Connect Envoy proxy 监听的 IPv6 地址。
原因
ECS Service Connect 会为 service alias 注册 IPv4 + IPv6(Envoy proxy 通过 dual-stack 监听)。另一方面,Fargate awsvpc 任务默认 仅支持 IPv4。当 grpc-go 或其他 dual-stack 客户端选择 DNS 最先返回的 IPv6 地址时,由于没有 IPv6 出站路径,连接会不可达。
解决方法(从简单到复杂)
A. 切换为 HTTP 协议
使用 OTLP HTTP(4318)代替 OTLP gRPC(4317)。HTTP 客户端(例如 Go 的 net/http)通常会尝试 IPv4,因此较少遇到 dual-stack 拨号问题。
OpenTelemetry Collector 示例:
exporters:
# 旧: otlp (gRPC) で IPv6 で詰まる
# otlp/tempo:
# endpoint: tempo.study-aws.local:4317
# 新: otlphttp で OK
otlphttp/tempo:
endpoint: http://tempo.study-aws.local:4318
tls:
insecure: true
service:
pipelines:
traces:
exporters: [otlphttp/tempo]
target 侧的 Service Connect 设置也要将 HTTP port(4318)设为 alias:
service_connect_configuration {
service {
port_name = "otlp-grpc"
discovery_name = "tempo"
client_alias { port = 4317; dns_name = "tempo.study-aws.local" }
}
service {
port_name = "otlp-http"
discovery_name = "tempo-http"
client_alias { port = 4318; dns_name = "tempo.study-aws.local" }
}
}
B. Cloud Map private DNS namespace + A record(仅 IPv4)
不要使用 Service Connect(aws_service_discovery_http_namespace),而是使用 Service Discovery(aws_service_discovery_private_dns_namespace)+ aws_service_discovery_service 直接注册 A record。这样不会经过 Envoy proxy,而是直接返回 Cloud Map 的 A record(IPv4)。将 AWS::ServiceDiscovery::Service 的 DnsConfig.DnsRecords 设为仅包含 A。
通过 ECS Service 的 service_registries 附加。这样将无法使用 Service Connect 的功能(Envoy mesh),但不会出现 IPv6 问题。
C. 在客户端强制使用 IPv4
如果使用 Go,可通过 GODEBUG=netdns=go+1 启用 gai.conf 设置,并在 /etc/gai.conf 中设置 precedence ::ffff:0:0/96 100,以提高 IPv4 优先级。可以通过 container env 传入。
不过,如果使用 build-once 的 image,每次都需要重新 build,比更改 Service Connect 设置更麻烦。
诊断
从 ECS Task 内部确认 DNS 解析结果:
aws ecs execute-command --cluster <c> --task <t> --container <name> --interactive --command "/bin/sh -c 'getent hosts tempo.study-aws.local'"
如果返回 IPv6,则可以确定是此问题。
相关信息
- gRPC 基于 HTTP/2,但
grpc-go的 resolver 不容易控制 IP family 的优先顺序 - 在 Service Connect 的 portMappings 中设置
appProtocol = "grpc"可让 Envoy 按 gRPC 处理,但 IPv6 问题是另一回事