AWS:单个 EC2 实例上的多个容器之间的通信
动机:
有时您的服务不是单个应用程序,它很容易 dockerize 和部署。但是,如果您的服务有多个 docker 容器,其中一个使用另一个容器的数据怎么办?为此,您需要在容器之间创建某种通信通道。当您为每个应用程序创建一个 EC2 实例时,可以通过策略轻松实现,但这会增加您的成本,显然这样的策略并不划算。然后,您想充分利用 EC2 实例并在单个 EC2 实例上运行两个 dockerized 应用程序。
这是有关如何创建 AWS ECS 任务定义的分步指南,该定义由两个带有应用程序的 docker 容器组成,并且能够在单个 EC2 实例上在它们之间进行通信。
[
](https://res.cloudinary.com/practicaldev/image/fetch/s--rscttXKb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// /dev-to-uploads.s3.amazonaws.com/uploads/articles/lww72taa5mrs684dp72y.png)
我们将使用ECS 服务来管理 EC2 实例上的 docker 容器。
创建ECS集群&ECS服务
让我们从官方 AWS-ECS示例的基本堆栈开始,稍作修改。
declare const vpc: ec2.Vpc;
// Create an ECS cluster
const cluster = new ecs.Cluster(this, 'Cluster', {
vpc,
});
// Add capacity to it
cluster.addCapacity('DefaultAutoScalingGroupCapacity', {
instanceType: new ec2.InstanceType("t2.micro"),
desiredCapacity: 1,
});
// Place for adding task definition,
// docker container options,
// and all other options from this article below
// Instantiate an Amazon ECS Service
const ecsService = new ecs.Ec2Service(this, 'Service', {
cluster,
taskDefinition,
});
进入全屏模式 退出全屏模式
添加任务定义
这里主要是用**Bridge Network Mode**创建任务定义。这种模式使得连接到同一个 Docker 内部网络或 Bridge 的 docker 容器之间的通信成为可能。
const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef', {
networkMode: Network.BRIDGE,
});
进入全屏模式 退出全屏模式
添加ProducerApp容器
现在让我们添加生产者容器。生产者应用程序将是一个简单的 HTTP 服务器,端口为 8080,具有/data端点,消费者可以在其中获取数据。
const producerContainer = taskDefinition.addContainer('ProducerContainer', {
image: ecs.ContainerImage.fromRegistry('producer-image'),
memoryLimitMiB: 256,
});
producerContainer.addPortMappings({
containerPort: 80,
hostPort: 8080,
protocol: ecs.Protocol.TCP,
});
进入全屏模式 退出全屏模式
添加消费者容器
另外让我们添加消费者容器。消费者应用程序将是端口 8081 上的 HTTP 服务器,能够像 HTTP 客户端一样工作,每分钟从生产者应用程序检索数据。
但是消费者应用程序如何知道如何联系生产者应用程序呢? Consumer App 应该 ping 哪个端点?我们稍后会澄清这一点。
const consumerContainer = taskDefinition.addContainer('ConsumerContainer', {
image: ecs.ContainerImage.fromRegistry('consumer-image'),
memoryLimitMiB: 256,
});
consumerContainer.addPortMappings({
containerPort: 81,
hostPort: 8081,
protocol: ecs.Protocol.TCP,
});
进入全屏模式 退出全屏模式
添加容器间通信
现在是最后一个技巧:我们需要在 ProducerContainer 和 ConsumerContainer 之间创建一种通信方式。我们将使用addLink方法。这种方法的好处是,我们不需要担心映射端口或其他任何事情。在内部,此方法向 /etc/hosts 添加了一个别名,它允许容器仅使用别名相互通信,并且您还记得这两个容器都在同一个 Bridge Network 中,因此它使容器可以访问。
consumerContainer.addLink(producerContainer)
进入全屏模式 退出全屏模式
从CDK的角度来看就是这样。但是我们仍然缺少生产者的端点,消费者应用程序应该从那里检索数据。
深入寻找Producer端点
成功部署 CDK 后,我们来看看 Producer 端点的样子。
通过 SSH 或会话管理器连接到 EC2 实例。
~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6a008b35bb2 producerContainer "/usr/src/app/produc…" 10 min ago Up 10 min producerContainer
a85bbfa3fae3 consumerContainer "/usr/src/app/consum…" 10 min ago Up 10 min consumerContainer
进入全屏模式 退出全屏模式
首先,我们可以清楚地看到两个 docker 容器都已启动并正在运行。让我们深入了解 consumerContainer。
~$ sudo docker exec -it a85bbfa3fae3 /bin/sh
~$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
172.17.0.2 producerContainer d6a008b35bb2
172.17.0.3 a85bbfa3fae3
进入全屏模式 退出全屏模式
如您所见,现在我们知道了 producerContainer 的别名:
172.17.0.2 producerContainer d6a008b35bb2.
让我们从中获取一些数据!
~$ curl producerContainer:8080/data
~$ {data: "Very important data"}
进入全屏模式 退出全屏模式
它就像一个魅力!现在您只需添加producerContainer:8080/data作为 Consumer Application 的 HTTP 客户端的目标端点,并从 Producer Application 中检索数据!
另外,如果你更频繁地获取数据,或者你需要容器之间的双向通信,可以考虑在容器之间建立WebSocket连接,以更方便、更快捷的方式生产/消费数据!
结论:
这个技巧不仅可以帮助您更多地了解 docker 和 AWS,还可以利用更多的 EC2 实例并为您节省一些钱!希望你喜欢它!
更多推荐
所有评论(0)