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

使用PublicDnsNamespace配置Fargate服务CloudMap遇问题求助

Fargate服务发现与跨账号DNS委托问题解析

问题背景

我正尝试搭建一组需互相通信的Fargate服务,其中一个通过负载均衡器对外开放。当前使用PublicDnsNamespace,通过FargateService的cloudMapOptions关联到服务。使用的是另一个账号的VPC(无法修改但拥有子网权限),域名是另一个账号HostedZone的子域,且具备该域的委托角色。

PublicDnsNamespace和FargateServices均已正常启动,但服务无法解析任何主机名,推测原因是PublicDnsNamespace创建的HostedZone的域名服务器未配置到父账号的HostedZone中。

尝试使用CrossAccountZoneDelegationRecord创建NS记录时,出现如下错误:

(internalzonedelegationCrossAccountZoneDelegationCustomResource3DD11448) Received response status [FAILED] from custom resource. Message returned: TypeError: Cannot read properties of undefined (reading 'map')
    at r (/var/task/index.js:1:1466)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Runtime.handler (/var/task/__entrypoint__.js:1:952) (RequestId: 570780ca-f06e-459b-bcd1-b1df2928ff9b)

经排查,错误由传入CrossAccountZoneDelegation lambda函数的HostedZone域名服务器为null导致。基础栈代码如下:

export class Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    /* Create a PublicDnsNamespace and delegate its created HostedZone
     * to the parent internal domain name using the delegation role*/

    const dnsNamespace = new serviceDiscovery.PublicDnsNamespace(this, 'namespace', {
      name: props.internalDomainName,
    });

    if (props.internalDelegationRoleArn) {
      const internalDelegationRole = iam.Role.fromRoleArn(this, 'internal-zone-delegationRole', props.internalDelegationRoleArn);

      new r53.CrossAccountZoneDelegationRecord(this, 'internal-zone-delegation', {
        delegatedZone: r53.HostedZone.fromHostedZoneAttributes(this, 'internal-zone', {
          hostedZoneId: dnsNamespace.namespaceHostedZoneId,
          zoneName: props.internalDomainName
        }),
        parentHostedZoneName: props.internalParentDomainName,
        delegationRole: internalDelegationRole,
      });
    }

    const vpc = ec2.Vpc.fromLookup(this, 'apps-vpc', {
      vpcName: 'apps-vpc',
    });

    const cluster = new ecs.Cluster(this, 'cluster', {
      vpc: vpc,
    });

    // Test service
    const testTask = new ecs.FargateTaskDefinition(this, 'test-task', {
      memoryLimitMiB: 512,
      cpu: 256,
    });

    testTask.addContainer('test-container', {
      image: ecs.ContainerImage.fromRegistry('alpine'),
      command: ['sh', '-c', `while true; do wget -O - http://service.${dnsNamespace.namespaceName}/healthCheck; sleep 60; done`],
      logging: new ecs.AwsLogDriver({
        logGroup: loggingGroup,
        streamPrefix: 'test-container',
      }),
    });

    new ecs.FargateService(this, 'test-service', {
      cluster: cluster,
      taskDefinition: testTask,
      assignPublicIp: true,
      desiredCount: 1,
      vpcSubnets: props.subnetFilter,
      cloudMapOptions: {
        name: 'test-service',
        cloudMapNamespace: dnsNamespace,
        dnsRecordType: serviceDiscovery.DnsRecordType.A,
      },
    });
  }
}

问题解答

1. 如何解决上述错误?

错误根源在于使用r53.HostedZone.fromHostedZoneAttributes导入托管区时,仅传入了hostedZoneId和zoneName,未提供nameServers参数,导致CrossAccountZoneDelegationRecord的自定义资源无法获取域名服务器列表,触发map操作的未定义错误。

修复方法很简单:直接使用PublicDnsNamespace实例自带的hostedZone属性作为delegatedZone参数。因为该属性是CDK自动关联的托管区对象,包含了完整的域名服务器信息,无需手动导入。

修改后的代码片段:

if (props.internalDelegationRoleArn) {
  const internalDelegationRole = iam.Role.fromRoleArn(this, 'internal-zone-delegationRole', props.internalDelegationRoleArn);

  new r53.CrossAccountZoneDelegationRecord(this, 'internal-zone-delegation', {
    delegatedZone: dnsNamespace.hostedZone, // 直接使用namespace创建的HostedZone对象
    parentHostedZoneName: props.internalParentDomainName,
    delegationRole: internalDelegationRole,
  });
}

2. 这种实现Fargate服务间发现与通信的方式是否为最优方案?

当前方案并非最优,需根据服务的访问范围调整:

当前方案的优缺点

  • 优点:利用Cloud Map自动注册Fargate实例,简化服务发现配置;跨账号DNS委托实现子域的独立管理,适合需要公网可访问的服务。
  • 缺点:PublicDnsNamespace会将服务DNS记录暴露到公网,若服务仅需VPC内部通信,存在不必要的安全风险;跨账号DNS委托需要额外的权限配置,且依赖Route53的跨账号操作逻辑。

更优方案建议

  • 内部服务优先用PrivateDnsNamespace:如果服务仅需在VPC内部通信,改用PrivateDnsNamespace并关联目标VPC,这样DNS记录仅在指定VPC内可解析,安全性更高。示例代码:
    const dnsNamespace = new serviceDiscovery.PrivateDnsNamespace(this, 'namespace', {
      name: props.internalDomainName,
      vpc: vpc, // 关联到目标VPC
    });
    
    跨账号访问可通过RAM共享Private HostedZone,或配置VPC peering并关联托管区实现。
  • 公网服务需强化安全:若必须使用PublicDnsNamespace,需确保父域NS记录委托配置正确,同时通过Fargate安全组限制仅允许必要的IP或服务访问,避免公网暴露带来的风险。
  • 服务间通信优化:无需对外暴露的服务,尽量使用VPC内部的服务发现机制,减少公网DNS解析的开销和安全隐患。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:15:55