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

如何通过AWS CDK获取EC2实例的公网IP或公网DNS?

在AWS CDK中获取EC2公网IP/DNS的正确姿势

当然可行!我之前帮很多开发者解决过这个问题——你看到的${Token[TOKEN.XX]}是CDK的正常机制,先给你拆解原因,再给几种实用的解决方案:

为什么会出现Token?

CDK是声明式的基础设施即代码工具,在你执行cdk synth或cdk deploy的早期阶段,EC2实例还没被AWS实际创建,所以公网IP、公网DNS这类动态生成的属性还没有真实值。CDK用Token作为占位符,等部署完成后才会被AWS替换成实际的资源值。直接在代码里print的话,只能拿到这个占位符,而不是真实IP/DNS。

解决方案1:用CfnOutput输出部署后的真实值(最常用)

这是最简单直接的方式,部署完成后会在控制台显示结果,也可以导出到文件供SSH/Ansible使用。修改你的代码,在EC2实例定义后添加这两行:

core.CfnOutput(self, "EC2PublicDNS", value=ec2.instance_public_dns_name, description="EC2实例公网DNS")
core.CfnOutput(self, "EC2PublicIP", value=ec2.instance_public_ip, description="EC2实例公网IP")

执行cdk deploy后,控制台会输出类似这样的内容:

Outputs:
WebsiteStack.EC2PublicDNS = ec2-12-34-56-78.us-east-1.compute.amazonaws.com
WebsiteStack.EC2PublicIP = 12.34.56.78

如果想把输出保存到JSON文件(方便脚本读取),用这条命令部署:

cdk deploy --outputs-file ec2-outputs.json

之后你可以直接从ec2-outputs.json里提取IP/DNS,比如用jq命令:

# 获取公网IP
jq -r '.WebsiteStack.EC2PublicIP' ec2-outputs.json

解决方案2:在CDK代码中传递Token给其他资源

如果你的CDK代码需要把公网IP/DNS传给其他资源(比如Lambda函数的环境变量、S3桶的通知配置),直接使用Token即可——CDK会在部署阶段自动把Token替换成真实值,不需要做额外处理:

# 示例:把EC2公网DNS传给Lambda函数
lambda_fn = aws_lambda.Function(
    self, "MyAnsibleTriggerLambda",
    runtime=aws_lambda.Runtime.PYTHON_3_11,
    code=aws_lambda.Code.from_asset("lambda"),
    handler="handler.lambda_handler",
    environment={
        "EC2_PUBLIC_DNS": ec2.instance_public_dns_name,
        "EC2_PUBLIC_IP": ec2.instance_public_ip
    }
)

解决方案3:部署时实时获取并输出(进阶)

如果需要在部署过程中就拿到真实值(而不是等部署完成),可以用CDK的自定义资源(Custom Resource)来调用AWS API查询实例属性。示例代码如下:

from aws_cdk import custom_resources as cr

# 创建一个Lambda函数作为自定义资源的处理器,用于查询EC2实例信息
ec2_info_handler = aws_lambda.Function(
    self, "EC2InfoHandler",
    runtime=aws_lambda.Runtime.PYTHON_3_11,
    code=aws_lambda.Code.from_inline("""
import boto3
import json

def handler(event, context):
    ec2_client = boto3.client('ec2')
    instance_id = event['ResourceProperties']['InstanceId']
    # 查询实例详情
    response = ec2_client.describe_instances(InstanceIds=[instance_id])
    instance_data = response['Reservations'][0]['Instances'][0]
    return {
        'PhysicalResourceId': instance_id,
        'Data': {
            'PublicDnsName': instance_data.get('PublicDnsName', ''),
            'PublicIpAddress': instance_data.get('PublicIpAddress', '')
        }
    }
    """),
    handler="index.handler"
)

# 给Lambda函数添加查询EC2实例的权限
ec2_info_handler.add_to_role_policy(aws_iam.PolicyStatement(
    actions=["ec2:DescribeInstances"],
    resources=["*"]
))

# 创建自定义资源,传入EC2实例ID
ec2_info_resource = cr.AwsCustomResource(self, "EC2InfoResource",
    resource_type="Custom::EC2InstanceInfo",
    service_token=ec2_info_handler.function_arn,
    properties={
        "InstanceId": ec2.instance_id
    }
)

# 输出自定义资源返回的真实IP/DNS
core.CfnOutput(self, "EC2PublicDNS_RealTime", value=ec2_info_resource.get_string("PublicDnsName"))
core.CfnOutput(self, "EC2PublicIP_RealTime", value=ec2_info_resource.get_string("PublicIpAddress"))

这种方式会在EC2实例创建完成后立即查询并输出真实值,适合需要在部署流程中即时获取的场景。


内容的提问来源于stack exchange,提问作者Ikar Pohorský

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:52:42