通过Java获取EC2实例的实例ID

17

我有一个已部署的 AWS EC2 实例,我需要找到它的公共 IP。但是,为了知道这一点,我必须先知道我的实例的实例 ID。

目标:

  • 我在我的实例中运行了一个 Java 代码,并且想要该代码确定正在运行的实例的当前 IP 或实例 ID。

阅读 Amazon 文档后,我编写了一个 Java 方法,可以返回所有实例的 IP,但这不是我想要的,我想要一个方法仅返回正在运行的实例的实例 ID 或公共 IP 地址。

    /**
     * Returns a list with the public IPs of all the active instances, which are
     * returned by the {@link #getActiveInstances()} method.
     * 
     * @return  a list with the public IPs of all the active instances.
     * @see     #getActiveInstances()
     * */
    public List<String> getPublicIPs(){
        List<String> publicIpsList = new LinkedList<String>();

        //if there are no active instances, we return immediately to avoid extra 
        //computations.
        if(!areAnyActive())
            return publicIpsList;

        DescribeInstancesRequest request =  new DescribeInstancesRequest();
        request.setInstanceIds(instanceIds);

        DescribeInstancesResult result = ec2.describeInstances(request);
        List<Reservation> reservations = result.getReservations();

        List<Instance> instances;
        for(Reservation res : reservations){
            instances = res.getInstances();
            for(Instance ins : instances){
                LOG.info("PublicIP from " + ins.getImageId() + " is " + ins.getPublicIpAddress());
                publicIpsList.add(ins.getPublicIpAddress());
            }
        }

        return publicIpsList;
    }

在这段代码中,我有一个包含所有活动实例的实例ID数组,但我不知道它们是否是“我”本身。因此,我假设我的第一步是要知道我是谁,然后请求我的公共IP地址。

有没有更改我之前所使用方法以得到我想要的结果?有没有更高效的方式来完成它?


2
请参阅以下程序相关内容的翻译:这里是解决方案:http://codeflex.co/java-get-ec2-private-public-ip-and-instance-id/ - ybonda
7个回答

53

我建议使用AWS SDK for Java。

// Resolve the instanceId
String instanceId = EC2MetadataUtils.getInstanceId();

// Resolve (first/primary) private IP
String privateAddress = EC2MetadataUtils.getInstanceInfo().getPrivateIp();

// Resolve public IP
AmazonEC2 client = AmazonEC2ClientBuilder.defaultClient();
String publicAddress = client.describeInstances(new DescribeInstancesRequest()
                                                    .withInstanceIds(instanceId))
                             .getReservations()
                             .stream()
                             .map(Reservation::getInstances)
                             .flatMap(List::stream)
                             .findFirst()
                             .map(Instance::getPublicIpAddress)
                             .orElse(null);

除非Java8可用,否则这将需要更多的样板代码。但简而言之,就是这样。

https://dev59.com/1mAg5IYBdhLWcg3w3eJi#30317951已经提到了EC2MetadataUtils,但这里包括了可用的代码。


@anuj,希望这对你有用,但是我在 AmazonEC2ClientBuilder.defaultClient() 语句中遇到了一个错误。提示没有这样的方法可用。 - user3132347
@user3132347 也许自2015年以来他们已经更改了API,那已经是3年前的事了。还要注意以后的参考:这全部都是关于AWS Java SDK v1的。 - knalli

27

6
以下方法将返回EC2实例ID。
public String retrieveInstanceId() throws IOException {
    String EC2Id = null;
    String inputLine;
    URL EC2MetaData = new URL("http://169.254.169.254/latest/meta-data/instance-id");
    URLConnection EC2MD = EC2MetaData.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(EC2MD.getInputStream()));
    while ((inputLine = in.readLine()) != null) {
        EC2Id = inputLine;
    }
    in.close();
    return EC2Id;
}

从这里开始,您可以执行以下操作以获取信息,例如IP地址(在本示例中为privateIP):

try {
    myEC2Id = retrieveInstanceId();
} catch (IOException e1) {
    e1.printStackTrace(getErrorStream());
}
DescribeInstancesRequest describeInstanceRequest = new DescribeInstancesRequest().withInstanceIds(myEC2Id);
DescribeInstancesResult describeInstanceResult = ec2.describeInstances(describeInstanceRequest);
System.out.println(describeInstanceResult.getReservations().get(0).getInstances().get(0).getPrivateIPAddress());

您还可以使用此方法获取 Java 程序正在运行的当前实例的所有相关信息。只需用适当的获取命令替换 .getPrivateIPAddress() ,即可获取所需信息。可在此处找到可用命令列表:http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/ec2/model/Instance.html
编辑:对于那些可能因为 "未知" URL 而不使用此功能的人,请查看 Amazon 关于此主题的文档,该文档直接指向相同的 URL;唯一的区别是他们是通过 cli 而非 Java 内部执行的。http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

