docker swarm. Docker Flow Proxy

Thank you for reading this post, don't forget to subscribe!
Прок­си-сер­вер Docker Flow явля­ет­ся обрат­ным прок­си-сер­ве­ром для кон­тей­не­ров Docker.

Прок­си-сер­вер 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"]

[/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
В резуль­та­те, у нас есть crtcsrи 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

 

Как мы видим, дан­ный сек­рет досту­пен на всех масте­рах сварм кластера:

После того, как сек­рет сохра­нен в мене­дже­рах 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"]

[/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
проверяем: