Nginx прокси для многих контейнеров, работающих на разных узлах CoreOS
Просматривая сеть, я нашел много уроков по проксированию для различных контейнеров Docker, работающих на одном хосте, с использованием Nginx/Confd (или Haproxy, или Vulcand). Однако то, что мне нужно сделать, это другое. После обзора моей инфраструктуры:
- Онлайн-кластер CoreOS с 5 узлами, все работают под управлением etcd
- На каждом узле кластера запускаются различные контейнеры Docker (веб-серверы Nginx, на которых выполняются приложения WordPress) с использованием флота, без указания порта и записи своих ips (Docker ip, взятый с помощью docker inspect) на etcd.
- Если узел выходит из строя, мои услуги автоматически перемещаются на другой доступный узел
Теперь мне нужно иметь, скажем, один прокси-сервер Nginx, который направляет мой трафик в различные контейнеры в зависимости от vhost. Следующий пример:
Nginx (с IP-адресом паба) получает запрос xxx.domain.com
-> node-1
-> container
с автоматически назначенным ip (прослушивание порта 80)
Nginx (с IP-адресом паба) получает запрос yyy.domain.com
-> node-2
-> container
с автоматически назначенным ip (прослушивание порта 80)
Вот мои вопросы:
- Это мой сценарий правильный? Я думаю, что-то не так?
- Мой прокси Nginx должен быть вне кластера CoreOS? Или я должен запустить его на каждом узле CoreOS?
- Как я могу добиться этой конфигурации? Какой лучший способ?
Заранее спасибо!
3 ответа
Чтобы nginx мог "найти" контейнеры, работающие на узлах, вам нужно найти какой-то тип службы. Вы можете записать запись в etcd при запуске контейнера и удалить при выходе, чтобы nginx проверил их.
Для перемещения услуг вокруг, вы могли бы взглянуть на флот для простого планирования.
Вы можете использовать трио nginx, etcd & confd, чтобы сделать это. В блоге под названием " Балансировка нагрузки с помощью CoreOS, confd и nginx " рассказывается о запуске трех контейнеров.
- Вам нужен общий контейнер данных, в котором вы можете хранить динамически сгенерированные конфигурации nginx
- Вам нужен контейнер, запускающий confd, который будет считывать значения из etcd и динамически генерировать для вас конфигурацию nginx (она сохраняется в томе из общего контейнера "data")
- Наконец, вам понадобится nginx, который просто использует этот общий том "data" для своих конфигураций.
Ключом к этому является то, что каждый HTTP-сервер объявляет себя через etcd, а затем confd подхватит изменения и перенастроит nginx на лету. Этот процесс очень близок к тому, что @Julian упомянул в предыдущем ответе:
ExecStart=<do something>
ExecStartPost=/usr/bin/etcdctl set /services/<your_service>/%i/location '{\"host\": "%H", \"port\": <your containers exposed port>}'
ExecStop=/usr/bin/docker stop <your service>
ExecStopPost=/usr/bin/etcdctl rm --recursive /services/<your_service>/%i
Посмотрите шаблоны документов confd для большего количества примеров, но у вас будет что-то вроде этого:
{{range $dir := lsdir "/services/web"}}
upstream {{base $dir}} {
{{$custdir := printf "/services/web/%s/*" $dir}}{{range gets $custdir}}
server {{$data := json .Value}}{{$data.IP}}:80;
{{end}}
}
server {
server_name {{base $dir}}.example.com;
location / {
proxy_pass {{base $dir}};
}
}
{{end}}
Просто отметим, что вам понадобится только один из этих "трио", если только вы не хотите настроить более высокую доступность, в этом случае вам понадобится два или более. Когда вы идете в HA, вам, вероятно, захочется представить им экземпляр ELB.
Я не знаю, правильно ли я вас понял. Но вот как я это сделаю:
Установите балансировщик нагрузки (HAProxy, Nginx, Amazon ELB (если вы используете EC2)) вне кластера, маршрутизирующего каждый трафик внутри него.
Внутри вы можете попробовать Gogeta: https://github.com/arkenio/gogeta
Это обратный прокси-сервер, работающий глобально (на каждом узле) и направляющий трафик на основе записей домена в etcd в определенные контейнеры. Затем вы можете настроить служебные файлы, добавляя и удаляя их присутствие в etcd, который отслеживает gogeta.
ExecStart=<do something>
ExecStartPost=/usr/bin/etcdctl set /services/<your_service>/%i/location '{\"host\": "%H", \"port\": <your containers exposed port>}'
ExecStop=/usr/bin/docker stop <your service>
ExecStopPost=/usr/bin/etcdctl rm --recursive /services/<your_service>/%i
Он работает и запрашивает балансировку нагрузки с помощью стратегии Round Robin. Хотя, кажется, есть проблема, которую я подал https://github.com/arkenio/gogeta/issues/10
Это тебе помогает?