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, а также AWS SDK для Java. Я вижу, что CLI может возвращать массив networkBindings, содержащий такие элементы:
{
"bindIP": "0.0.0.0",
"containerPort": 8021,
"hostPort": 8021
},
и Java SDK имеет класс с именем NetworkBinding, который представляет ту же информацию. Однако эта информация представляется только для вывода в ответ на запрос. Я не могу найти способ предоставить эту обязательную информацию в ECS.
Причина, по которой я хочу это сделать, заключается в том, что я хочу настроить совершенно разные виртуальные машины для разных групп пользователей, используя разные контейнеры, потенциально на одном и том же экземпляре EC2. Каждая виртуальная машина будет иметь свой собственный веб-сервер (включая отдельные сертификаты SSL), а также собственный сервис FTP и SSH.
Благодарю.
3 ответа
Вот фактический, логичный способ сделать это. Это звучит слишком сложно, но вы можете реализовать это в считанные минуты, и это работает. Я на самом деле реализую это, как мы говорим.
Вы создаете задачу для каждого контейнера и создаете службу для каждой задачи вместе с целевой группой для каждой службы. И тогда вы создаете только 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 этот метод работает отлично.
Один из вариантов: создать ELB для каждого клиента, а затем назначить определенные контейнеры для каждого ELB.
[1] http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html
Вы не можете подключиться к самому контейнеру, но вы можете создать экземпляр EC2, выделенный для конкретного контейнера. Затем, где вам нужен доступ к этой службе, вы можете сослаться на хост EC2, на котором запущен контейнер.
- Создайте выделенный кластер для ваших услуг с этим требованием
- Создайте оптимизированный для AMI экземпляр EC2, используя предпочитаемый тип экземпляра
- Обязательно назначьте этот экземпляр вышеупомянутому кластеру, используя опцию UserData, как описано в этом руководстве.
- Создайте TaskDefinition с NetworkMode, установленным в "bridge" (так же, как ваш рабочий стол)
- Создайте определение сервиса с:
- LaunchType установлен в EC2
- Кластер установлен на кластер, который вы создали выше
- Определение задачи соответствует определению задачи, которое вы создали выше
- Присвойте любые группы безопасности экземпляру EC2, как в противном случае.
Хотя вы все еще говорите напрямую с экземпляром EC2, вы можете управлять IP-адресом контейнера (косвенно) так же, как и экземпляром EC2. Это избавляет вас от головной боли при работе служб на "голом железе", позволяя упростить управление и настройку службы и ее конфигурации.