← Все статьи

Vault Secrets Operator замолчал после seal — и рестарт его не разбудил

38 из 43 VaultStaticSecret два дня висели с замёрзшей ошибкой. Unseal Vault и рестарт оператора ничего не дали; помогло изменение одного поля в spec.

В Optimacros bare-metal кластер Kubernetes получает секреты приложений из Vault через Vault Secrets Operator (VSO). Однажды я заметил, что 38 из 43 объектов VaultStaticSecret примерно двое суток показывают SecretSynced=False.

Замёрзшая ошибка — это не повторяющаяся ошибка

В условии стояло 503 Vault is sealed и back-off horizon 4,939 секунды. Я опросил его несколько раз. Horizon каждый раз был одинаковым до наносекунды. Контроллер, который действительно повторяет попытки, пересчитывает это значение при каждой. Этот не повторял вообще.

Логи оператора это подтверждали: с момента seal — ни строчки. Под был жив, продлевал leader lease и потреблял несколько милликор CPU, но ничего не реконсилил.

Слой первый: один запечатанный узел за Service

У самой 503 причина была простая. Vault работает как Raft-кластер из трёх узлов, и один узел был запечатан. Service vault балансирует на все поды, так что примерно треть чтений VSO попадала на запечатанный узел. Это объясняло и странную смесь: одни секреты синкались, другие нет, чисто по везению round-robin.

Я распечатал узел, все три пода Vault стали ready. Объекты VaultStaticSecret остались False.

Слой второй: умер цикл реконсиляции

Дальше я попробовал два официальных средства: rollout restart оператора и аннотацию force-sync на застрявших объектах. Ни то, ни другое ничего не изменило.

Оказалось, это известный баг VSO, hashicorp/vault-secrets-operator#840. После seal и unseal умирают lifetime watcher’ы отдельных секретов, и ни периодический таймер refreshAfter, ни force-sync не возвращают объекты в очередь. Informer жив, но ничто ничего не ставит в очередь заново.

Будильник: изменить spec

Informer по-прежнему реагирует на изменения spec. Поэтому я поменял spec.refreshAfter у каждого застрявшего объекта. Это порождает watch-событие, запускается реконсиляция, и объект уходит в True. Успешные синки VSO на уровне info не логирует, так что логи молчали и тогда, когда всё сработало; единственным сигналом были условия. Когда всё засинкалось, я вернул исходный refreshAfter вторым патчем.

Это было безопасно, потому что у секретов стоял overwrite: false: будильник починил статус и не переписал существующие данные.

Настоящее исправление в другом месте

Изменение spec — это обходной путь. В этом кластере Vault распечатывался по Shamir без auto-unseal, поэтому каждый рестарт пода Vault запечатывал узел, и каждый seal снова останавливал бы VSO. Настоящие лекарства — обновить VSO до версии с исправлением бага и перевести Vault на auto-unseal, чтобы seal вообще перестал случаться.

Что вынести

  • Сообщение условия, которое не меняется между опросами вплоть до таймингов back-off, — отпечаток мёртвой очереди, а не медленного повтора.
  • Service перед Raft-кластером шлёт трафик и на запечатанные узлы. Смешанный успех на одинаковых объектах часто значит, что часть бэкендов плохая.
  • Если рестарты и аннотации force-sync не помогают, безобидное изменение spec проходит через informer и возвращает объект в очередь.
  • Чини источник: auto-unseal убирает seal, обновление убирает зависание.