Amazon ECS (Docker): привязка контейнера к определенному IP-адресу


24

Я играю с Amazon ECS (переупаковка Docker) и обнаружил, что есть одна возможность Docker, которую ECS, похоже, не предоставляет. А именно, я хотел бы, чтобы в экземпляре работало несколько контейнеров, и чтобы запросы, поступающие на IP-адрес 1, отображались в контейнер 1, а запросы, поступающие на IP-адрес 2, отображались в контейнер 2 и т. Д.

В Docker привязка контейнера к определенному IP-адресу осуществляется через:

docker run -p myHostIPAddr:80:8080 imageName command

Однако в Amazon ECS, похоже, нет способа сделать это.

Я настроил экземпляр EC2 с несколькими эластичными IP-адресами. При настройке контейнера как части определения задачи можно сопоставить порты хоста с портами контейнера. Однако, в отличие от Docker, ECS не предоставляет способ указать IP-адрес хоста как часть сопоставления.

Дополнительный поворот заключается в том, что я хотел бы, чтобы исходящие запросы из контейнера N имели внешний IP-адрес контейнера N.

Есть ли способ сделать все вышеперечисленное?

Я просмотрел документацию по интерфейсу командной строки AWS, а также AWS SDK для Java. Я вижу, что CLI может возвращать массив networkBindings, содержащий такие элементы:

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

и Java SDK имеет класс с именем NetworkBinding, который представляет ту же информацию. Однако эта информация представляется только для вывода в ответ на запрос. Я не могу найти способ предоставить эту обязательную информацию в ECS.

Причина, по которой я хочу это сделать, заключается в том, что я хочу настроить совершенно разные виртуальные машины для разных групп пользователей, используя разные контейнеры, потенциально на одном и том же экземпляре EC2. Каждая виртуальная машина будет иметь свой собственный веб-сервер (включая отдельные сертификаты SSL), а также собственный сервис FTP и SSH.

Спасибо.


У меня та же проблема с нашим рабочим процессом. aws ecs describe-container-instancesпохоже не помогает. Кажется, они действительно хотят подтолкнуть вас к использованию ELB, что в нашем случае довольно глупо.
4:43

Похоже, что есть один способ сделать это сейчас (4 квартал 2017 года): stackoverflow.com/a/46577872/6309
VonC

Ответы:


4

Один из вариантов: создать ELB для каждого клиента, а затем назначить определенные контейнеры для каждого ELB.

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


13
Ca-цин! 18 баксов в месяц за один ELB. Теперь, кому нужны микросервисы с ECS? aws.amazon.com/elasticloadbalancing/pricing
Узлы

1
@ У нас была такая же проблема. Затем мы переключились на Lambda + API Gateway, и наша стоимость снизилась до 10 центов.
grepe

Теперь вы можете использовать один ALB (вместо классических ELB) для всех ваших услуг, а не 1 для каждой услуги. Они должны быть либо на разных именах хостов, либо на разных путях в имени хоста.
AJ Браун

4

Вот фактический, логичный способ сделать это. Это звучит слишком сложно, но вы можете реализовать это в считанные минуты, и это работает. Я на самом деле реализую это, как мы говорим.

Вы создаете задачу для каждого контейнера и создаете службу для каждой задачи вместе с целевой группой для каждой службы. И тогда вы создаете только 1 Elastic Load Balancer.

Балансировщики эластичных нагрузок на основе приложений могут направлять запросы на основе запрошенного пути. Используя целевые группы, вы можете направлять запросы, поступающие elb-domain.com/1в контейнер 1, elb-domain.com/2в контейнер 2 и т. Д.

Теперь вы в одном шаге от вас. Создайте обратный прокси-сервер.

В моем случае мы используем nginx, поэтому вы можете создать сервер nginx с таким количеством IP-адресов, которое вы хотите, и с помощью функции обратного проксирования nginx вы можете направить ваши IP-адреса на пути вашего ELB, которые соответственно направят их в правильный контейнер (с). Вот пример, если вы используете домены.

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

Конечно, если вы на самом деле слушаете IP-адреса, вы можете пропустить server_nameстроку и просто прослушать соответствующие интерфейсы.

На самом деле это лучше, чем назначать статический IP-адрес для контейнера, поскольку он позволяет вам иметь кластеры докеров, где запросы сбалансированы по этому кластеру для каждого из ваших «IP-адресов». Воссоздание машины не влияет на статический IP, и вам не нужно много переделывать конфигурацию.

Хотя это не полностью отвечает на ваш вопрос, потому что не позволяет вам использовать FTP и SSH, я бы сказал, что вам никогда не следует использовать Docker, а вместо этого вы должны использовать облачные серверы. Если вы используете Docker, то вместо обновления сервера с использованием FTP или SSH вам следует обновить сам контейнер. Однако для HTTP и HTTPS этот метод работает отлично.


1

Вы не можете подключиться к самому контейнеру, но вы можете создать экземпляр EC2, выделенный для конкретного контейнера. Затем, где вам нужен доступ к этой службе, вы можете сослаться на хост EC2, на котором запущен контейнер.

  • Создайте выделенный кластер для ваших услуг с этим требованием
  • Создайте оптимизированный для AMI экземпляр EC2, используя предпочитаемый тип экземпляра
    • Обязательно назначьте этот экземпляр вышеупомянутому кластеру, используя опцию UserData, как описано в этом руководстве.
  • Создайте TaskDefinition с NetworkMode, установленным в «bridge» (так же, как ваш рабочий стол)
  • Создайте определение сервиса с:
    • LaunchType установлен в EC2
    • Кластер установлен на кластер, который вы создали выше
    • Определение задачи установлено на определение задачи, которое вы создали выше
  • Присвойте любые группы безопасности экземпляру EC2, как в противном случае.

Хотя вы все еще говорите напрямую с экземпляром EC2, вы можете управлять IP-адресом контейнера (косвенно) так же, как и экземпляром EC2. Это избавляет вас от головной боли при работе служб на «голом железе», позволяя упростить управление и настройку службы и ее конфигурации.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.