如何使用 CLI 检索 Fargate 任务的公共 IP?

问题描述 投票:0回答:6

我有一个运行服务的集群,并且还可以从命令行启动 Fargate 任务。我可以获取 taskArn 作为启动任务的响应,并且可以使用“aws ecs wait”等待任务处于运行状态。我一直在想如何获取任务的公共IP。我可以通过网页轻松找到它,并且可以通过其公共 IP 访问机器...

如何使用 CLI 界面获取 Fargate 任务的公共 IP?

我使用以下命令来启动任务,等待它运行并检索任务描述:

$ aws ecs run-task --launch-type FARGATE --cluster xxxx --task-definition xxxx --network-configuration xxxx
$ aws ecs wait <taskArn>
$ aws ecs describe-tasks --cluster xxxx --task <taskArn> | grep -i ipv4

最后一个命令只给我私有IP...

"privateIpv4Address": "10.0.1.252",
"name": "privateIPv4Address"

我也尝试过使用:

$ ecs-cli ps --cluster xxxx

但是端口栏是空白的。

Name                                       State    Ports  TaskDefinition
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxxx  RUNNING         xxxx:1
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxxx  RUNNING         xxxx:1
amazon-web-services aws-fargate
6个回答
38
投票

一旦我意识到描述任务为我提供了 ENI id 以及私有 IP,我就能够通过以下方式获取公共 IP:

$ aws ec2 describe-network-interfaces --network-interface-ids eni-xxxxxxxx

10
投票

您可以使用这样的脚本。

SERVICE_NAME="my-service"

TASK_ARN=$(aws ecs list-tasks --service-name "$SERVICE_NAME" --query 'taskArns[0]' --output text)
TASK_DETAILS=$(aws ecs describe-tasks --task "${TASK_ARN}" --query 'tasks[0].attachments[0].details')
ENI=$(echo $TASK_DETAILS | jq -r '.[] | select(.name=="networkInterfaceId").value')
IP=$(aws ec2 describe-network-interfaces --network-interface-ids "${ENI}" --query 'NetworkInterfaces[0].Association.PublicIp' --output text)

echo "$IP"

9
投票

这是特定于我的用例的,但也许对其他人有用(旨在在运行 ecs.createService() 后在 Lambda 中作为 javascript 运行)

是的,我知道这个主题是针对 CLI 的,但这是在寻找“Fargate 公共 IP”时弹出的第一个结果,我正在寻找基于 javascript 的解决方案。

// get container IP
getContainerIP(myServiceName).then(ip => {
  console.log("Container IP address is: ", ip);

}).catch(err => {
  console.log(err);
});



function getContainerIP(servicename) {
  // note: assumes that only 1 task with 1 container is in the provided service, and that a container only has 1 network interface

  return new Promise(function (resolve, reject) {
    // get task arns (needs a delay because we just launched it)
    setTimeout(getTasks, 6000);

    // get task arns
    function getTasks() {
      ecs.listTasks({
        cluster: process.env.ecs_cluster,
        launchType: "FARGATE",
        serviceName: servicename
      }, function (err, res) {
        if (err) {
          reject("Unable to get task list");
          return;
        }

        // loop until we have a result
        if (!res.taskArns.length) {
          setTimeout(getTasks, 2000);
          return;
        }

        // get details
        getTaskDetails(res.taskArns);
      });
    }

    // get the details of the task (we assume only one task because that's how its configured)
    function getTaskDetails(taskArns) {
      ecs.describeTasks({
        cluster: process.env.ecs_cluster,
        tasks: taskArns
      }, function (err, res) {
        if (err) {
          reject("Unable to get task details");
          return;
        }

        // no results
        if (!res.tasks.length || !res.tasks[0].attachments.length) {
          reject("No tasks available");
          return;
        }

        // network needs to be in status ATTACHING to see the eni, else wait
        if (res.tasks[0].attachments[0].status !== "ATTACHING") {
          setTimeout(function () { getTaskDetails(taskArns); }, 2000);
          return;
        }

        // get network ID from result
        let eni = "";
        for (let i in res.tasks[0].attachments[0].details) {
          if (!res.tasks[0].attachments[0].details.hasOwnProperty(i)) continue;
          if (res.tasks[0].attachments[0].details[i].name !== "networkInterfaceId") continue;

          // get the eni
          eni = res.tasks[0].attachments[0].details[i].value;
          break;
        }

        // no eni
        if (eni === "") {
          reject("Unable to retrieve container ENI");
          return;
        }

        // get network details
        getNetworkDetails(eni);
      });
    }

    // get network details
    function getNetworkDetails(eni) {

      // get the ENI details
      ec2.describeNetworkInterfaces({
        NetworkInterfaceIds: [eni]
      }, function (err, res) {
        if (err) {
          reject("Unable to retrieve ENI details");
          return;
        }

        // confirm available data
        if (!res.NetworkInterfaces.length || typeof res.NetworkInterfaces[0].Association === "undefined" || typeof res.NetworkInterfaces[0].Association.PublicIp === "undefined") {
          reject("Unable to retrieve IP from ENI details");
          return;
        }

        // resolve the public IP address
        resolve(res.NetworkInterfaces[0].Association.PublicIp);
      });
    }
  });
}

