我有一个运行服务的集群,并且还可以从命令行启动 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
一旦我意识到描述任务为我提供了 ENI id 以及私有 IP,我就能够通过以下方式获取公共 IP:
$ aws ec2 describe-network-interfaces --network-interface-ids eni-xxxxxxxx
您可以使用这样的脚本。
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"
这是特定于我的用例的,但也许对其他人有用(旨在在运行 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);
});
}
});
}
我修改了这里的一条评论,并提出了以下 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。
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地址
describe-addresses
文档在这里:https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-addresses.html