использование configs и secrets в Swarm

Thank you for reading this post, don't forget to subscribe!

Начи­ная с вер­сии 17.06 — у Docker Swarm появи­лась под­держ­ка новой кон­цеп­ции хра­не­ния и под­клю­че­ния фай­лов настро­ек для сер­ви­сов — configs.

А ещё ранее, с вер­сии 1.13 — secrets, для хра­не­ния и пере­да­чи зашиф­ро­ван­ных дан­ных меж­ду мене­дже­ра­ми и нодами.

Ниже — опи­са­ние и при­ме­не­ние secrets и configs в Docker Swarm.

Docker configs

Swarm service configs поз­во­ля­ет хра­нить некри­тич­ные дан­ные, такие как фай­лы кон­фи­гу­ра­ции, вне docker-обра­за или кон­тей­не­ра: вме­сто того, что бы под­клю­чать файл настро­ек через volume (-v) или пере­да­вать пере­мен­ные с пара­мет­ра­ми — вы може­те создать объ­ект кон­фи­га и под­клю­чить его напря­мую к фай­ло­вой систе­ме в созда­ва­е­мом сервисе/контейнере.

Когда вы созда­ё­те такой config — Docker отправ­ля­ет его на manager-ноду кла­сте­ра по TLS, где он хра­нит­ся в зашиф­ро­ван­ных Raft логах (/var/lib/docker/swarm/raft), кото­рые реп­ли­ци­ру­ют­ся по всем мене­дже­рам swarm-а.

Когда вы даё­те доступ к кон­фи­гу для ново­го или уже запу­щен­но­го сер­ви­са в Swarm — он мон­ти­ру­ет­ся в фай­ло­вую систе­му кон­тей­не­ра, по умол­ча­нию для Linux это будет /<config_name>.

Вы може­те так же ото­звать доступ к кон­фи­гу или доба­вить допол­ни­тель­ный в любой момент.

Создание configs

Создать кон­фиг очень про­сто, напри­мер — созда­дим файл настро­ек вир­ту­ал­хо­ста для NGINX:

Созда­ём объ­ект Docker config:
docker config create vhost_nginx nginx_vhost.conf

про­ве­ря­ем:

docker config ls
ID                          NAME                CREATED             UPDATED
i7ckjge352lvght06qr8dzonc   vhost_nginx         15 seconds ago      15 seconds ago
Про­смот­реть его содержимое:
docker config inspect vhost_nginx --pretty
ID:                     i7ckjge352lvght06qr8dzonc
Name:                   vhost_nginx
Created at:             2017-11-15 12:09:50.035131215 +0000 utc
Updated at:             2017-11-15 12:09:50.035131215 +0000 utc
Data:
server {
listen 80;
root /usr/share/nginx/html/;
index index.html index.htm index.nginx-debian.html;
server_name dc-swarm.local;
location / {
try_files $uri $uri/ =404;
}
}

Теперь мож­но уда­лить исход­ный файл, и исполь­зо­вать создан­ный конфиг.

Применение configs

Обнов­ля­ем сер­вис, под­клю­ча­ем конфиг:

docker service update --config-add vhost_nginx nginx
nginx
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
Про­ве­ря­ем
docker exec -ti 2ca2986076ef cat /vhost_nginx
server {
listen 80;
root /usr/share/nginx/html/;
index index.html index.htm index.nginx-debian.html;
server_name dc-swarm.local;
location / {
try_files $uri $uri/ =404;
}
}
Что бы под­клю­чить кон­фиг в опре­де­лён­ный ката­лог — исполь­зу­ем src и target:
docker service update --config-add src=vhost_nginx,target="/etc/nginx/conf.d/dc-swarm.local.conf" nginx
nginx
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
Про­ве­ря­ем
 docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') ls -l /etc/nginx/conf.d
total 8
-r--r--r-- 1 root root  242 Nov 15 12:25 dc-swarm.local.conf
-rw-r--r-- 1 root root 1093 Sep 14 16:35 default.conf

Обновление configs

Обнов­ля­ем настрой­ки вир­ту­ал­хо­ста — поме­ня­ем индекс­ный файл:

Созда­ём кон­фиг с име­нем vhost_nginx_v2:

docker config create vhost_nginx_v2 nginx_vhost.conf

Отклю­ча­ем кон­фиг от сервиса:

docker service update --config-rm vhost_nginx nginx
nginx
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
Уда­ля­ем ста­рый кон­фиг из Swarm:
docker config rm vhost_nginx
vhost_nginx
Про­ве­ря­ем
docker config ls
ID                          NAME                CREATED              UPDATED
4ych3x1inktdkuqfz6q9hklby   dc_index            5 minutes ago        5 minutes ago
h13yug0d1jfcmdznosttyvqbp   vhost_nginx_v2      About a minute ago   About a minute ago
Под­клю­ча­ем новый, v2:
docker service update --config-add src=vhost_nginx_v2,target="/etc/nginx/conf.d/dc-swarm.local.conf" nginx
nginx
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

