Назад | Перейти на главную страницу

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

Я играю с 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 CLI, а также AWS SDK для Java. Я вижу, что CLI может возвращать массив networkBindings, содержащий такие элементы:

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

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

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

Спасибо.

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

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

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

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

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

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 line и просто слушайте соответствующие интерфейсы.

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

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

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

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

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

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

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