Как стать автором
Обновить

Комментарии 36

Интересная реализация! Есть над чем подумать)

спасибо ^^

После поднятия второго контейнера и исправления файла в nginx старый контейнер убивается. Как в таком случаи поведут себя активные соединения с этим контейнером?
Тот случай, когда запрос может выполнятся 10-20 секунд.

на запросы по 10-20 секунд, конечно, не рассчитано ((
при docker rm -f приложение получит SIGKILL и всё оборвёт. В таком случае, скорее всего лучше явно делать docker stop && docker rm, тогда приложение получит SIGTERM и сможет обработать завершение при наличии необработанных запросов.


А по простому — если известно сколько примерно может длится запрос, можно поднять цифру в sleep на удвоенное время среднего запроса.

Поменял docker rm -f на docker stop. Теперь даже rollback поддерживается. Если после деплоя и ручной проверки выяснилось, что новый контейнер работает хуже старого, можно вернуть старый простым docker start и заменой конфига. Что-нибудь типа такого:


rollback() {
    local image_name=${1?"Usage: ${FUNCNAME[0]} image_name"}

    if get-active-slot $image_name
    then
        local previous_slot=GREEN
        local current_slot=BLUE
    else
        local previous_slot=BLUE
        local current_slot=GREEN
    fi
    docker start ${image_name}_${previous_slot}
    set-active-slot $image_name $previous_slot
    docker stop ${image_name}_${current_slot}
}

Делали подобное. Nginx при команде reload сбрасывает все активные подключения и это не лечится. Если ресурсов не жалко — просто ставим сверху второй и получается совсем бесшовно — проверяли свою реализацию под лоад тестами.

Ого, спасибо за то что поделились опытом, мы только предполагали, что nginx по идее должен подождать ответов на активные запросы. Если есть такая проблема, то наверно можно его настроить на балансирование трафика с коэффициентами до переключения 1:0, а потом 0:1 после переключения. А ещё, мы Traefik пробовали, но он тогда сыроват был и пришлось отказаться из за бага в хелсчеке.


Или он вообще при любом reload сбрасывает, даже при смене коэффициентов?


Тогда это очень странно

> мы только предполагали, что nginx по идее должен подождать ответов на активные запросы
Вот и мы предпологали, но проверили это предположение.

> Или он вообще при любом reload сбрасывает, даже при смене коэффициентов?
При любом reload. Он убивает старые воркеры и поднимает новые, с новым конфигом.
А если поставить nginx перед ним, он сделает retry и для клиента это не будет заметно.

мда, c такими особенностями nginx уже не кажется идеально подходящим на роль балансера или реверс-прокси… Очень полезный опыт, реально спасибо )

Ничего он не убивает, а ждет завершении работы клиента с воркером.

> Nginx при команде reload сбрасывает все активные подключения и это не лечится.

Смотря что подразумевается под активными. Открытые коннекты, в которых не выполняется никакой запрос, он действительно сбрасывает. Однако если какой-то запрос выполняется, то нет.

Я специально потестил: попробовал медленно качать большой файл, и сделать в этот момент reload. Скачка не прервалась, и воркер, на котором остался этот коннект, висит в списке процессов под именем «nginx: worker process is shutting down». Как только скачивание заканчивается, он выходит.
Спасибо. Но у нас коннекты действительно падали, надо разобраться почему.

Это не так, nginx при reload ждёт окончания соединений или отвала по таймауту. При этом запускает новые воркеры для обслуживания новых соединений. Старые воркеры будут остановлены только когда все текущие соединения будут завершены или по таймауту worker_shutdown_timeout

А зачем у вас в тексте цвет, если нужно представлять, как бы это выглядело на «железном» терминале?

это хайлайтеры )) кто-то очень хорошо оформил эти старинные вклейки, чтобы казалось будто смотришь код на цветном телевизоре)

Никто и никогда не смотрел вывод UNIX на цветном телевизоре.
Человек, который мог себе позволить компьютер, на котором запускалась Unix — мог позволить себе и монитор.

