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 |