Thank you for reading this post, don't forget to subscribe!
Есть несколько вариантов обновления конфигов в docker swarm. Рассмотрим простой стек где будет запущен nginx
[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 |
version: '3.4' services: test-nginx: image: nginx hostname: nginx configs: - source: nginx_config #Наш конфиг который мы будем обновлять target: /etc/nginx/conf.d/new.conf #Путь куда необходимо данный конфиг положить healthcheck: test: ["CMD", "service", "nginx", "status"] interval: 10s timeout: 3s retries: 5 networks: - nginx - proxy deploy: mode: replicated replicas: 3 update_config: parallelism: 1 delay: 10s order: start-first labels: - com.df.notify=true - com.df.serviceDomain=nginx.test.ru - com.df.port=80 configs: # здесь описываем наш конфиг nginx_config: # название file: /root/docker-nginx/new.conf # путь до конфига # external: true # данный параметр необходим если конфиг будет создан предварительно вручную networks: nginx: external: true proxy: external: true |
[/codesyntax]
=============================================================================
Все варианты основаны на изменении имени конфига
1, 2 и 3 варианты особо не отличаются:
1 вариант - мы правим имя в стеке
configs:
- source: nginx_config2 #Наш конфиг который мы будем обновлять
target: /etc/nginx/conf.d/new.conf #Путь куда необходимо данный конфиг положить
И
configs: # здесь описываем наш конфиг
nginx_config2: # название
file: /root/docker-nginx/new.conf # путь до конфига
После чего заново деплоим стек:
docker stack deploy -c nginx-stack.yml nginx
2 вариант мы предварительно создаём конфиг:
docker config create nginx_config2 new.conf
Правим имя в стеке:
configs:
- source: nginx_config2 #Наш конфиг который мы будем обновлять
target: /etc/nginx/conf.d/new.conf #Путь куда необходимо данный конфиг положить
И
configs: # здесь описываем наш конфиг
nginx_config2: # название
external: true # будет подтягивать заранее созданный конфиг
После чего заново деплоим стек:
docker stack deploy -c nginx-stack.yml nginx
3 вариант если мы используем ci/cd то добавляем переменную в наш стек:
Оставляем без изменений эту часть:
configs:
- source: nginx_config #Наш конфиг который мы будем обновлять
target: /etc/nginx/conf.d/new.conf #Путь куда необходимо данный конфиг положить
И вносим изменения сюда:
configs: # здесь описываем наш конфиг
nginx_config: # название
name: new.conf-${CI_JOB_ID}
file: /root/docker-nginx/new.conf # путь до конфига
Недостатком использования номера задания является то, что вы будете обновлять конфиги и секреты и их зависимые сервисы при каждом запуске задания
4 вариант обновление конфигов и сервисов без деплоя всего стека.
Смотрим как в системе называются конфиги(при деплое добавляется имя стека)
docker config ls | grep nginx
9v608868r8ov6b9qlvpr0mz52 nginx_nginx_config 5 hours ago 5 hours ago
l1300aj6g60jlqpo0ze2qjx8h nginx_nginx_config2 4 hours ago 4 hours ago
смотрим какой конфиг используется сервисом:
docker service inspect nginx_test-nginx | grep -i configname
"ConfigName": "nginx_nginx_config2"
обновляем сервис удаляя старый конфиг и добавляя новый:
docker service update --config-rm nginx_nginx_config2 --config-add src=nginx_nginx_config3,target=new.conf nginx_test-nginx
target - указывает путь в файлу
nginx_test-nginx - имя сервиса.
=========================================================================================
Docker Secrets
Мы можем запустить команду, чтобы создать Decker-«секрет»:
date |md5sum|awk '{print $1}' | docker secret create my_secret -
> qk4k9adgri6b3ubjua9nca5fp
Созданный «секрет» назван my_secret.
При вводе docker secret ls вы получаете информацию об используемых«секретах» :
> ID NAME CREATED UPDATED
> qk4k9adgri6b3ubjua9nca5fp my_secret About a minute ago About a minute ago
Qk4k9adgri6b3ubjua9nca5fp –
случайный и уникальный идентификатор недавно созданного «секрета».
«Секрет» сохраняется во временную файловую систему (tmpfs) под /run/secrets/my_secret.
Tmpfs — временное хранилище во многих Unix-подобных операционных системах. Файлы хранятся в энергозависимой памяти вместо внешнего устройства хранения данных.
Начнем с создания «секрета»:
date |md5sum|awk '{print $1}' | docker secret create my_new_secret -
После этого старый «секрет» должен быть удален и заменен. Все это делается одной командой:
docker service update --secret-rm my_secret --secret-add source=my_new_secret,target=my_secret my_test_app
========================================================================================
ROLLBACK
Откат образа, конфига.
Рассмотрим настройку стека когда необходим откат конфига (образа) в случае некорректного апдейта, отметим, что версия должна быть 3,7 так как рол бек добавлен в ней: version: '3.7'
Ниже предоставлен стек для примера
[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 40 41 42 43 44 |
cat nginx-stack.yml version: '3.7' services: test-nginx: image: nginx hostname: "nginx-{{.Node.Hostname}}" # добавляет к hostname внутри контейнера "nginx и имя сервера" на котором он запущен configs: - source: nginx_config target: /etc/nginx/conf.d/new.conf healthcheck: test: ["CMD", "service", "nginx", "status"] interval: 5s timeout: 2s retries: 2 networks: - nginx - proxy deploy: mode: replicated replicas: 5 update_config: parallelism: 1 delay: 2s # задержка между обновлениями группы контейнеров order: start-first failure_action: rollback # действие при ошибке обновления (continue, rollback,pause, по умолчанию pause) rollback_config: parallelism: 1 delay: 2s # Задержка между откатами группы контейнеров order: start-first monitor: "2s" # Продолжительность мониторинга на сбой после каждого обновления labels: - com.df.notify=true - com.df.serviceDomain=nginx.test.ru - com.df.port=80 configs: nginx_config: file: /root/docker-nginx/new.conf networks: nginx: external: true proxy: external: true |
[/codesyntax]
Подтягиваемый конфиг:
cat new.conf
1 2 3 4 5 6 7 8 |
server { listen 80; server_name nginx.test.ru <a href="http://www.nginx.test.ru">www.nginx.test.ru</a>; location / { root /usr/share/nginx/html; index index.html index.htm; } } |
Запускаем:
docker stack deploy -c nginx-stack.yml nginx
Проверяем
docker service ps nginx_test-nginx
1 2 3 4 5 6 7 8 9 10 11 |
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 96df6xnyli53 nginx_test-nginx.1 nginx:latest node3 Running Running 21 seconds ago nrlxjnmji13w nginx_test-nginx.2 nginx:latest node1 Running Running 22 seconds ago 29t8eaiueqql nginx_test-nginx.3 nginx:latest node2 Running Running 21 seconds ago j0b889pqoi8y nginx_test-nginx.4 nginx:latest node3 Running Running 21 seconds ago s148hhtq6c8a nginx_test-nginx.5 nginx:latest node2 Running Running 21 seconds ago |
Для этого же стека меняем образ с nginx на httpd (соответственно healthcheck не сможет нормально проверить статус nginx и будет возвращать ошибку)
cat nginx-stack.yml | grep image
image: httpd
Апдейтим:
docker stack deploy -c nginx-stack.yml nginx
Проверяем:
docker service ps nginx_test-nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 96df6xnyli53 nginx_test-nginx.1 nginx:latest node3 Running Running 6 minutes ago nrlxjnmji13w nginx_test-nginx.2 nginx:latest node1 Running Running 6 minutes ago kgwibu8hblf7 nginx_test-nginx.3 <b>httpd</b>:latest node1 <b>Shutdown</b> Shutdown 5 seconds ago 7w5edt4311y2 \_ nginx_test-nginx.3 <b>httpd</b>:latest node1 <b>Shutdown</b> Complete 7 seconds ago 29t8eaiueqql \_ <b>nginx_test-nginx.3 nginx:latest node2 Running</b> Running 6 minutes ago j0b889pqoi8y nginx_test-nginx.4 nginx:latest node3 Running Running 6 minutes ago s148hhtq6c8a nginx_test-nginx.5 nginx:latest node2 Running Running 6 minutes ago |
Как мы видим, на одной из реплик образ попытался запуститься, хелсчек не прошёл и образ вернулся на nginx, такой процесс прошёл только на одной реплике потому что мы указали в update_config: parallelism: 1
Вернём правильный образ на nginx и испортим конфиг файл nginx чтобы он не смог запуститься:
cat nginx-stack.yml | grep -E 'conf|image' | grep -vE 'update_|rollback_'
image: nginx
configs:
- source: nginx_config2
target: /etc/nginx/conf.d/new.conf
configs:
nginx_config2:
file: /root/docker-nginx/fail.conf
В конфиге nginx мы убрали закрывающуюся скобку:
cat fail.conf
1 2 3 4 5 6 7 |
server { listen 80; server_name nginx.test.ru <a href="http://www.nginx.test.ru">www.nginx.test.ru</a>; location / { root /usr/share/nginx/html; index index.html index.htm; } |
Запускаем апдейт:
docker stack deploy -c nginx-stack.yml nginx
Creating config nginx_nginx_config2
Updating service nginx_test-nginx (id: 4u7fvnd65mkg0hmvwqw5rrf2a)
Проверяем:
docker service ps nginx_test-nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS tusw4tgqn9a3 nginx_test-nginx.1 nginx:latest node3 Running Running 19 minutes ago nkli1a7kogk1 nginx_test-nginx.2 nginx:latest node1 Running Running 19 minutes ago oivacnavj5cs nginx_test-nginx.3 nginx:latest node2 Running Running 19 minutes ago rt8bqp1t5w3z <b> nginx_test-nginx.4</b> nginx:latest node1 <b>Shutdown</b> Shutdown 2 minutes ago qrly61r8sy43 \_ <b>nginx_test-nginx.4</b> nginx:latest node1 <b>Shutdown</b> Failed 2 minutes ago "task: non-zero exit (1)" tvxfnd6ae7qu \_ <b>nginx_test-nginx.4 nginx:latest node3 Running Running 18 minutes ago</b> y7323rbdosbo nginx_test-nginx.5 nginx:latest node2 Running Running 19 minutes ago |
Как видим, контейнер попытался про апдейтиться но не вышло и он откатил старый конфиг, остальные контейнеры так же не были затронуты потому, что мы указали в update_config: parallelism: 1