Amazon ECS (Docker): enlace de contenedor a una dirección IP específica

24

Estoy jugando con Amazon ECS (un reempaquetado de Docker) y descubro que hay una capacidad de Docker que ECS no parece proporcionar. Es decir, me gustaría tener varios contenedores ejecutándose en una instancia, y que las solicitudes que ingresen a la dirección IP 1 se asignen al contenedor 1, y las solicitudes que lleguen a la dirección IP 2 se asignen al contenedor 2, etc.

En Docker, la vinculación de un contenedor a una dirección IP específica se realiza a través de:

docker run -p myHostIPAddr:80:8080 imageName command

Sin embargo, en Amazon ECS, no parece haber una manera de hacer esto.

He configurado una instancia EC2 con múltiples direcciones IP elásticas. Al configurar un contenedor como parte de una definición de tarea, es posible asignar puertos de host a puertos de contenedor. Sin embargo, a diferencia de Docker, ECS no proporciona una forma de especificar la dirección IP del host como parte de la asignación.

Un giro adicional es que me gustaría que las solicitudes salientes del contenedor N tengan la dirección IP externa del contenedor N.

¿Hay alguna manera de hacer todo lo anterior?

He revisado la documentación de AWS CLI, así como el AWS SDK para Java. Puedo ver que la CLI puede devolver una matriz networkBindings que contiene elementos como este:

{
  "bindIP": "0.0.0.0", 
  "containerPort": 8021, 
  "hostPort": 8021
},

y el SDK de Java tiene una clase llamada NetworkBinding que representa la misma información. Sin embargo, esta información parece ser solo de salida, en respuesta a una solicitud. No puedo encontrar una manera de proporcionar esta información vinculante a ECS.

La razón por la que quiero hacer esto es porque quiero configurar máquinas virtuales completamente diferentes para diferentes circunscripciones, utilizando diferentes contenedores potencialmente en la misma instancia de EC2. Cada VM tendría su propio servidor web (incluidos certificados SSL distintos), así como su propio servicio FTP y SSH.

Gracias.

Mark R
fuente
Tengo el mismo problema con nuestro flujo de trabajo. aws ecs describe-container-instancesno parece ayudar Parece que realmente quieren empujarlo a usar un ELB, que para nuestro caso es un poco tonto.
four43
Parece que hay una forma de hacerlo ahora (cuarto trimestre de 2017): stackoverflow.com/a/46577872/6309
VonC

Respuestas:

4

Una opción: crear un ELB para cada cliente y luego asignar ciertos contenedores a cada ELB.

[1] http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html

Adam Keck
fuente
13
Ca-ching! 18 dólares al mes por un ELB. Ahora, ¿quién quiere microservicios con ECS? aws.amazon.com/elasticloadbalancing/pricing
Nudos
1
@ Nudos tuvimos el mismo problema. Luego nos cambiamos a Lambda + API Gateway y nuestro costo bajó a 10 centavos.
grepe
Ahora puede usar un solo ALB (en lugar de los ELB clásicos) para todos sus servicios en lugar de 1 por servicio. Deben estar en diferentes nombres de host o diferentes rutas en un nombre de host.
AJ Brown
4

Aquí hay una forma real y lógica de hacerlo. Suena demasiado complicado, pero puedes implementarlo en cuestión de minutos y funciona. En realidad lo estoy implementando mientras hablamos.

Crea una tarea para cada contenedor y crea un servicio para cada tarea, junto con un grupo objetivo para cada servicio. Y luego creas solo 1 Elastic Load Balancer.

Los equilibradores de carga elásticos basados ​​en aplicaciones pueden enrutar solicitudes basadas en la ruta solicitada. Usando los grupos objetivo, puede enrutar las solicitudes que llegan elb-domain.com/1al contenedor 1, elb-domain.com/2al contenedor 2, etc.

Ahora estás a solo un paso. Crea un servidor proxy inverso.

En mi caso, estamos usando nginx, por lo que puede crear un servidor nginx con tantas direcciones IP como desee, y usando la capacidad de proxy inverso de nginx puede enrutar sus direcciones IP a las rutas de su ELB, que en consecuencia las enrutan al contenedor correcto (s) Aquí hay un ejemplo si está utilizando dominios.

server {
    server_name domain1.com;
    listen 80;
    access_log /var/log/nginx/access.log vhost;
    location / {
        proxy_pass http://elb-domain.com/1;
    }
}

Por supuesto, si realmente está escuchando IP, puede omitir la server_namelínea y simplemente escuchar las interfaces correspondientes.

En realidad, esto es mejor que asignar una IP estática por contenedor porque le permite tener clústeres de máquinas acoplables donde las solicitudes se equilibran sobre ese clúster para cada una de sus "IP". La recreación de una máquina no afecta la IP estática y no tiene que rehacer mucha configuración.

Aunque esto no responde completamente a su pregunta porque no le permitirá usar FTP y SSH, diría que nunca debe usar Docker para hacer eso, sino que debe usar servidores en la nube. Si está utilizando Docker, en lugar de actualizar el servidor mediante FTP o SSH, debe actualizar el contenedor. Sin embargo, para HTTP y HTTPS, este método funciona perfectamente.

TheNavigat
fuente
1

No puede acceder al contenedor en sí, pero puede hacer una instancia EC2 dedicada a un contenedor específico. Luego, cuando necesite acceder a ese servicio, puede hacer referencia al host EC2 que ejecuta el contenedor.

  • Cree un clúster dedicado para sus servicios con este requisito
  • Cree una instancia EC2 optimizada para AMI utilizando su tipo de instancia preferido
    • Asegúrese de asignar esa instancia al clúster anterior utilizando la opción UserData como se describe en esa guía.
  • Cree una definición de tarea con NetworkMode configurado en "bridge" (igual que su escritorio)
  • Cree una definición de servicio con:
    • LaunchType establecido en EC2
    • Clúster establecido en el clúster que creó anteriormente
    • Definición de tarea establecida en la definición de tarea que creó anteriormente
  • Asigne cualquier grupo de seguridad a la instancia EC2 como lo haría de otra manera.

Aunque todavía está hablando directamente con una instancia EC2, puede controlar la IP del contenedor (indirectamente) como lo haría con la instancia EC2. Esto le ahorra el dolor de cabeza de ejecutar los servicios en el "bare metal", lo que le permite administrar y configurar más fácilmente el servicio y su configuración.

Patrick Twohig
fuente