Thank you for reading this post, don't forget to subscribe!
Прокси-сервер Docker Flow обеспечивает простой способ перенастройки прокси-сервера каждый раз при развертывании новой службы или при масштабировании службы. Он не пытается "изобретать колесо", а использовать существующих лидеров и объединить их с помощью простой в использовании интеграции. Он использует HAProxy в качестве прокси-сервера и добавляет пользовательскую логику, которая позволяет реконфигурировать по требованию.
Принцип действия:
Пользователь или служба отправляет запрос на наш DNS. Запрос обычно - HTTP на порту 80
или HTTPS на порту 443
.
DNS разрешает домен на один из серверов внутри кластера. Нам не нужно регистрировать все узлы. Достаточно нескольких (более одного в случае сбоя).
Сетка маршрутизации Докера проверяет, какие контейнеры запущены на данном порту и повторно отправляет запрос одному из экземпляров прокси. Он использует циклическое распределение нагрузки, чтобы все экземпляры распределяли нагрузку (более или менее) в равной степени.
Прокси-сервер проверяет путь запроса (например /demo/hello
) и отправляет ему конечную точку с тем же именем, что и служба назначения (например go-demo
). Обратите внимание, что для этого, как прокси-сервер, так и служба назначения должны принадлежать к одной сети (например proxy
). Прокси-сервер меняет порт на порт службы назначения (например, 8080
).
Прокси-сеть выполняет балансировку нагрузки между всеми экземплярами службы назначения и повторно отправляет запрос одному из них.
Swarm Listener работает внутри одного из узлов диспетчера Swarm и запрашивает Docker API в поиске вновь созданных сервисов. Как только он находит новый сервис, он ищет его метки. Если служба содержит com.df.notify
(она может содержать любое значение), остальные метки с ключами, начинающимися с com.df.
, извлекаются. Все эти метки используются для формирования параметров запроса. Эти параметры добавляются к адресу, указанному в качестве DF_NOTIFY_CREATE_SERVICE_URL
переменной среды, определенной в swarm-listener
службе. Наконец, запрос отправлен. В этом конкретном случае был сделан запрос на перенастройку прокси-сервера со службой go-demo
(имя службы), используя /demo
в качестве пути и работающую на порту 8080
https://proxy.dockerflow.com/swarm-mode-auto/
имеется несколько серверов:
192.168.1.180 swarm_master1_180
192.168.1.181 swarm_master2_181
192.168.1.182 swarm_master3_182
192.168.1.183 swarm_node1_183
192.168.1.184 swarm_node2_184
192.168.1.185 swarm_node3_185
настроен swarm кластер(ниже показаны только мастера):
[codesyntax lang="php" blockstate="collapsed"]
1 2 3 4 5 6 |
[root@swarm_master1_180 ~]# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION l6dlgynhjw8b7p30tczz4tysg * swarm_master1_180 Ready Active Leader 19.03.1 ejuadkwudusjipvoehn3pma88 swarm_master2_181 Ready Active Reachable 19.03.1 ws4gvcxyuvujpxwiyx5k2t7b6 swarm_master3_182 Ready Active Reachable 19.03.1 |
[/codesyntax]
Docker Flow: Proxy
. Его целью является мониторинг сервисов Swarm и отправка запросов на прокси-сервер всякий раз, когда сервис создается или уничтожается.
Создание сертификатов для docker-flow proxy
чтобы добавить сертификаты(самоподписанные), создадим директорию:
mkdir -p /certs
Сертификат будет привязан к *.test.ru
домену, что удобно для демонстрационных целей. Это позволит нам использовать тот же сертификат, даже если IP-адреса нашего сервера могут измениться при локальном тестировании. С test.ru не нужно заново создавать самозаверяющий сертификат, когда, например, наш докер меняет IP.
Чтобы создать сертификат, сначала нам нужен ключ.
openssl genrsa -out /certs/test.ru.key 1024
С помощью вновь созданного ключа мы можем продолжить и создать запрос на подпись сертификата (CSR). Команда выглядит следующим образом.
openssl req -new -key /certs/test.ru.key -out /certs/test.ru.csr
После необходимо указать корректные данные. Важно, чтобы когда появилось ""Common Name (e.g. server FQDN or YOUR name)" " «Общее имя
(например, полное доменное имя сервера или ВАШЕ имя)», вы отвечали на него *.test.ru
[root@swarm_master1_180 ~]# openssl req -new -key /certs/test.ru.key -out /certs/test.ru.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:kg
State or Province Name (full name) []:bishkek
Locality Name (eg, city) [Default City]:bishkek
Organization Name (eg, company) [Default Company Ltd]:dom
Organizational Unit Name (eg, section) []:dom
Common Name (eg, your name or your server's hostname) []:*.test.ru
Email Address []:admin@test.ru
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Наконец, с помощью ключа и CSR мы можем создать сертификат. Команда выглядит следующим образом.
openssl x509 -req -days 365 -in /certs/test.ru.csr -signkey /certs/test.ru.key -out /certs/test.ru.crt
В результате, у нас есть crt
, csr
и key
файлы в /cert каталоге
[root@swarm_master1_180 ~]# openssl x509 -req -days 365 -in /certs/test.ru.csr -signkey /certs/test.ru.key -out /certs/test.ru.crt
Signature ok
subject=/C=kg/ST=bishkek/L=bishkek/O=dom/OU=dom/CN=*.test.ru/emailAddress=admin@test.ru
Getting Private key
Далее, после того, как сертификаты созданы, нам нужно создать pem
файл. Файл pem - это, по сути, просто
сертификат, ключ и, необязательно, центры сертификации, объединенные в один файл. В нашем примере мы просто
объединяем файлы сертификатов и ключей вместе (в указанном порядке), чтобы создать test.ru.pem
файл
cat /certs/test.ru.crt /certs/test.ru.key | tee /certs/test.ru.pem
[root@swarm_master1_180 ~]# cat /certs/test.ru.crt /certs/test.ru.key | tee /certs/test.ru.pem
Добавление сертификатов как секретов Docker
Хранение сертификатов внутри образов Docker или подключенных томов довольно небезопасно. Чтобы усилить безопасность, мы можем добавить сертификат в качестве секрета Docker.
docker secret create cert-test.ru.pem /certs/test.ru.pem
1 2 3 4 5 |
[root@swarm_master1_180 ~]# <strong>docker secret create cert-test.ru.pem /certs/test.ru.pem</strong> 4rh7oapykk83zbks90qajt4jn [root@swarm_master1_180 ~]# <strong>docker secret ls</strong> ID NAME DRIVER CREATED UPDATED 4rh7oapykk83zbks90qajt4jn cert-test.ru.pem 7 seconds ago 7 seconds ago |
Как мы видим, данный секрет доступен на всех мастерах сварм кластера:
1 2 3 4 5 |
[root@<strong>swarm_master3_182 ~]# docker secret ls</strong> ID NAME DRIVER CREATED UPDATED 4rh7oapykk83zbks90qajt4jn cert-test.ru.pem 2 minutes ago 2 minutes ago |
После того, как секрет сохранен в менеджерах Swarm, далее, необходимо добавить его в прокси.
Лучше всего включать сертификаты при создании сервиса. Однако, если proxy
служба уже запущена, то можно обновить её следующим образом:
docker service update --secret-add cert-test.ru.pem proxy_proxy
Docker хранит секретный сертификат во всех контейнерах, которые формируют proxy
сервис.
Запуск Docker Flow Proxy
создаём сеть:
docker network create --driver overlay proxy
создаём директорию где будет храниться файл для данного сервиса:
[root@swarm_master1_180 ~]# mkdir docker-flow-proxy
Мы будем использовать docker-compose-stack.yml из репозитория docker-flow / docker-flow-proxy для создания docker-flow-proxy
и docker-flow-swarm-listener
обслуживания.
Содержание docker-compose-stack.yml (переименуем его в proxy.yml)
файла выглядит следующим образом:
[codesyntax lang="php" blockstate="collapsed"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[root@swarm_master1_180 ~]# cat docker-flow-proxy/proxy.yml version: "3.7" services: proxy: image: dockerflow/docker-flow-proxy secrets: - cert-test.ru.pem ports: - 80:80 - 443:443 networks: - proxy environment: - LISTENER_ADDRESS=swarm-listener - MODE=swarm deploy: replicas: 3 swarm-listener: image: dockerflow/docker-flow-swarm-listener networks: - proxy volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove deploy: placement: constraints: [node.role == manager] networks: proxy: external: true secrets: cert-test.ru.pem: external: true |
[/codesyntax]
Формат написан в версии 3
(обязательно для docker stack deploy
).
Он содержит две службы: proxy
и swarm-listener
proxy
Сеть определяется как external
. Несмотря на то что выполняется командаdocker stack deploy.
default
означает, что сеть будет создана для всех сервисов, которые образуют стек, proxy
сеть должна быть внешней, чтобы мы могли подключать к ней сервисы из других стеков.
secrets: служит для подтягивания секретов, т.е. в них мы скрываем пароли и всю информацию которую нежелательно оставлять в открытом виде:
https://docs.docker.com/engine/swarm/secrets/
cert-test.ru.pem: - название
external: true - указывает на то что он уже создан.
скачиваем:
curl -o docker-compose-stack.yml https://raw.githubusercontent.com/docker-flow/docker-flow-proxy/master/docker-compose-stack.yml
правим(если необходимо что-то подкоректирвоать, например добавить сертификаты)
запускаем:
docker stack deploy -c proxy.yml proxy
в нашем случае запускаем:
[root@swarm_master1_180 ~]# docker stack deploy -c docker-flow-proxy/proxy.yml proxy
проверяем:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[root@swarm_master1_180 ~]# <strong>docker stack ls</strong> NAME SERVICES ORCHESTRATOR proxy 2 Swarm [root@swarm_master1_180 ~]# <strong>docker service ls</strong> ID NAME MODE REPLICAS IMAGE PORTS 29fl8nvzekwe proxy_proxy replicated 3/3 dockerflow/docker-flow-proxy:latest *:80->80/tcp, *:443->443/tcp oyj07sgnsmbd proxy_swarm-listener replicated 1/1 dockerflow/docker-flow-swarm-listener:latest [root@swarm_master1_180 ~]# <strong>docker service ps proxy_proxy</strong> ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS x11xpossozr1 proxy_proxy.1 dockerflow/docker-flow-proxy:latest swarm_master2_181 Running Running 48 seconds ago brib4w88ioxj proxy_proxy.2 dockerflow/docker-flow-proxy:latest swarm_master1_180 Running Running 50 seconds ago gjf1o6t3nvjk proxy_proxy.3 dockerflow/docker-flow-proxy:latest swarm_node3_185 Running Running 47 seconds ago [root@swarm_master1_180 ~]# <strong>docker service ps proxy_swarm-listener</strong> ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 3jbno51lht2p proxy_swarm-listener.1 dockerflow/docker-flow-swarm-listener:latest swarm_master3_182 Running Running about a minute ago |