mcpField
A
aws-ecs-service-connect-ipv6

aws-ecs-service-connect-ipv6

github.com/mizchi云与 DevOps41649 次安装1 周前更新
代码仓库

关于 aws-ecs-service-connect-ipv6

面向排查 ECS Service Connect IPv6 连接故障的技能,解释 IPv4-only Fargate task 遇到 IPv6 地址时的原因,并整理协议、DNS 和客户端侧的规避方法。

主要功能

  1. 01说明 IPv6 连接失败原因
  2. 02提供切换 OTLP HTTP 方法
  3. 03介绍 Cloud Map A 记录方案
  4. 04列出 Go 客户端 IPv4 配置
  5. 05提供 DNS 诊断命令

适用场景

  1. 01排查 Fargate task 连接 Service Connect alias 失败
  2. 02为 OTLP 导出选择规避方案
  3. 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 问题是另一回事

评论

支持 Markdown