ECS on EC2 bidirectional communication between two containers in the same task - amazon-web-services

I'm trying to configure ECS task on EC2 instance. Network mode in task definition is Bridge
My task has two containers inside, that should communicate with each other. e.g. ContainerA makes requests to ContainerB and ContainerB makes requests to ContainerA.
Everything works well when I use docker-compose, containers can communicate by their names. But when I deploy on ECS those containers don't see each other. Partly I can fix this problem using Links in the task definition, however, it works only in one direction, I mean if set links for both containers I receive such error message during creation task definition:
Unable to create a new revision of Task Definition web-app:12
Container links should not have a cycle
It would be great to hear any thoughts, what did I miss and if it's actually possible. Honestly, I thought that containers inside one task should communicate automatically by container names, especially when they are under the same Bridge network.
I know that there is a feature Service Discovery that allow communication between to services by names, but still, I would prefer to have one service and task with two containers inside.
Thank you for any help.
ContainerA NETWORK SETTINGS

If both containers are defined in the same task definition they are available via localhost:
For instance, if ContainerA is listening on port 8081 and ContainerB is listening on port 8082, they can simply reach each other by:
localhost:8081
localhost:8082
Side note: same concept as in Kubernetes pod with two containers - they are accessible via localhost
EDIT: that's relevant for awsvpc network mode as you can see in the documentation:
containers that belong to the same task can communicate over the
localhost interface

docker-compose uses not a bridge, but user-defined network by default. That's by addressing by service name works:
By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.
https://docs.docker.com/compose/networking/
ECS EC2 uses links by default, which are deprecated by Docker and not cannot have cycles, as you've found out.
Unfortunately user-defined networks are not supported by AWS despite a long-standing issue: https://github.com/aws/containers-roadmap/issues/184
That's what I've figured out so far. I guess the only option left is to use the awsvpc network mode which allows containers to communicate via localhost (which I find rather awkward):
This means that all containers in a task are addressable by the IP addresses of the elastic network interface, and they can communicate with each other over the localhost interface.
https://aws.amazon.com/blogs/compute/under-the-hood-task-networking-for-amazon-ecs/

Related

fargate hostname set awsvpc

I'm pushing out a Aws Fagate task with 2 containers.
One of the containers is Nginx, which is going to route the traffic to the other container running in the task.
In Docker Compose, the containers seem to route to each other using the Docker dns service.
This does not work in Fargate.
I'm sure someone else has figured out how to communicate between containers in Fargate. I see there is a Network Mode, but Fargate seeems to default to awsvpc, so the settings for the container do net allow me to set the hostname.
Does anyone have some ideas how to make it possible for two containers in the same task to be able to refer to each other by hostname ?
Since you are using awsvpc networking mode, containes which are part of same task, as in your case, can simply use localhost to communicate with each other:
containers that belong to the same task can communicate over the localhost interface.
So you could modify your application/containers to use localhost for between-container communication as part of the same task.

Two ECS tasks connectivity in one EC2 Host

I have 2 ECS Services running with EC2 launch type and bridge networking mode. each service is having 1 task and both tasks are running on same EC2 container host.
on the Same ECS host, API container in 1st task is trying to communicate DB container in 2nd task by host name and port number( ex: http://abc-def:5000). what are the ways to achieve this ?
Your options are:
Put everything in a single task definition. Then you can use the link attribute to enable container A to communicate with container B like so B:port. Notice that link does not support circular relations meaning if A can talk with B, B will not be able to do that as well.
Switch to network mode host. This way you can communicate with localhost.
Proper service discovery with a tool like Consul or AWS ECS Service Discovery. I have no experience with the latter. See here.
Put your tasks behind ALB and use this load balancer to communicate between tasks.

AWS : VPC Networking mode

I have an ecs architecture, which has an application running as a container and a nginx side car container. So each task has 2 containers(nginx+app). These two containers are linked through bridge network mode. We currently observe increase in response time. We suspected it may be because of docker bridge network.So, we are trying to change to aws vpc mode networking. But when we tried to update to aws vpc network mode, it gave us an error 'Links are not supported when networkMode=awsvpc.'. So how to use aws vpc networking for these kind of side car architectures?
Linking is not supported in AWSVPC network mode.you need to use service discovery.
links
Type: string array
Required: no
The link parameter allows containers to communicate with each other
without the need for port mappings. Only supported if the network mode
of a task definition is set to bridge.
Note
This parameter is not supported for Windows containers or tasks using
the awsvpc network mode.
task_definition_parameters

Communication Between Microservices in Aws Ecs

I'm having troubles with the communication between microservices. I have many spring boot applications, and many requests HTTP and AMQP (RabbitMQ) between them. Locally (in dev) I use Eureka (Netflix Oss) without Docker Images.
The question is: in the Amazon ECS Infraestructure how i can work with the same behavior? Which is the common pratice for the communication between microservices using Docker? I can still use Eureka for Service Discovery? Besides that, how this comunication will works between container instances?
I'd suggest reading up on ECS Service Load Balancing, in particular two points:
Your ECS service configuration may say that you let ECS or the EC2 instance essentially pick what port number the service runs on externally. (ie for Spring Boot applications inside the Docker container your application thinks it's running on port 8080, but in reality to anything outside the Docker container it may be running on port 1234
2 ECS clusters will check the health endpoint you defined in the load balancer, and kill / respawn instances of your service that have died
A load balancer gives you different ways to specify which application in the cluster you are talking to. This can be route based or DNS name based (and maybe some others). Thus http://myservice.example.com/api could point to a different ECS service than http://myservice.exaple.com/app... or http://app.myservice.example.com vs http://api.myservice.example.com.
You can configure ECS without a load balancer, I'm unsure how well that will work in this situation.
Now, you're talking service discovery. You can still use Eureka for service discovery, having Spring Boot take care of that. You may need to be clever about how you tell Eureka where your service lives (as the hostname inside the Docker container may be useless, and the port number inside the container totally will be too.) You may need to do something clever here to correctly derive that number, like introspecting using AWS APIs. I think this SO answer describes it correctly, or at least close enough to get started.
Additionally apparently ECS has service discovery built in now. This is either new since I last used ECS, or we didn't use it because we had other solutions. If you aren't completely tied to Eureka for other reasons.
Thanks for you reply. For now I'm using Eureka because I'm using Feign too for comunication between microservices.
My case is this: I have microservices (Example A,B,C). A communicates with B and C by way of Feign (Rest).
Microservices Example
Example of Code on Microservice A:
#FeignClient("b-service")
public interface BFeign {
}
#FeignClient("c-service")
public interface CFeign {
}
Using ECS and ALB it's possible still using Feign? If yes or not, how you suggest I do this?

Connect ECS instances from different task definitions

We are testing the ECS infrastructure to run an application that requires a backend service (a MySQL) as well as a few web servers. Since we'd like to restart and redeploy the front end web servers independently from the elasticsearch service, we were considering defining them as separate task definitions, as suggested here.
However, since the container names are autogenerated by ECS, we have no means of referring to the container running the MySQL instance, and links can only be defined between containers running on the same task.
How can I make a reference to a container from a different task?
PS: I'd like to keep everything running within ECS, and not rely on RDS, at least for now.
What you're asking about is generally called service discovery, and there are a number of different alternatives. ECS has integration with ELB through the service feature, where tasks will be automatically registered in the ELB and deregistered in the ELB appropriately. If you want to avoid ELB, another pattern might be an ambassador container (there's a sample called the ecs-task-kite that uses the ECS API) or you might be interested in an overlay network (Weave has a fairly detailed getting started guide for their solution).