Какой-то школьный утренник, честное слово :(

Ну сорян, что не запарился над реконструкторской частью. Ответ что подсвеченный код всё-таки хоть немного удобнее неподсвеченного вас больше устроит? Подсветка, конечно, отстойная тут для bash, может ее действительно лучше и не включать

Сорри, это я Вам в каком-то депрессивном состоянии духа написал, прошу прощения за негатив!

Простите, но зачем велосипеды(сложные), когда blue-green из коробки:
docker service update --image imagename:tag servicename

This is a cluster management command, and must be executed on a swarm manager node.


А swarm мёртв (тащем то сам docker тоже мёртв, а этот скрипт скорее всего нормально на podman работает).
Так то и k8s можно юзать, но это уже не интересно.
Статья показывает как готовить blue-green вручную, а если у Вас есть оркестратор, то там уже всё приготовлено

Docker Swarm — мёртв.
Docker Swarm Mode — живой, из коробки, не требует доп ресурсов и траты времени на баш-костыли.
Для чего вообще подобное может понадобиться, если давно все стараются(должны) унифицировать окружения? Ваши скрипты не поедут в прод, так зачем локально управлять иначе?
Swarm мёртв, k8s сложно — и потом в прод едут велосипеды, я это вижу в 2020.

  1. Это отличная практика баш-скриптинга
  2. Оно может пригодиться в проде как минимум в двух случаях:
    • Частично: например, заменить тяжелый и сложный Ansible на представленный способ параметризованного удалённого выполнения функций в каких-то суперпростых задачах.
    • Полностью: если приложения требуют какой-то сложной логики хелсчека или переключения слотов, а docker swarm это не поддерживает.

Вот, например, https://github.com/p8952/bocker — тоже народ бесполезно время потратил и никому это не надо?

Юзаю docker swarm mode 3 года в прод — полёт отличный, бесшовное обновление контейнеров(при условии нормально настроенного healthcheck), быстрый откат(rollback). А так интересно написанное решение. Спасибо!

Вот за это:
service=${1?$usage_msg}
Спасибо! Не знал и писал отдельную обертку.

Ага, это уже высший эльфийский bash-скриптинга, там ещё очень много всякого можно делать со строками прямо на выводе, и всё это крайне неинтуитивно, сразу же забывается, но чертовски привлекательно )

А что, если:


  1. поднять контейнер приложения с примонтированными файлами
    docker run ... -v /app/current:/var/www ...
  2. любым capistrano like инструментом делать current release методом ссылок
    ln -s /app/current /var/www/releases/100500

Контейнер никогда не останавливается, файлы обновляются. Все довольны.
Ещё больше минималок для blue-green deployment

прикольная идея. Вроде Visual Studio подобным образом делает для отладки в докере. Но опять же подходит далеко не всегда:


  1. Не всё можно обновить таким образом, если надо бампнуть версию самого HTTP сервера, то его всё-таки придётся останавливать. А современные приложения обычно сами себе HTTP сервер (как в примере), и никакого /var/www вообще нету ))
  2. Засорять сервер исходниками вне контейнеров, бэээ. Зачем тогда вообще контейнер, если можно просто HTTP сервер на bare metal поднять и то же самое делать )

Конечно.


По первому пункту: если файлов нет, то сразу в swarm идём и получаем удовольствие.
По второму пункту: нужно обратиться к здравомыслию. Если контейнер используется только как HTTP слой, то можно и самому поднимать nginx и проксировать на файлы, без контейнеров. Но чаще всего, спасение от контейнеров в том, что в нём стоит over 100500 зависимостей для обработки картинок и прочего дерьма, которое сложновато поставить на bare.


ИМХО. Не являюсь носителем истины последней инстанции.

сразу в swarm идём и получаем удовольствие

Было уже про swarm выше. Я честно не знал, что swarm ещё хоть в каком-то виде жив и был немало удивлён тем, что есть некий swarm mode и он вроде как норм. Но вообще, даже есть и так, то swarm — это поделка чисто докера, а докер уже давно мёртв не только как компания, но и как реализация контейнерной технологии. В RHEL-полушарии линуксов уже даже полностью отказались от докера, заменив его на CLI-совместимый podman без центрального демона, работающего от рута, который является очень узким местом. Есть основания полагать, что скоро этот тренд и до Debian-полушария дойдёт, и тогда все точно слезут с докера. А в podman уже нет никакого недооркестратора, только k8s, только хардкор. А этого монстра далеко не везде возможно внедрить...

Разговоры о том, кто мёртв, а кто жив, будут до тех пор, пока наконец-то все не начнут использовать terraform.

Разговоры о том, кто мёртв, а кто жив, будут до тех пор, пока наконец-то все не начнут использовать %MY_FAVORITE_TECH%.

Я про то, что нужно переходить на какой-либо инструмент унификации и не зависеть от технологий.

Я уже добавил дисклеймер про это в конец статьи. Моё мнение, что для подобных штук надо использовать k8s, но я могу ошибаться, так как нормально пощупать k8s у меня ещё не было возможности, к сожалению. Это прям стандарт отрасли сейчас, лучше придерживаться решений такого класса, чтобы не переделывать всё каждые 2 года

НЛО прилетело и опубликовало эту надпись здесь

Как раз для k8s нужен именно демон, который реализует cri интерфейс, podman не реализует cri интерфейс, k8s с ним не работает. На текущий момент их не так много, основных: containerd, docker, cri-o (https://kubernetes.io/docs/setup/production-environment/container-runtimes/). Docker внутри использует containerd, то есть по сути это containerd vs cri-o, и я бы не сказал что cri-o обладает супер преимуществами, чтобы делать выбор в его сторону, более того с ним я испытал больше проблем чем с containerd (от docker). Поэтому считаю сомнительными все эти похороны докера.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации