如何获取特定AWS ECS任务的IP地址?

我试图在ECS中构build自己的服务发现版本,因为我希望扩展和缩减的服务不是HTTP服务器,所以不能由ELBpipe理。 此外, ECS还不支持docker的用户定义的networkingfunction,这将是另一种做服务发现的方式。 正如在这个问题讨论中提到的:

目前的服务发现是一个巨大的痛苦需要另一个服务(本身通常是基于群集,自我发现,然后监听其他服务)。 这是一个混乱的解决scheme,更不用说Lambda“解决scheme”,更难以执行和维护。

所以我要去讨厌的Lambda“解决scheme”路线来代替其他select。 我需要构build这个黑客服务发现的主要事情是在我的EC2主机上运行的每个Docker容器的IP地址。

通过SSH进入作为ECS容器实例之一的EC2服务器,我可以运行docker ps来获取每个正在运行的docker容器的容器id。 对于任何给定的containerId,我可以运行docker inspect ${containerId} ,它将返回JSON,包括有关该容器的许多详细信息,特别是绑定到该容器的NetworkSettings.IPAddress (我的发现实现所需的主要内容)。

我正尝试从Lambda内使用AWS SDK来获取此值。 这是我的Lambda函数到目前为止(你也应该能够运行这个 – 没有具体到我的设置这里):

 exports.handler = (event, context, callback) => { var AWS = require('aws-sdk'), ecs = new AWS.ECS({"apiVersion": '2014-11-13'}); ecs.listClusters({}, (err, data) => { data.clusterArns.map((clusterArn) => { ecs.listTasks({ cluster: clusterArn }, (err, data) => { ecs.describeTasks({ cluster: clusterArn, tasks: data.taskArns }, (err, data) => { if (err) console.log(err, err.stack); else console.log(JSON.stringify(data, null, 4)); }) }); }) }) }; 

describeTasks调用的输出是相当无用的。 它没有像docker inspect调用产生的细节那么多,特别是它不包括运行任务的docker容器的IP地址。

我也试图通过describeContainerInstances调用find我需要的数据,但是正如所料,没有返回任何特定于任务的细节。

我愿意尝试直接在EC2主机上运行docker inspect ,如果有任何方法从Lambda进行。 我不确定是否可以通过SDK在容器上运行命令; 可能不会。 因此,我将不得不在ECS容器镜像的特制版本上构build定制服务,这听起来很糟糕。

如何使用AWS SDK获取这些容器IP地址? 或者如何解决ECS服务发现的一般问题有一些比较好的想法?

  • 如何使用Amazon EC2 Container Service扩展一个容器
  • 我们如何增加在Jetty中允许的最大HTTP GET查询长度?
  • 为什么UFW不会阻塞使用docker公开的端口?
  • 在Docker容器中发送电子邮件到运行postfix的主机smtp
  • iptables LOG规则在一个networking命名空间内
  • 操作系统docker集装箱:与虚拟机有什么不同呢?
  • 2 Solutions collect form web for “如何获取特定AWS ECS任务的IP地址?”

    即使您的服务不是HTTP,也可以将Classic Elastic Load Balancer与ECS服务关联。 确保在ELB上创buildTCP监听器(不是HTTP或HTTP / SSL),并指向容器的公开端口。 使用经典ELB与应用程序ELB的缺点是,您将不得不为每个ECS服务单独使用ELB(额外费用)。

    http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-listener-config.html

    事实certificate,我的原始前提(需要知道任务容器自己的内部IP地址用于服务发现)是非常有缺陷的 – 该IP地址只能在单个EC2容器实例中使用。 如果您有多个容器实例(您可能应该有),那么这些任务容器IP基本上是无用的。

    我想出的替代解决scheme是遵循针对运行HTTP / HTTPS的应用程序负载平衡器所build议的模式 – 将端口映射为0作为主机端口,指向我需要使用的docker实例中的端口。 通过这样做,Docker将分配一个随机的主机端口,然后使用AWS开发工具包(特别是ECS模块上提供的“describeTasks”function)来查找。 详情请看这里: http : //docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ECS.html#describeTasks-property

    这是我自己的服务发现机制的基础 – 有很多其他的细节需要完成这个工作。 我使用了调用AWS SDK以及PostgreSQL数据库的Lambda函数,以保持我的主机容器列表(有点像dynamicDNSregistry)。 部分技巧是你需要知道每个容器的IP和端口,但describeTasks只返回端口。 这里是我写的一个方便的NodeJS函数,它使用一个容器名称,并查找群集中find的所有IP地址和端口,以查找该名称的容器:

     var Q = require('q'); /** * @param {String} - cluster - name of the cluster to query, eg "sqlfiddle3" * @param {String} - containerType - name of the container to search for within the cluster * @returns {Promise} - promise resolved with a list of ip/port combinations found for this container name, like so: [ { "connection_meta": "{\"type\":\"ecs\",\"taskArn\":\"arn:aws:ecs:u..\"}", "port": 32769, "ip": "10.0.1.49" } ] * */ exports.getAllHostsForContainerType = (cluster, containerType) => { var AWS = require('aws-sdk'), ecs = new AWS.ECS({"apiVersion": '2014-11-13'}), ec2 = new AWS.EC2({"apiVersion": '2016-11-15'}); return ecs.listTasks({ cluster }).promise() .then((taskList) => ecs.describeTasks({ cluster, tasks: taskList.taskArns }).promise()) .then((taskDetails) => { var containersForName = taskDetails.tasks .filter((taskDetail) => taskDetail.containers.filter( (container) => container.name === containerType ).length > 0 ) .map((taskDetail) => taskDetail.containers.map((container) => { container.containerInstanceArn = taskDetail.containerInstanceArn; return container; }) ) .reduce((final, containers) => final.concat(containers) , []); return containersForName.length ? (ecs.describeContainerInstances({ cluster, containerInstances: containersForName.map( (containerDetails) => containerDetails.containerInstanceArn ) }).promise() .then((containerInstanceList) => { containersForName.forEach((containerDetails) => { containerDetails.containerInstanceDetails = containerInstanceList.containerInstances.filter((instance) => instance.containerInstanceArn === containerDetails.containerInstanceArn )[0]; }); return ec2.describeInstances({ InstanceIds: containerInstanceList.containerInstances.map((instance) => instance.ec2InstanceId ) }).promise(); }) .then((instanceDetails) => { var instanceList = instanceDetails.Reservations.reduce( (final, res) => final.concat(res.Instances), [] ); containersForName.forEach((containerDetails) => { if (containerDetails.containerInstanceDetails) { containerDetails.containerInstanceDetails.ec2Instance = instanceList.filter( (instance) => instance.InstanceId === containerDetails.containerInstanceDetails.ec2InstanceId )[0]; } }); return containersForName; })) : []; }) .then( (containersForName) => containersForName.map( (container) => ({ connection_meta: JSON.stringify({ type: "ecs", taskArn: container.taskArn }), // assumes that this container has exactly one network binding port: container.networkBindings[0].hostPort, ip: container.containerInstanceDetails.ec2Instance.PrivateIpAddress }) ) ); }; 

    请注意,这使用“Q”承诺库 – 您需要在package.json中声明它作为依赖项。

    我使用Lambda函数处理ECS服务发现的其他定制解决scheme可以在这里find: https : //github.com/jakefeasel/sqlfiddle3#setting-up-in-amazon-web-services

    服务器问题集锦,包括 Linux(Ubuntu, Centos,Debian等)和Windows Server服务器.