使用BOTO3检索EC2实例的公共DNS

20

我正在使用ipython来了解Boto3和与EC2实例进行交互。这是我用来创建实例的代码:

import boto3

ec2 = boto3.resource('ec2')
client = boto3.client('ec2')


new_instance = ec2.create_instances(
    ImageId='ami-d05e75b8',
    MinCount=1,
    MaxCount=1,
    InstanceType='t2.micro',
    KeyName=<name_of_my_key>,
    SecurityGroups=['<security_group_name>'],
    DryRun = False
    )

启动EC2实例很好,我可以从AWS控制台获取公共DNS名称、IP和其他信息。但是,当我尝试使用Boto获取公共DNS时,执行以下操作:

new_instance[0].public_dns_name
返回空引号。然而,其他实例细节,比如:
new_instance[0].instance_type

返回正确的信息。

有什么想法吗?谢谢。

编辑:

所以如果我这样做:

def get_name(inst):
    client = boto3.client('ec2')
    response = client.describe_instances(InstanceIds = [inst[0].instance_id])
    foo = response['Reservations'][0]['Instances'][0]['NetworkInterfaces'][0]['Association']['PublicDnsName']
    return foo


foo = get_name(new_instance)
print foo

然后它将返回公共 DNS。但我不明白为什么我需要做所有这些。

3个回答

32

你得到的 Instance 对象仅包含从 create_instances 调用的响应属性。由于 DNS 名称直到实例达到运行状态 [1] 才可用,因此它不会立即出现。我想象你创建实例并调用描述实例之间的时间足够让微型实例启动。

import boto3

ec2 = boto3.resource('ec2')
instances = ec2.create_instances(
    ImageId='ami-f0091d91',
    MinCount=1,
    MaxCount=1,
    InstanceType='t2.micro',
    KeyName='<KEY-NAME>',
    SecurityGroups=['<GROUP-NAME>'])
instance = instances[0]

# Wait for the instance to enter the running state
instance.wait_until_running()

# Reload the instance attributes
instance.load()
print(instance.public_dns_name)

我尝试了instance.load,但是它给了我一个错误:"AttributeError: 'dict' object has no attribute 'load'。 - Alex
对于其他遇到Alex问题的人,实例应该是ec2.Instance类型的,请检查您的逻辑。另外,请注意create_instances()的返回值是一个ec2.Instance对象列表。 - The Unknown Dev
谢谢 - 我之前不确定为什么我的实例(即使在使用了等待调用之后)仍然显示为挂起状态,原来是没有使用加载函数。 - Ali

3

这是我的包装器:

import boto3
from boto3.session import Session

def credentials():
    """Credentials:"""
    session = Session(aws_access_key_id= 'XXXXXXXXX',
                      aws_secret_access_key= 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
    ec2 = boto3.resource('ec2', region_name='us-east-2')
    return ec2

def get_public_dns(instance_id):
    """having the instance_id, gives you the public DNS"""
    ec2 = credentials()
    instance = ec2.Instance(instance_id)
    instancePublicDNS = instance.public_dns_name
    return instancePublicDNS

然后您只需要使用实例 ID 获取任何活动 EC2 的公共 DNS:

dns = get_public_dns(instance_id)

记得将 "region_name" 改成您的区域,并添加您的 "aws_access_key_id" 和 "aws_secret_access_key"


1
import boto3
import pandas as pd
session = boto3.Session(profile_name='aws_dev')
dev_ec2_client = session.client('ec2')
response = dev_ec2_client.describe_instances()
df = pd.DataFrame(columns=['InstanceId', 'InstanceType', 'PrivateIpAddress','PublicDnsName'])
i = 0
for res in response['Reservations']:
    df.loc[i, 'InstanceId'] = res['Instances'][0]['InstanceId']
    df.loc[i, 'InstanceType'] = res['Instances'][0]['InstanceType']
    df.loc[i, 'PrivateIpAddress'] = res['Instances'][0]['PrivateIpAddress']
    df.loc[i, 'PublicDnsName'] = res['Instances'][0]['PublicDnsName']
    i += 1
print df

注意:

  1. 将此配置文件更改为您的AWS配置文件名称 profile_name='aws_dev'
  2. 此代码适用于Python3

3
在这种情况下使用pandas似乎过于复杂。 - jarmod
@jarmod:我希望能够将这些值以表格形式展示,这样我们就可以做好清单准备。由于我们从boto3获取的数据是字典结构,在可视化方面非常复杂。而且这是一种模板,我们还会获取其他AWS属性。 - Jitendra Bhalothia
感谢使用pandas,因为它使得理解API接口更容易。 - Joshua Wolff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接