3

我不是Java程序员。然而,我的下面的Ruby代码确实打印了您所需的“running”实例的“Instance ID”和“Public IP”:

ec2.describe_instances(
  filters:[
    {
      name: "instance-state-name",
      values: ["running"]
    }
  ]
).each do |resp|
  resp.reservations.each do |reservation|
    reservation.instances.each do |instance|
        puts instance.instance_id + " ---AND--- " + instance.public_ip_address
    end
  end
end

您只需要在JAVA SDK文档中查找相应的方法/调用即可。您需要查看的代码如下:

  filters:[
    {
      name: "instance-state-name",
      values: ["running"]
    }

在上面的代码块中,我正在过滤出仅处于运行状态的实例。
并且
resp.reservations.each do |reservation|
        reservation.instances.each do |instance|
            puts instance.instance_id + " ---AND--- " + instance.public_ip_address

在上面的代码块中,我运行了2个for循环,并提取了instance.instance_id以及instance.public_ip_address
由于JAVA SDK和Ruby SDK都使用相同的AWS EC2 API,所以JAVA SDK中必须有类似的设置。
此外,您的问题含糊不清,是从需要实例ID的实例运行JAVA代码?还是从另一个实例运行java代码并想拉取所有正在运行的实例的实例ID? 更新: 回答已更改,现在进行更新:
AWS在每个启动的实例上提供元数据服务。您可以在本地轮询元数据服务以找到所需的信息。
从bash提示符下,以下命令提供了实例的实例ID和公共IP地址。
$ curl -L http://169.254.169.254/latest/meta-data/instance-id

$ curl -L http://169.254.169.254/latest/meta-data/public-ipv4

你需要想办法在Java中从上述URL中提取数据。现在你已经有足够的信息了,这个问题与AWS无关,因为现在更多地是一个关于如何轮询上述URL的JAVA问题。


我编辑了我的问题,尽可能地让其更加清晰明了。希望现在所有的含糊不清都已经消失了! - Flame_Phoenix
1
错误,这不是JAVA SDK的缺陷,事实上,AWS EC2 APIs没有这样的功能。它只能使用上述提到的元数据服务来获取,并且我对此并不感到奇怪。 - slayedbylucifer
所以,即使你是Ruby迷、PHP迷或其他什么迷,这是正确的选择,对吧?好吧,我不知道。感谢您的时间。 - Flame_Phoenix
1
这是正确的。由于API本身没有此功能,因此SDK都无法实现。元数据服务是唯一的出路。 - slayedbylucifer
简短版:获取实例 ID 的 URL:http://169.254.169.254/latest/meta-data/instance-id。 - Adrian Seeley
显示剩余3条评论

3

回答最初的问题:

我部署了一个 AWS EC2 实例,需要找到其公网 IP 地址。

您可以使用 AWS API 在 Java 中完成此操作:

EC2MetadataUtils.getData("/latest/meta-data/public-ipv4");

如果存在公共IP,则此方法将直接提供该IP。

1

不使用Java SDK,这不是我正在寻找的解决方案,也无法解决我面临的任何问题。抱歉。 - Flame_Phoenix
1
看来您的答案最终是正确的。这是解决此问题的唯一方法,因为AWS EC2 API没有以其他方式支持此功能。赞++先生。 - Flame_Phoenix

1

我需要执行许多Amazon EC2操作。然后,我实现了一个实用程序类来处理这些操作。也许它对那些到达这里的人有用。我使用了AWS SDK for java version 2进行了实现。这些操作包括:

  • 创建机器;
  • 启动机器;
  • 停止机器;
  • 重启机器;
  • 删除机器(终止);
  • 描述机器;
  • 从机器获取公共IP;

AmazonEC2类

import govbr.cloud.management.api.CloudManagementException;
import govbr.cloud.management.api.CloudServerMachine;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.exception.SdkServiceException;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.Instance;
import software.amazon.awssdk.services.ec2.model.InstanceNetworkInterface;
import software.amazon.awssdk.services.ec2.model.InstanceType;
import software.amazon.awssdk.services.ec2.model.RebootInstancesRequest;
import software.amazon.awssdk.services.ec2.model.Reservation;
import software.amazon.awssdk.services.ec2.model.RunInstancesRequest;
import software.amazon.awssdk.services.ec2.model.RunInstancesResponse;
import software.amazon.awssdk.services.ec2.model.StartInstancesRequest;
import software.amazon.awssdk.services.ec2.model.StopInstancesRequest;
import software.amazon.awssdk.services.ec2.model.TerminateInstancesRequest;


public class AmazonEC2 {

    private final static String EC2_MESSAGE_ERROR = "A error occurred on the     Ec2.";
    private final static String CLIENT_MESSAGE_ERROR = "A error occurred in client side.";
    private final static String SERVER_MESSAGE_ERROR = "A error occurred in Amazon server.";
    private final static String UNEXPECTED_MESSAGE_ERROR = "Unexpected error occurred.";


    private Ec2Client buildDefaultEc2() {

        AwsCredentialsProvider credentials = AmazonCredentials.loadCredentialsFromFile();

        Ec2Client ec2 = Ec2Client.builder()
                .region(Region.SA_EAST_1)
                .credentialsProvider(credentials)                            
                .build();

        return ec2;
    }

    public String createMachine(String name, String amazonMachineId) 
                        throws CloudManagementException {
        try {
            if(amazonMachineId == null) {
                amazonMachineId = "ami-07b14488da8ea02a0";              
            }       

            Ec2Client ec2 = buildDefaultEc2();           

            RunInstancesRequest request = RunInstancesRequest.builder()
                    .imageId(amazonMachineId)
                    .instanceType(InstanceType.T1_MICRO)
                    .maxCount(1)
                    .minCount(1)
                    .build();

            RunInstancesResponse response = ec2.runInstances(request);

            Instance instance = null;

            if (response.reservation().instances().size() > 0) {
                instance = response.reservation().instances().get(0);
            }

            if(instance != null) {
                System.out.println("Machine created! Machine identifier: " 
                                    + instance.instanceId());
                return instance.instanceId();
            }

            return null;

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }       
    }

    public void startMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            StartInstancesRequest request = StartInstancesRequest.builder()
                                             .instanceIds(instanceId).build();
            ec2.startInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public void stopMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            StopInstancesRequest request = StopInstancesRequest.builder()
                                              .instanceIds(instanceId).build();
            ec2.stopInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public void rebootMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            RebootInstancesRequest request = RebootInstancesRequest.builder()
                                              .instanceIds(instanceId).build();
            ec2.rebootInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public void destroyMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            TerminateInstancesRequest request = TerminateInstancesRequest.builder()
       .instanceIds(instanceId).build();
            ec2.terminateInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public String getPublicIpAddress(String instanceId) throws CloudManagementException {
        try {

            Ec2Client ec2 = buildDefaultEc2();

            boolean done = false;

            DescribeInstancesRequest request = DescribeInstancesRequest.builder().build();

            while(!done) {
                DescribeInstancesResponse response = ec2.describeInstances(request);

                for(Reservation reservation : response.reservations()) {
                    for(Instance instance : reservation.instances()) {
                        if(instance.instanceId().equals(instanceId)) {
                            if(instance.networkInterfaces().size() > 0) {
                                InstanceNetworkInterface networkInterface = 
                                           instance.networkInterfaces().get(0);
                                String publicIp = networkInterface
                                                     .association().publicIp();
                                System.out.println("Machine found. Machine with Id " 
                                                   + instanceId 
                                                   + " has the follow public IP: " 
                                                   + publicIp);
                                return publicIp;
                            }                           
                        }
                    }
                }

                if(response.nextToken() == null) {
                    done = true;
                }
            }

            return null;

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public String describeMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();          

            boolean done = false;

            DescribeInstancesRequest request = DescribeInstancesRequest.builder().build();

            while(!done) {
                DescribeInstancesResponse response = ec2.describeInstances(request);

                for(Reservation reservation : response.reservations()) {
                    for(Instance instance : reservation.instances()) {
                        if(instance.instanceId().equals(instanceId)) {                          
                            return "Found reservation with id " +
                                    instance.instanceId() +
                                    ", AMI " + instance.imageId() + 
                                    ", type " + instance.instanceType() + 
                                    ", state " + instance.state().name() + 
                                    "and monitoring state" + 
                                    instance.monitoring().state();                          
                        }
                    }
                }

                if(response.nextToken() == null) {
                    done = true;
                }
            }

            return null;

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

}

AmazonCredentials类:
import java.io.InputStream;

import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.profiles.ProfileFile.Type;

public class AmazonCredentials {


public static AwsCredentialsProvider loadCredentialsFromFile() {
    InputStream profileInput = ClassLoader.getSystemResourceAsStream("credentials.profiles");

    ProfileFile profileFile = ProfileFile.builder()
            .content(profileInput)
            .type(Type.CREDENTIALS)
            .build();

    AwsCredentialsProvider profileProvider = ProfileCredentialsProvider.builder()
            .profileFile(profileFile)
            .build();

    return profileProvider;
}

}

CloudManagementException类:
public class CloudManagementException extends RuntimeException {

private static final long serialVersionUID = 1L;


public CloudManagementException(String message) {
    super(message);
}

public CloudManagementException(String message, Throwable cause) {
    super(message, cause);
}

}

credentials.profiles:

[default]
aws_access_key_id={your access key id here}
aws_secret_access_key={your secret access key here}

我希望能帮到您 o/


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