Docker secrets

secrets — это дан­ные, напри­мер пароль или SSH ключ, кото­рые не долж­ны хра­нить­ся в откры­том виде в Dockerfile и не долж­ны пере­да­вать­ся в таком виде  по сети.

Глав­ное отли­чие secrets от configs это то, что configs под­клю­ча­ют­ся к фай­ло­вой систе­ме кон­тей­не­ра, тогда как secrets — мон­ти­ру­ют­ся в память (/run/).

Когда вы явно ука­зы­ва­е­те доступ к сек­ре­ту для сер­ви­са или кон­тей­не­ра — по умол­ча­нию он будет поме­щён в /run/secrets/<secret_name>.

Создание secrets

Созда­ём новый «сек­рет»:

echo "password" > pwd.txt

docker secret create pwd pwd.txt
urgibv1kmkz3o3850n8msc0ej
Про­ве­ря­ем
 docker secret ls
ID                          NAME                DRIVER              CREATED              UPDATED
urgibv1kmkz3o3850n8msc0ej   pwd                                     About a minute ago   About a minute ago
Даём доступ к это­му сек­ре­ту для сер­ви­са nginx:
docker service update --secret-add pwd nginx
ID                          NAME                DRIVER              CREATED              UPDATED
urgibv1kmkz3o3850n8msc0ej   pwd                                     About a minute ago   About a minute ago
Про­ве­ря­ем /var/run/secrets в контейнере:
docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') ls -l /var/run/secrets
total 4
-r--r--r-- 1 root root 9 Nov 15 14:37 pwd
И содер­жи­мое файла:
docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') cat /var/run/secrets/pwd
password

Ана­ло­гич­но с configs — мож­но ука­зать точ­ку монтирования.

Отклю­ча­ем сек­рет от контейнера:

docker service update --secret-rm pwd nginx
nginx
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
И под­клю­ча­ем его в /etc/pwd:
docker service update --secret-add src=pwd,target="/etc/pwd" nginx
nginx
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
Про­ве­ря­ем
 docker exec -ti $(docker ps | tail -n 1 | awk '{print $1}') cat /etc/pwd
password

Docker secrets vs configs

Как гово­ри­лось, основ­ная раз­ни­ца в том, что configs при под­клю­че­нии к кон­тей­не­ру ста­но­вит­ся частью фай­ло­вой систе­мы, тогда как secret — поме­ща­ет­ся в памяти.

Про­ве­рить это мож­но сде­лав новый образ запу­щен­но­го контейнера.

Сей­час у нас есть сер­вис nginx к кото­ро­му под­клю­чен config dc_index и vhost_nginx_v2, и secret — pwd:

[codesyntax lang="php" blockstate="collapsed"]

[/codesyntax]

Созда­ём новый образ из это­го запу­щен­но­го контейнера:

docker commit $(docker ps | tail -n 1 | awk '{print $1}') nginx_copy

Про­ве­ря­ем образы:

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx_copy          latest              4987a44e0708        16 seconds ago      108MB
nginx               <none>              40960efd7b8f        10 days ago         108MB
Запус­ка­ем новый кон­тей­нер из создан­но­го образа:
docker run -tid --name=nginx_copy nginx_copy
Про­ве­ря­ем фай­лы configs:
docker exec -ti nginx_copy ls -l /etc/nginx/conf.d
total 4
-rwxr-xr-x 1 root root    0 Nov 15 14:40 dc-swarm.local.conf
-rw-r--r-- 1 root root 1093 Sep 14 16:35 default.conf
ОК — на месте.
И secret
docker exec -ti nginx_copy ls -l /run/
total 12
drwxrwxrwt 2 root root 4096 Oct  9 00:00 lock
drwxr-xr-x 2 root root 4096 Oct  9 00:00 mount
-rw-r--r-- 1 root root    2 Nov 15 15:11 nginx.pid
-rw-rw-r-- 1 root utmp    0 Oct  9 00:00 utmp
пусто

Docker secrets и configs в Compose

Что бы исполь­зо­вать secrets и configs в Compose фай­ле — исполь­зу­ем configs и secrets:

[codesyntax lang="php" blockstate="collapsed"]

[/codesyntax]

Созда­ём стек:

docker stack deploy -c compose_secrets_configs.yml nginx
Creating service nginx_nginx
Про­ве­ря­ем

[codesyntax lang="php" blockstate="expanded"]

[/codesyntax]