Docker — масштабирование nginx и php-fpm по отдельности

Docker — масштабирование nginx и php-fpm по отдельности

Я экспериментировал с docker и docker-compose и у меня возник вопрос.

В настоящее время мой docker-compose.yml выглядит так:

app:
    image: myname/php-app
    volumes:
        - /var/www
    environment:
        <SYMFONY_ENVIRONMENT>: dev

web:
    image: myname/nginx
    ports:
        - 80
    links:
        - app
    volumes_from:
        - app

Приложение содержит php-fpm на порту 9000 и мой код приложения. Веб — это nginx с несколькими битами конфигурации.

Это работает так, как я и ожидал, однако для подключения nginx к php-fpm у меня есть эта строка:

fastcgi_pass    app:9000;

Как мне эффективно масштабировать это? Если бы я хотел, например, чтобы был запущен один контейнер nginx и три контейнера приложений, то у меня наверняка будут три экземпляра php-fpm, которые попытаются прослушивать порт 9000.

Как мне разместить каждый экземпляр php-fpm на отдельном порту, но при этом знать, где они находятся в моей конфигурации nginx в любой момент времени?

Может быть, я выбрал неправильный подход?

Спасибо!

решение1

Одним из решений является добавление дополнительных экземпляров php-fpm в ваш файл docker-compose, а затем использование nginx upstream, как упоминалось в других ответах, для балансировки нагрузки между ними. Это сделано в этом примере репозитория docker-compose:https://github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137

upstream php {
    #If there's no directive here, then use round_robin.
    #least_conn;
    server dockernginxphpfpm_php1_1:9000;
    server dockernginxphpfpm_php2_1:9000;
    server dockernginxphpfpm_php3_1:9000;
}

Это не совсем идеальный вариант, поскольку для масштабирования потребуется изменить конфигурацию nginx и docker-compose.yml.

Обратите внимание, что порт 9000 является внутренним для контейнера, а не для вашего фактического хоста, поэтому не имеет значения, есть ли у вас несколько контейнеров php-fpm на порту 9000.

Docker приобрел Tutum этой осенью. У них есть решение, которое объединяет контейнер HAProxy с их API для автоматической настройки конфигурации балансировщика нагрузки для работающих контейнеров, которые он балансирует. Это хорошее решение. Затем nginx указывает на имя хоста, назначенное балансировщику нагрузки. Возможно, Docker будет и дальше интегрировать этот тип решения в свои инструменты после приобретения Tutum. Статья об этом есть здесь:https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-балансировка-нагрузки-веб-сервиса

Tutum в настоящее время является платным сервисом. Rancher — проект с открытым исходным кодом, который предоставляет похожую функцию балансировки нагрузки. У них также есть "rancher-compose.yml", который может определять балансировку нагрузки и масштабирование настройки сервисов в docker-compose.yml. http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer

ОБНОВЛЕНИЕ 2017/03/06: Я использовал проект под названиемблокировкакоторый работает с Docker для автоматического обновления конфигурации nginx и перезапуска его. Также см. @iwaseatenbyagrue'sотвечатькоторый имеет дополнительные подходы.

решение2

Хотя этот пост датируется 2015 годом и я чувствую, что занимаюсь некропостингом (извините, сообщество), я считаю, что сейчас будет полезно добавить:

В настоящее время (и с тех пор, как был упомянут Kubernetes), когда вы работаете с Docker, вы можете использовать Kubernetes или Docker Swarm очень легко для решения этой проблемы. Оба оркестратора будут принимать ваши узлы docker (один узел = один сервер с Docker на нем), и вы можете развернуть на них службы, и они будут управлять вызовами портов для вас, используя оверлейные сети.

Поскольку я более сведущ в Docker Swarm, вот как можно подойти к решению этой проблемы (предполагая, что у вас есть один узел Docker):

Инициализируем рой:

docker swarm init

cd в корень вашего проекта

cd some/project/root

создайте стек Swarm из вашего docker-compose.yml (вместо использования docker-compose):

docker stack deploy -c docker-compose.yml myApp

Это создаст стек сервисов docker swarm с именем "myApp" и будет управлять портами для вас. Это означает: вам нужно добавить только одно определение "port: 9000:9000" в ваш сервис php-fpm в вашем файле docker-compose, а затем вы можете масштабировать сервис php-fpm, скажем, до 3 экземпляров, в то время как swarm автоматически магическим образом распределит нагрузку запросов между тремя экземплярами без необходимости какой-либо дополнительной работы.

решение3

Вы можете использовать апстрим для определения нескольких бэкэндов, как описано здесь:

https://stackoverflow.com/questions/5467921/how-to-use-fastcgi-next-upstream-in-nginx

Вам также захочется обновлять конфигурацию всякий раз, когда новые бэкэнды умирают/вступают в эксплуатацию, например:

https://github.com/kelseyhightower/confd

решение4

Другой подход может заключаться в рассмотрении чего-то вродеконсул-шаблон.

И, конечно, в какой-то момент,Кубернетесвозможно, необходимо упомянуть.

Однако вы можете рассмотреть подход, немного более приближенный к «кускам веревки и клейкой ленты», посмотрев, что может сделать для вас использование событий Docker (запустите docker events --since 0для быстрого примера).

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

Однако вернемся к исходной предпосылке: если ваши контейнеры php-fpm запущены в собственной сети (т. е. не используют сеть другого контейнера, например, nginx), то вы можете прослушивать порт 9000 столько контейнеров, сколько захотите — поскольку у них есть IP-адреса для каждого контейнера, проблем с «конфликтом» портов не возникнет.

То, как вы это масштабируете, скорее всего, будет зависеть от вашей конечной цели/варианта использования, но вы можете рассмотреть возможность размещения HAproxy между узлами nginx и php-fpm. Это может позволить вам просто назначить диапазон (и, возможно, создать docker network) для ваших серверов php-fpm (например, 172.18.0.0/24) и настроить HAproxy на попытку использования любого IP-адреса в этом диапазоне в качестве бэкэнда. Поскольку HAproxy имеет проверки работоспособности, он может быстро определить, какие адреса активны, и использовать их.

Видетьhttps://stackoverflow.com/questions/1358198/nginx-удаление-серверов-вышестоящего-потока-из-пуладля обсуждения того, как nginx и haproxy справляются с апстримами.

Если вы не использовали для этого выделенную сеть Docker, вымощьнеобходимо выполнить ручное управление IP-адресами для узлов php-fpm.

Связанный контент