Helm пишет «another operation is in progress», а ничего не запущено
Отменённая CI-джоба оставила два Helm-релиза в pending-upgrade и заблокировала все деплои. Как найти lock, безопасно его снять и проверить весь namespace разом.
Однажды утром в Gambchamp деплой-джобы двух бэкенд-сервисов покраснели одновременно. Обе упали с одной и той же строкой:
Error: UPGRADE FAILED: another operation (install/upgrade/rollback) is in progress
При этом никто ничего не деплоил. Ни один пайплайн не шёл, ни у кого не было открытого терминала к этому namespace. А Helm настаивал, что какая-то операция идёт.
Первая гипотеза и почему она не подтвердилась
Когда два сервиса падают вместе, обычно подозреваешь общую зависимость: реестр образов, API кластера, раннер. Их мы и проверили первыми. API отвечал, образы тянулись, другие релизы в других namespace деплоились нормально. Сбой касался только этих двух релизов, и общее у них было одно: их деплоит одна и та же группа пайплайнов в один и тот же namespace.
Что Helm на самом деле помнит
Helm хранит состояние каждой ревизии релиза как Secret в namespace релиза. Статус лежит в лейбле: deployed, superseded, failed — или pending-install, pending-upgrade, pending-rollback. Ревизия в pending-* — это и есть lock Helm. Пока она существует, любой новый helm upgrade для этого релиза отказывается стартовать.
helm history показал ровно это: последняя ревизия обоих релизов была в pending-upgrade, и обе создались в одну и ту же минуту.
Таймстемп всё объяснил. Предыдущий деплой отменили (или он упёрся в таймаут) посреди helm upgrade --atomic. --atomic обещает автоматический откат при ошибке, но только если процесс Helm доживёт до этого отката. Убейте джобу на полпути — и отката не будет. Lock остаётся, и каждый следующий деплой в него упирается.
Решение
Lock снимается откатом на последнюю ревизию, которая действительно прошла успешно:
helm history <release> -n <ns> # найти последнюю ревизию "deployed"
helm rollback <release> <rev> -n <ns> # откат на неё снимает pending-lock
После отката повтор CI-джобы прошёл штатно. Раз два релиза замёрзли в одну минуту, чинить их по одному и пропустить третий мы не хотели. Один запрос показывает все зависшие релизы в namespace:
kubectl -n <ns> get secret -l owner=helm -o json \
| jq -r '.items[] | select(.metadata.labels.status | test("pending"))
| "\(.metadata.labels.name) rev=\(.metadata.labels.version) status=\(.metadata.labels.status)"'
Выводы
another operation is in progressпочти всегда означает ревизию вpending-*. Начинайте сhelm history, а не с сети.--atomic— не гарантия. Он откатывает, только если Helm доработал до конца; отменённая джоба оставляет lock.- Несколько релизов, зависших с одинаковым таймстемпом, — это один инцидент: оборванный пакетный деплой или умерший раннер. Проверяйте весь namespace, а не чините релизы по одному.
- Откатывайтесь на последнюю
deployed-ревизию, а не удаляйте Secret’ы релиза руками: это обратимо и сохраняет историю Helm целостной.