2
投票

我修改了这里的一条评论,并提出了以下 shell 脚本:

#!/bin/bash

# Take the cluster name from the script arguments
CLUSTER_NAME=$1

# Get a list of tasks in the cluster
TASKS=$(aws ecs list-tasks --cluster "$CLUSTER_NAME" --query "taskArns" --output text)

# Loop through each task to get the container instance ARN
for TASK_ARN in $TASKS
do
  # Get a human readable ARN.
  TASK_ID=$(basename $TASK_ARN)
  
  # Get the network interface ID for the task
  NETWORK_INTERFACE_ID=$(aws ecs describe-tasks --cluster $CLUSTER_NAME --tasks $TASK_ARN --query 'tasks[0].attachments[0].details[?name==`networkInterfaceId`].value' --output text)
  
  #Get the public IP of the network interface
  PUBLIC_IP=$(aws ec2 describe-network-interfaces --network-interface-ids $NETWORK_INTERFACE_ID --query 'NetworkInterfaces[0].Association.PublicIp')

  echo "Task: $TASK_ID -- Public IP: $PUBLIC_IP"
done

您可以像

./list-ecs-tasks.sh <your-cluster-arn>
那样调用脚本,它会循环遍历集群中的任务并打印出每个任务的 TaskID 和公共 IP。


0
投票

ECS 在 FARGATE 情况下获取 PublicDnsName 和 PublicIp

步骤1

aws ecs list-tasks --cluster <cluster-name> --service-name <service-name>
CLI: aws ecs list-tasks --cluster inx --service-name inx-service

步骤2

aws ecs describe-tasks --cluster <cluster-name> --tasks <arn-of-task>
CLI: aws ecs describe-tasks --cluster inx --tasks arn:aws:ecs:ap-south-1:123456789012:task/inx/3b2902d17ca64d7e96eb412253fd8cf9

Inside attachments section get networkInterfaceId that should be like eni-0e07d16ba740ecf8d

...
{
 "name": "networkInterfaceId",
 "value": "eni-0e07d16ba740ecf8d"
},
...

步骤3

aws ec2 describe-network-interfaces --network-interface-ids <eni-id>
                    
CLI: aws ec2 describe-network-interfaces --network-interface-ids eni-0e07d16ba740ecf8d

...
{
  "NetworkInterfaces": [
  {
    "Association": {
    "IpOwnerId": "amazon",
    "PublicDnsName": "ec2-11-123-11-111.ap-south-1.compute.amazonaws.com",
    "PublicIp": "11.123.11.111"
  }
...

终于

查看此处的步骤 3 “PublicDnsName”:“ec2-11-123-11-111.ap-south-1.compute.amazonaws.com” 是您的公共 Dns 名称地址,“PublicIp”: “11.123.11.111”是您的公共IP地址


© www.soinside.com 2019 - 2024. All rights reserved.